]> bbs.cooldavid.org Git - net-next-2.6.git/blob - security/tomoyo/file.c
df3b203d7d4f486d6ba9d7a42610d5d02b26800f
[net-next-2.6.git] / security / tomoyo / file.c
1 /*
2  * security/tomoyo/file.c
3  *
4  * Pathname restriction functions.
5  *
6  * Copyright (C) 2005-2010  NTT DATA CORPORATION
7  */
8
9 #include "common.h"
10 #include <linux/slab.h>
11
12 /* Keyword array for operations with one pathname. */
13 const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = {
14         [TOMOYO_TYPE_READ_WRITE] = "read/write",
15         [TOMOYO_TYPE_EXECUTE]    = "execute",
16         [TOMOYO_TYPE_READ]       = "read",
17         [TOMOYO_TYPE_WRITE]      = "write",
18         [TOMOYO_TYPE_UNLINK]     = "unlink",
19         [TOMOYO_TYPE_RMDIR]      = "rmdir",
20         [TOMOYO_TYPE_TRUNCATE]   = "truncate",
21         [TOMOYO_TYPE_SYMLINK]    = "symlink",
22         [TOMOYO_TYPE_REWRITE]    = "rewrite",
23         [TOMOYO_TYPE_CHROOT]     = "chroot",
24         [TOMOYO_TYPE_UMOUNT]     = "unmount",
25 };
26
27 /* Keyword array for operations with one pathname and three numbers. */
28 const char *tomoyo_mkdev_keyword[TOMOYO_MAX_MKDEV_OPERATION] = {
29         [TOMOYO_TYPE_MKBLOCK]    = "mkblock",
30         [TOMOYO_TYPE_MKCHAR]     = "mkchar",
31 };
32
33 /* Keyword array for operations with two pathnames. */
34 const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = {
35         [TOMOYO_TYPE_LINK]       = "link",
36         [TOMOYO_TYPE_RENAME]     = "rename",
37         [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root",
38 };
39
40 /* Keyword array for operations with one pathname and one number. */
41 const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
42         [TOMOYO_TYPE_CREATE]     = "create",
43         [TOMOYO_TYPE_MKDIR]      = "mkdir",
44         [TOMOYO_TYPE_MKFIFO]     = "mkfifo",
45         [TOMOYO_TYPE_MKSOCK]     = "mksock",
46         [TOMOYO_TYPE_IOCTL]      = "ioctl",
47         [TOMOYO_TYPE_CHMOD]      = "chmod",
48         [TOMOYO_TYPE_CHOWN]      = "chown",
49         [TOMOYO_TYPE_CHGRP]      = "chgrp",
50 };
51
52 static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
53         [TOMOYO_TYPE_READ_WRITE] = TOMOYO_MAC_FILE_OPEN,
54         [TOMOYO_TYPE_EXECUTE]    = TOMOYO_MAC_FILE_EXECUTE,
55         [TOMOYO_TYPE_READ]       = TOMOYO_MAC_FILE_OPEN,
56         [TOMOYO_TYPE_WRITE]      = TOMOYO_MAC_FILE_OPEN,
57         [TOMOYO_TYPE_UNLINK]     = TOMOYO_MAC_FILE_UNLINK,
58         [TOMOYO_TYPE_RMDIR]      = TOMOYO_MAC_FILE_RMDIR,
59         [TOMOYO_TYPE_TRUNCATE]   = TOMOYO_MAC_FILE_TRUNCATE,
60         [TOMOYO_TYPE_SYMLINK]    = TOMOYO_MAC_FILE_SYMLINK,
61         [TOMOYO_TYPE_REWRITE]    = TOMOYO_MAC_FILE_REWRITE,
62         [TOMOYO_TYPE_CHROOT]     = TOMOYO_MAC_FILE_CHROOT,
63         [TOMOYO_TYPE_UMOUNT]     = TOMOYO_MAC_FILE_UMOUNT,
64 };
65
66 static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
67         [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK,
68         [TOMOYO_TYPE_MKCHAR]  = TOMOYO_MAC_FILE_MKCHAR,
69 };
70
71 static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
72         [TOMOYO_TYPE_LINK]       = TOMOYO_MAC_FILE_LINK,
73         [TOMOYO_TYPE_RENAME]     = TOMOYO_MAC_FILE_RENAME,
74         [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT,
75 };
76
77 static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
78         [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE,
79         [TOMOYO_TYPE_MKDIR]  = TOMOYO_MAC_FILE_MKDIR,
80         [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO,
81         [TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK,
82         [TOMOYO_TYPE_IOCTL]  = TOMOYO_MAC_FILE_IOCTL,
83         [TOMOYO_TYPE_CHMOD]  = TOMOYO_MAC_FILE_CHMOD,
84         [TOMOYO_TYPE_CHOWN]  = TOMOYO_MAC_FILE_CHOWN,
85         [TOMOYO_TYPE_CHGRP]  = TOMOYO_MAC_FILE_CHGRP,
86 };
87
88 void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
89 {
90         if (!ptr)
91                 return;
92         if (ptr->is_group)
93                 tomoyo_put_group(ptr->group);
94         else
95                 tomoyo_put_name(ptr->filename);
96 }
97
98 bool tomoyo_compare_name_union(const struct tomoyo_path_info *name,
99                                const struct tomoyo_name_union *ptr)
100 {
101         if (ptr->is_group)
102                 return tomoyo_path_matches_group(name, ptr->group);
103         return tomoyo_path_matches_pattern(name, ptr->filename);
104 }
105
106 void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
107 {
108         if (ptr && ptr->is_group)
109                 tomoyo_put_group(ptr->group);
110 }
111
112 bool tomoyo_compare_number_union(const unsigned long value,
113                                  const struct tomoyo_number_union *ptr)
114 {
115         if (ptr->is_group)
116                 return tomoyo_number_matches_group(value, value, ptr->group);
117         return value >= ptr->values[0] && value <= ptr->values[1];
118 }
119
120 static void tomoyo_add_slash(struct tomoyo_path_info *buf)
121 {
122         if (buf->is_dir)
123                 return;
124         /*
125          * This is OK because tomoyo_encode() reserves space for appending "/".
126          */
127         strcat((char *) buf->name, "/");
128         tomoyo_fill_path_info(buf);
129 }
130
131 /**
132  * tomoyo_strendswith - Check whether the token ends with the given token.
133  *
134  * @name: The token to check.
135  * @tail: The token to find.
136  *
137  * Returns true if @name ends with @tail, false otherwise.
138  */
139 static bool tomoyo_strendswith(const char *name, const char *tail)
140 {
141         int len;
142
143         if (!name || !tail)
144                 return false;
145         len = strlen(name) - strlen(tail);
146         return len >= 0 && !strcmp(name + len, tail);
147 }
148
149 /**
150  * tomoyo_get_realpath - Get realpath.
151  *
152  * @buf:  Pointer to "struct tomoyo_path_info".
153  * @path: Pointer to "struct path".
154  *
155  * Returns true on success, false otherwise.
156  */
157 static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path)
158 {
159         buf->name = tomoyo_realpath_from_path(path);
160         if (buf->name) {
161                 tomoyo_fill_path_info(buf);
162                 return true;
163         }
164         return false;
165 }
166
167 /**
168  * tomoyo_audit_path_log - Audit path request log.
169  *
170  * @r: Pointer to "struct tomoyo_request_info".
171  *
172  * Returns 0 on success, negative value otherwise.
173  */
174 static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
175 {
176         const char *operation = tomoyo_path_keyword[r->param.path.operation];
177         const struct tomoyo_path_info *filename = r->param.path.filename;
178         if (r->granted)
179                 return 0;
180         tomoyo_warn_log(r, "%s %s", operation, filename->name);
181         return tomoyo_supervisor(r, "allow_%s %s\n", operation,
182                                  tomoyo_file_pattern(filename));
183 }
184
185 /**
186  * tomoyo_audit_path2_log - Audit path/path request log.
187  *
188  * @r: Pointer to "struct tomoyo_request_info".
189  *
190  * Returns 0 on success, negative value otherwise.
191  */
192 static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
193 {
194         const char *operation = tomoyo_path2_keyword[r->param.path2.operation];
195         const struct tomoyo_path_info *filename1 = r->param.path2.filename1;
196         const struct tomoyo_path_info *filename2 = r->param.path2.filename2;
197         if (r->granted)
198                 return 0;
199         tomoyo_warn_log(r, "%s %s %s", operation, filename1->name,
200                         filename2->name);
201         return tomoyo_supervisor(r, "allow_%s %s %s\n", operation,
202                                  tomoyo_file_pattern(filename1),
203                                  tomoyo_file_pattern(filename2));
204 }
205
206 /**
207  * tomoyo_audit_mkdev_log - Audit path/number/number/number request log.
208  *
209  * @r: Pointer to "struct tomoyo_request_info".
210  *
211  * Returns 0 on success, negative value otherwise.
212  */
213 static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r)
214 {
215         const char *operation = tomoyo_mkdev_keyword[r->param.mkdev.operation];
216         const struct tomoyo_path_info *filename = r->param.mkdev.filename;
217         const unsigned int major = r->param.mkdev.major;
218         const unsigned int minor = r->param.mkdev.minor;
219         const unsigned int mode = r->param.mkdev.mode;
220         if (r->granted)
221                 return 0;
222         tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode,
223                         major, minor);
224         return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation,
225                                  tomoyo_file_pattern(filename), mode, major,
226                                  minor);
227 }
228
229 /**
230  * tomoyo_audit_path_number_log - Audit path/number request log.
231  *
232  * @r:     Pointer to "struct tomoyo_request_info".
233  * @error: Error code.
234  *
235  * Returns 0 on success, negative value otherwise.
236  */
237 static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
238 {
239         const u8 type = r->param.path_number.operation;
240         u8 radix;
241         const struct tomoyo_path_info *filename = r->param.path_number.filename;
242         const char *operation = tomoyo_path_number_keyword[type];
243         char buffer[64];
244         if (r->granted)
245                 return 0;
246         switch (type) {
247         case TOMOYO_TYPE_CREATE:
248         case TOMOYO_TYPE_MKDIR:
249         case TOMOYO_TYPE_MKFIFO:
250         case TOMOYO_TYPE_MKSOCK:
251         case TOMOYO_TYPE_CHMOD:
252                 radix = TOMOYO_VALUE_TYPE_OCTAL;
253                 break;
254         case TOMOYO_TYPE_IOCTL:
255                 radix = TOMOYO_VALUE_TYPE_HEXADECIMAL;
256                 break;
257         default:
258                 radix = TOMOYO_VALUE_TYPE_DECIMAL;
259                 break;
260         }
261         tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number,
262                            radix);
263         tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer);
264         return tomoyo_supervisor(r, "allow_%s %s %s\n", operation,
265                                  tomoyo_file_pattern(filename), buffer);
266 }
267
268 static bool tomoyo_same_globally_readable(const struct tomoyo_acl_head *a,
269                                           const struct tomoyo_acl_head *b)
270 {
271         return container_of(a, struct tomoyo_globally_readable_file_entry,
272                             head)->filename ==
273                 container_of(b, struct tomoyo_globally_readable_file_entry,
274                              head)->filename;
275 }
276
277 /**
278  * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list.
279  *
280  * @filename:  Filename unconditionally permitted to open() for reading.
281  * @is_delete: True if it is a delete request.
282  *
283  * Returns 0 on success, negative value otherwise.
284  *
285  * Caller holds tomoyo_read_lock().
286  */
287 static int tomoyo_update_globally_readable_entry(const char *filename,
288                                                  const bool is_delete)
289 {
290         struct tomoyo_globally_readable_file_entry e = { };
291         int error;
292
293         if (!tomoyo_correct_word(filename))
294                 return -EINVAL;
295         e.filename = tomoyo_get_name(filename);
296         if (!e.filename)
297                 return -ENOMEM;
298         error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
299                                      &tomoyo_policy_list
300                                      [TOMOYO_ID_GLOBALLY_READABLE],
301                                      tomoyo_same_globally_readable);
302         tomoyo_put_name(e.filename);
303         return error;
304 }
305
306 /**
307  * tomoyo_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading.
308  *
309  * @filename: The filename to check.
310  *
311  * Returns true if any domain can open @filename for reading, false otherwise.
312  *
313  * Caller holds tomoyo_read_lock().
314  */
315 static bool tomoyo_globally_readable_file(const struct tomoyo_path_info *
316                                              filename)
317 {
318         struct tomoyo_globally_readable_file_entry *ptr;
319         bool found = false;
320
321         list_for_each_entry_rcu(ptr, &tomoyo_policy_list
322                                 [TOMOYO_ID_GLOBALLY_READABLE], head.list) {
323                 if (!ptr->head.is_deleted &&
324                     tomoyo_path_matches_pattern(filename, ptr->filename)) {
325                         found = true;
326                         break;
327                 }
328         }
329         return found;
330 }
331
332 /**
333  * tomoyo_write_globally_readable_policy - Write "struct tomoyo_globally_readable_file_entry" list.
334  *
335  * @data:      String to parse.
336  * @is_delete: True if it is a delete request.
337  *
338  * Returns 0 on success, negative value otherwise.
339  *
340  * Caller holds tomoyo_read_lock().
341  */
342 int tomoyo_write_globally_readable_policy(char *data, const bool is_delete)
343 {
344         return tomoyo_update_globally_readable_entry(data, is_delete);
345 }
346
347 /**
348  * tomoyo_read_globally_readable_policy - Read "struct tomoyo_globally_readable_file_entry" list.
349  *
350  * @head: Pointer to "struct tomoyo_io_buffer".
351  *
352  * Returns true on success, false otherwise.
353  *
354  * Caller holds tomoyo_read_lock().
355  */
356 bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
357 {
358         struct list_head *pos;
359         bool done = true;
360
361         list_for_each_cookie(pos, head->read_var2,
362                              &tomoyo_policy_list[TOMOYO_ID_GLOBALLY_READABLE]) {
363                 struct tomoyo_globally_readable_file_entry *ptr;
364                 ptr = list_entry(pos,
365                                  struct tomoyo_globally_readable_file_entry,
366                                  head.list);
367                 if (ptr->head.is_deleted)
368                         continue;
369                 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_READ "%s\n",
370                                         ptr->filename->name);
371                 if (!done)
372                         break;
373         }
374         return done;
375 }
376
377 static bool tomoyo_same_pattern(const struct tomoyo_acl_head *a,
378                                 const struct tomoyo_acl_head *b)
379 {
380         return container_of(a, struct tomoyo_pattern_entry, head)->pattern ==
381                 container_of(b, struct tomoyo_pattern_entry, head)->pattern;
382 }
383
384 /**
385  * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list.
386  *
387  * @pattern:   Pathname pattern.
388  * @is_delete: True if it is a delete request.
389  *
390  * Returns 0 on success, negative value otherwise.
391  *
392  * Caller holds tomoyo_read_lock().
393  */
394 static int tomoyo_update_file_pattern_entry(const char *pattern,
395                                             const bool is_delete)
396 {
397         struct tomoyo_pattern_entry e = { };
398         int error;
399
400         if (!tomoyo_correct_word(pattern))
401                 return -EINVAL;
402         e.pattern = tomoyo_get_name(pattern);
403         if (!e.pattern)
404                 return -ENOMEM;
405         error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
406                                      &tomoyo_policy_list[TOMOYO_ID_PATTERN],
407                                      tomoyo_same_pattern);
408         tomoyo_put_name(e.pattern);
409         return error;
410 }
411
412 /**
413  * tomoyo_file_pattern - Get patterned pathname.
414  *
415  * @filename: The filename to find patterned pathname.
416  *
417  * Returns pointer to pathname pattern if matched, @filename otherwise.
418  *
419  * Caller holds tomoyo_read_lock().
420  */
421 const char *tomoyo_file_pattern(const struct tomoyo_path_info *filename)
422 {
423         struct tomoyo_pattern_entry *ptr;
424         const struct tomoyo_path_info *pattern = NULL;
425
426         list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_PATTERN],
427                                 head.list) {
428                 if (ptr->head.is_deleted)
429                         continue;
430                 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
431                         continue;
432                 pattern = ptr->pattern;
433                 if (tomoyo_strendswith(pattern->name, "/\\*")) {
434                         /* Do nothing. Try to find the better match. */
435                 } else {
436                         /* This would be the better match. Use this. */
437                         break;
438                 }
439         }
440         if (pattern)
441                 filename = pattern;
442         return filename->name;
443 }
444
445 /**
446  * tomoyo_write_pattern_policy - Write "struct tomoyo_pattern_entry" list.
447  *
448  * @data:      String to parse.
449  * @is_delete: True if it is a delete request.
450  *
451  * Returns 0 on success, negative value otherwise.
452  *
453  * Caller holds tomoyo_read_lock().
454  */
455 int tomoyo_write_pattern_policy(char *data, const bool is_delete)
456 {
457         return tomoyo_update_file_pattern_entry(data, is_delete);
458 }
459
460 /**
461  * tomoyo_read_file_pattern - Read "struct tomoyo_pattern_entry" list.
462  *
463  * @head: Pointer to "struct tomoyo_io_buffer".
464  *
465  * Returns true on success, false otherwise.
466  *
467  * Caller holds tomoyo_read_lock().
468  */
469 bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
470 {
471         struct list_head *pos;
472         bool done = true;
473
474         list_for_each_cookie(pos, head->read_var2,
475                              &tomoyo_policy_list[TOMOYO_ID_PATTERN]) {
476                 struct tomoyo_pattern_entry *ptr;
477                 ptr = list_entry(pos, struct tomoyo_pattern_entry, head.list);
478                 if (ptr->head.is_deleted)
479                         continue;
480                 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_FILE_PATTERN
481                                         "%s\n", ptr->pattern->name);
482                 if (!done)
483                         break;
484         }
485         return done;
486 }
487
488 static bool tomoyo_same_no_rewrite(const struct tomoyo_acl_head *a,
489                                    const struct tomoyo_acl_head *b)
490 {
491         return container_of(a, struct tomoyo_no_rewrite_entry, head)->pattern
492                 == container_of(b, struct tomoyo_no_rewrite_entry, head)
493                 ->pattern;
494 }
495
496 /**
497  * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list.
498  *
499  * @pattern:   Pathname pattern that are not rewritable by default.
500  * @is_delete: True if it is a delete request.
501  *
502  * Returns 0 on success, negative value otherwise.
503  *
504  * Caller holds tomoyo_read_lock().
505  */
506 static int tomoyo_update_no_rewrite_entry(const char *pattern,
507                                           const bool is_delete)
508 {
509         struct tomoyo_no_rewrite_entry e = { };
510         int error;
511
512         if (!tomoyo_correct_word(pattern))
513                 return -EINVAL;
514         e.pattern = tomoyo_get_name(pattern);
515         if (!e.pattern)
516                 return -ENOMEM;
517         error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
518                                      &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE],
519                                      tomoyo_same_no_rewrite);
520         tomoyo_put_name(e.pattern);
521         return error;
522 }
523
524 /**
525  * tomoyo_no_rewrite_file - Check if the given pathname is not permitted to be rewrited.
526  *
527  * @filename: Filename to check.
528  *
529  * Returns true if @filename is specified by "deny_rewrite" directive,
530  * false otherwise.
531  *
532  * Caller holds tomoyo_read_lock().
533  */
534 static bool tomoyo_no_rewrite_file(const struct tomoyo_path_info *filename)
535 {
536         struct tomoyo_no_rewrite_entry *ptr;
537         bool found = false;
538
539         list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE],
540                                 head.list) {
541                 if (ptr->head.is_deleted)
542                         continue;
543                 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
544                         continue;
545                 found = true;
546                 break;
547         }
548         return found;
549 }
550
551 /**
552  * tomoyo_write_no_rewrite_policy - Write "struct tomoyo_no_rewrite_entry" list.
553  *
554  * @data:      String to parse.
555  * @is_delete: True if it is a delete request.
556  *
557  * Returns 0 on success, negative value otherwise.
558  *
559  * Caller holds tomoyo_read_lock().
560  */
561 int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete)
562 {
563         return tomoyo_update_no_rewrite_entry(data, is_delete);
564 }
565
566 /**
567  * tomoyo_read_no_rewrite_policy - Read "struct tomoyo_no_rewrite_entry" list.
568  *
569  * @head: Pointer to "struct tomoyo_io_buffer".
570  *
571  * Returns true on success, false otherwise.
572  *
573  * Caller holds tomoyo_read_lock().
574  */
575 bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
576 {
577         struct list_head *pos;
578         bool done = true;
579
580         list_for_each_cookie(pos, head->read_var2,
581                              &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE]) {
582                 struct tomoyo_no_rewrite_entry *ptr;
583                 ptr = list_entry(pos, struct tomoyo_no_rewrite_entry,
584                                  head.list);
585                 if (ptr->head.is_deleted)
586                         continue;
587                 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_DENY_REWRITE
588                                         "%s\n", ptr->pattern->name);
589                 if (!done)
590                         break;
591         }
592         return done;
593 }
594
595 static bool tomoyo_check_path_acl(const struct tomoyo_request_info *r,
596                                   const struct tomoyo_acl_info *ptr)
597 {
598         const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl),
599                                                          head);
600         return (acl->perm & (1 << r->param.path.operation)) &&
601                 tomoyo_compare_name_union(r->param.path.filename, &acl->name);
602 }
603
604 static bool tomoyo_check_path_number_acl(const struct tomoyo_request_info *r,
605                                          const struct tomoyo_acl_info *ptr)
606 {
607         const struct tomoyo_path_number_acl *acl =
608                 container_of(ptr, typeof(*acl), head);
609         return (acl->perm & (1 << r->param.path_number.operation)) &&
610                 tomoyo_compare_number_union(r->param.path_number.number,
611                                             &acl->number) &&
612                 tomoyo_compare_name_union(r->param.path_number.filename,
613                                           &acl->name);
614 }
615
616 static bool tomoyo_check_path2_acl(const struct tomoyo_request_info *r,
617                                    const struct tomoyo_acl_info *ptr)
618 {
619         const struct tomoyo_path2_acl *acl =
620                 container_of(ptr, typeof(*acl), head);
621         return (acl->perm & (1 << r->param.path2.operation)) &&
622                 tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1)
623                 && tomoyo_compare_name_union(r->param.path2.filename2,
624                                              &acl->name2);
625 }
626
627 static bool tomoyo_check_mkdev_acl(const struct tomoyo_request_info *r,
628                                 const struct tomoyo_acl_info *ptr)
629 {
630         const struct tomoyo_mkdev_acl *acl =
631                 container_of(ptr, typeof(*acl), head);
632         return (acl->perm & (1 << r->param.mkdev.operation)) &&
633                 tomoyo_compare_number_union(r->param.mkdev.mode,
634                                             &acl->mode) &&
635                 tomoyo_compare_number_union(r->param.mkdev.major,
636                                             &acl->major) &&
637                 tomoyo_compare_number_union(r->param.mkdev.minor,
638                                             &acl->minor) &&
639                 tomoyo_compare_name_union(r->param.mkdev.filename,
640                                           &acl->name);
641 }
642
643 static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
644                                  const struct tomoyo_acl_info *b)
645 {
646         const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
647         const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
648         return tomoyo_same_acl_head(&p1->head, &p2->head) &&
649                 tomoyo_same_name_union(&p1->name, &p2->name);
650 }
651
652 static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
653                                   struct tomoyo_acl_info *b,
654                                   const bool is_delete)
655 {
656         u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
657                 ->perm;
658         u16 perm = *a_perm;
659         const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
660         if (is_delete) {
661                 perm &= ~b_perm;
662                 if ((perm & TOMOYO_RW_MASK) != TOMOYO_RW_MASK)
663                         perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
664                 else if (!(perm & (1 << TOMOYO_TYPE_READ_WRITE)))
665                         perm &= ~TOMOYO_RW_MASK;
666         } else {
667                 perm |= b_perm;
668                 if ((perm & TOMOYO_RW_MASK) == TOMOYO_RW_MASK)
669                         perm |= (1 << TOMOYO_TYPE_READ_WRITE);
670                 else if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
671                         perm |= TOMOYO_RW_MASK;
672         }
673         *a_perm = perm;
674         return !perm;
675 }
676
677 /**
678  * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
679  *
680  * @type:      Type of operation.
681  * @filename:  Filename.
682  * @domain:    Pointer to "struct tomoyo_domain_info".
683  * @is_delete: True if it is a delete request.
684  *
685  * Returns 0 on success, negative value otherwise.
686  *
687  * Caller holds tomoyo_read_lock().
688  */
689 static int tomoyo_update_path_acl(const u8 type, const char *filename,
690                                   struct tomoyo_domain_info * const domain,
691                                   const bool is_delete)
692 {
693         struct tomoyo_path_acl e = {
694                 .head.type = TOMOYO_TYPE_PATH_ACL,
695                 .perm = 1 << type
696         };
697         int error;
698         if (e.perm == (1 << TOMOYO_TYPE_READ_WRITE))
699                 e.perm |= TOMOYO_RW_MASK;
700         if (!tomoyo_parse_name_union(filename, &e.name))
701                 return -EINVAL;
702         error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
703                                      tomoyo_same_path_acl,
704                                      tomoyo_merge_path_acl);
705         tomoyo_put_name_union(&e.name);
706         return error;
707 }
708
709 static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
710                                          const struct tomoyo_acl_info *b)
711 {
712         const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1),
713                                                                 head);
714         const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2),
715                                                                 head);
716         return tomoyo_same_acl_head(&p1->head, &p2->head)
717                 && tomoyo_same_name_union(&p1->name, &p2->name)
718                 && tomoyo_same_number_union(&p1->mode, &p2->mode)
719                 && tomoyo_same_number_union(&p1->major, &p2->major)
720                 && tomoyo_same_number_union(&p1->minor, &p2->minor);
721 }
722
723 static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
724                                           struct tomoyo_acl_info *b,
725                                           const bool is_delete)
726 {
727         u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
728                                          head)->perm;
729         u8 perm = *a_perm;
730         const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head)
731                 ->perm;
732         if (is_delete)
733                 perm &= ~b_perm;
734         else
735                 perm |= b_perm;
736         *a_perm = perm;
737         return !perm;
738 }
739
740 /**
741  * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list.
742  *
743  * @type:      Type of operation.
744  * @filename:  Filename.
745  * @mode:      Create mode.
746  * @major:     Device major number.
747  * @minor:     Device minor number.
748  * @domain:    Pointer to "struct tomoyo_domain_info".
749  * @is_delete: True if it is a delete request.
750  *
751  * Returns 0 on success, negative value otherwise.
752  *
753  * Caller holds tomoyo_read_lock().
754  */
755 static int tomoyo_update_mkdev_acl(const u8 type, const char *filename,
756                                           char *mode, char *major, char *minor,
757                                           struct tomoyo_domain_info * const
758                                           domain, const bool is_delete)
759 {
760         struct tomoyo_mkdev_acl e = {
761                 .head.type = TOMOYO_TYPE_MKDEV_ACL,
762                 .perm = 1 << type
763         };
764         int error = is_delete ? -ENOENT : -ENOMEM;
765         if (!tomoyo_parse_name_union(filename, &e.name) ||
766             !tomoyo_parse_number_union(mode, &e.mode) ||
767             !tomoyo_parse_number_union(major, &e.major) ||
768             !tomoyo_parse_number_union(minor, &e.minor))
769                 goto out;
770         error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
771                                      tomoyo_same_mkdev_acl,
772                                      tomoyo_merge_mkdev_acl);
773  out:
774         tomoyo_put_name_union(&e.name);
775         tomoyo_put_number_union(&e.mode);
776         tomoyo_put_number_union(&e.major);
777         tomoyo_put_number_union(&e.minor);
778         return error;
779 }
780
781 static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
782                                   const struct tomoyo_acl_info *b)
783 {
784         const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
785         const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
786         return tomoyo_same_acl_head(&p1->head, &p2->head)
787                 && tomoyo_same_name_union(&p1->name1, &p2->name1)
788                 && tomoyo_same_name_union(&p1->name2, &p2->name2);
789 }
790
791 static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
792                                    struct tomoyo_acl_info *b,
793                                    const bool is_delete)
794 {
795         u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
796                 ->perm;
797         u8 perm = *a_perm;
798         const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
799         if (is_delete)
800                 perm &= ~b_perm;
801         else
802                 perm |= b_perm;
803         *a_perm = perm;
804         return !perm;
805 }
806
807 /**
808  * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
809  *
810  * @type:      Type of operation.
811  * @filename1: First filename.
812  * @filename2: Second filename.
813  * @domain:    Pointer to "struct tomoyo_domain_info".
814  * @is_delete: True if it is a delete request.
815  *
816  * Returns 0 on success, negative value otherwise.
817  *
818  * Caller holds tomoyo_read_lock().
819  */
820 static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
821                                    const char *filename2,
822                                    struct tomoyo_domain_info * const domain,
823                                    const bool is_delete)
824 {
825         struct tomoyo_path2_acl e = {
826                 .head.type = TOMOYO_TYPE_PATH2_ACL,
827                 .perm = 1 << type
828         };
829         int error = is_delete ? -ENOENT : -ENOMEM;
830         if (!tomoyo_parse_name_union(filename1, &e.name1) ||
831             !tomoyo_parse_name_union(filename2, &e.name2))
832                 goto out;
833         error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
834                                      tomoyo_same_path2_acl,
835                                      tomoyo_merge_path2_acl);
836  out:
837         tomoyo_put_name_union(&e.name1);
838         tomoyo_put_name_union(&e.name2);
839         return error;
840 }
841
842 /**
843  * tomoyo_path_permission - Check permission for single path operation.
844  *
845  * @r:         Pointer to "struct tomoyo_request_info".
846  * @operation: Type of operation.
847  * @filename:  Filename to check.
848  *
849  * Returns 0 on success, negative value otherwise.
850  *
851  * Caller holds tomoyo_read_lock().
852  */
853 int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
854                            const struct tomoyo_path_info *filename)
855 {
856         int error;
857
858  next:
859         r->type = tomoyo_p2mac[operation];
860         r->mode = tomoyo_get_mode(r->profile, r->type);
861         if (r->mode == TOMOYO_CONFIG_DISABLED)
862                 return 0;
863         r->param_type = TOMOYO_TYPE_PATH_ACL;
864         r->param.path.filename = filename;
865         r->param.path.operation = operation;
866         do {
867                 tomoyo_check_acl(r, tomoyo_check_path_acl);
868                 if (!r->granted && operation == TOMOYO_TYPE_READ &&
869                     !r->domain->ignore_global_allow_read &&
870                     tomoyo_globally_readable_file(filename))
871                         r->granted = true;
872                 error = tomoyo_audit_path_log(r);
873                 /*
874                  * Do not retry for execute request, for alias may have
875                  * changed.
876                  */
877         } while (error == TOMOYO_RETRY_REQUEST &&
878                  operation != TOMOYO_TYPE_EXECUTE);
879         /*
880          * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
881          * we need to check "allow_rewrite" permission if the filename is
882          * specified by "deny_rewrite" keyword.
883          */
884         if (!error && operation == TOMOYO_TYPE_TRUNCATE &&
885             tomoyo_no_rewrite_file(filename)) {
886                 operation = TOMOYO_TYPE_REWRITE;
887                 goto next;
888         }
889         return error;
890 }
891
892 static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
893                                         const struct tomoyo_acl_info *b)
894 {
895         const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1),
896                                                                head);
897         const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
898                                                                head);
899         return tomoyo_same_acl_head(&p1->head, &p2->head)
900                 && tomoyo_same_name_union(&p1->name, &p2->name)
901                 && tomoyo_same_number_union(&p1->number, &p2->number);
902 }
903
904 static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
905                                          struct tomoyo_acl_info *b,
906                                          const bool is_delete)
907 {
908         u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl,
909                                           head)->perm;
910         u8 perm = *a_perm;
911         const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
912                 ->perm;
913         if (is_delete)
914                 perm &= ~b_perm;
915         else
916                 perm |= b_perm;
917         *a_perm = perm;
918         return !perm;
919 }
920
921 /**
922  * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
923  *
924  * @type:      Type of operation.
925  * @filename:  Filename.
926  * @number:    Number.
927  * @domain:    Pointer to "struct tomoyo_domain_info".
928  * @is_delete: True if it is a delete request.
929  *
930  * Returns 0 on success, negative value otherwise.
931  */
932 static int tomoyo_update_path_number_acl(const u8 type, const char *filename,
933                                          char *number,
934                                          struct tomoyo_domain_info * const
935                                          domain,
936                                          const bool is_delete)
937 {
938         struct tomoyo_path_number_acl e = {
939                 .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
940                 .perm = 1 << type
941         };
942         int error = is_delete ? -ENOENT : -ENOMEM;
943         if (!tomoyo_parse_name_union(filename, &e.name))
944                 return -EINVAL;
945         if (!tomoyo_parse_number_union(number, &e.number))
946                 goto out;
947         error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
948                                      tomoyo_same_path_number_acl,
949                                      tomoyo_merge_path_number_acl);
950  out:
951         tomoyo_put_name_union(&e.name);
952         tomoyo_put_number_union(&e.number);
953         return error;
954 }
955
956 /**
957  * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp".
958  *
959  * @type:   Type of operation.
960  * @path:   Pointer to "struct path".
961  * @number: Number.
962  *
963  * Returns 0 on success, negative value otherwise.
964  */
965 int tomoyo_path_number_perm(const u8 type, struct path *path,
966                             unsigned long number)
967 {
968         struct tomoyo_request_info r;
969         int error = -ENOMEM;
970         struct tomoyo_path_info buf;
971         int idx;
972
973         if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type])
974             == TOMOYO_CONFIG_DISABLED || !path->mnt || !path->dentry)
975                 return 0;
976         idx = tomoyo_read_lock();
977         if (!tomoyo_get_realpath(&buf, path))
978                 goto out;
979         if (type == TOMOYO_TYPE_MKDIR)
980                 tomoyo_add_slash(&buf);
981         r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
982         r.param.path_number.operation = type;
983         r.param.path_number.filename = &buf;
984         r.param.path_number.number = number;
985         do {
986                 tomoyo_check_acl(&r, tomoyo_check_path_number_acl);
987                 error = tomoyo_audit_path_number_log(&r);
988         } while (error == TOMOYO_RETRY_REQUEST);
989         kfree(buf.name);
990  out:
991         tomoyo_read_unlock(idx);
992         if (r.mode != TOMOYO_CONFIG_ENFORCING)
993                 error = 0;
994         return error;
995 }
996
997 /**
998  * tomoyo_check_open_permission - Check permission for "read" and "write".
999  *
1000  * @domain: Pointer to "struct tomoyo_domain_info".
1001  * @path:   Pointer to "struct path".
1002  * @flag:   Flags for open().
1003  *
1004  * Returns 0 on success, negative value otherwise.
1005  */
1006 int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1007                                  struct path *path, const int flag)
1008 {
1009         const u8 acc_mode = ACC_MODE(flag);
1010         int error = -ENOMEM;
1011         struct tomoyo_path_info buf;
1012         struct tomoyo_request_info r;
1013         int idx;
1014
1015         if (!path->mnt ||
1016             (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode)))
1017                 return 0;
1018         buf.name = NULL;
1019         r.mode = TOMOYO_CONFIG_DISABLED;
1020         idx = tomoyo_read_lock();
1021         if (!tomoyo_get_realpath(&buf, path))
1022                 goto out;
1023         error = 0;
1024         /*
1025          * If the filename is specified by "deny_rewrite" keyword,
1026          * we need to check "allow_rewrite" permission when the filename is not
1027          * opened for append mode or the filename is truncated at open time.
1028          */
1029         if ((acc_mode & MAY_WRITE) && !(flag & O_APPEND)
1030             && tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_REWRITE)
1031             != TOMOYO_CONFIG_DISABLED) {
1032                 if (!tomoyo_get_realpath(&buf, path)) {
1033                         error = -ENOMEM;
1034                         goto out;
1035                 }
1036                 if (tomoyo_no_rewrite_file(&buf))
1037                         error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE,
1038                                                        &buf);
1039         }
1040         if (!error && acc_mode &&
1041             tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
1042             != TOMOYO_CONFIG_DISABLED) {
1043                 u8 operation;
1044                 if (!buf.name && !tomoyo_get_realpath(&buf, path)) {
1045                         error = -ENOMEM;
1046                         goto out;
1047                 }
1048                 if (acc_mode == (MAY_READ | MAY_WRITE))
1049                         operation = TOMOYO_TYPE_READ_WRITE;
1050                 else if (acc_mode == MAY_READ)
1051                         operation = TOMOYO_TYPE_READ;
1052                 else
1053                         operation = TOMOYO_TYPE_WRITE;
1054                 error = tomoyo_path_permission(&r, operation, &buf);
1055         }
1056  out:
1057         kfree(buf.name);
1058         tomoyo_read_unlock(idx);
1059         if (r.mode != TOMOYO_CONFIG_ENFORCING)
1060                 error = 0;
1061         return error;
1062 }
1063
1064 /**
1065  * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "rewrite", "chroot" and "unmount".
1066  *
1067  * @operation: Type of operation.
1068  * @path:      Pointer to "struct path".
1069  *
1070  * Returns 0 on success, negative value otherwise.
1071  */
1072 int tomoyo_path_perm(const u8 operation, struct path *path)
1073 {
1074         int error = -ENOMEM;
1075         struct tomoyo_path_info buf;
1076         struct tomoyo_request_info r;
1077         int idx;
1078
1079         if (!path->mnt)
1080                 return 0;
1081         if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
1082             == TOMOYO_CONFIG_DISABLED)
1083                 return 0;
1084         buf.name = NULL;
1085         idx = tomoyo_read_lock();
1086         if (!tomoyo_get_realpath(&buf, path))
1087                 goto out;
1088         switch (operation) {
1089         case TOMOYO_TYPE_REWRITE:
1090                 if (!tomoyo_no_rewrite_file(&buf)) {
1091                         error = 0;
1092                         goto out;
1093                 }
1094                 break;
1095         case TOMOYO_TYPE_RMDIR:
1096         case TOMOYO_TYPE_CHROOT:
1097         case TOMOYO_TYPE_UMOUNT:
1098                 tomoyo_add_slash(&buf);
1099                 break;
1100         }
1101         error = tomoyo_path_permission(&r, operation, &buf);
1102  out:
1103         kfree(buf.name);
1104         tomoyo_read_unlock(idx);
1105         if (r.mode != TOMOYO_CONFIG_ENFORCING)
1106                 error = 0;
1107         return error;
1108 }
1109
1110 /**
1111  * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar".
1112  *
1113  * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK)
1114  * @path:      Pointer to "struct path".
1115  * @mode:      Create mode.
1116  * @dev:       Device number.
1117  *
1118  * Returns 0 on success, negative value otherwise.
1119  */
1120 int tomoyo_mkdev_perm(const u8 operation, struct path *path,
1121                              const unsigned int mode, unsigned int dev)
1122 {
1123         struct tomoyo_request_info r;
1124         int error = -ENOMEM;
1125         struct tomoyo_path_info buf;
1126         int idx;
1127
1128         if (!path->mnt ||
1129             tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
1130             == TOMOYO_CONFIG_DISABLED)
1131                 return 0;
1132         idx = tomoyo_read_lock();
1133         error = -ENOMEM;
1134         if (tomoyo_get_realpath(&buf, path)) {
1135                 dev = new_decode_dev(dev);
1136                 r.param_type = TOMOYO_TYPE_MKDEV_ACL;
1137                 r.param.mkdev.filename = &buf;
1138                 r.param.mkdev.operation = operation;
1139                 r.param.mkdev.mode = mode;
1140                 r.param.mkdev.major = MAJOR(dev);
1141                 r.param.mkdev.minor = MINOR(dev);
1142                 tomoyo_check_acl(&r, tomoyo_check_mkdev_acl);
1143                 error = tomoyo_audit_mkdev_log(&r);
1144                 kfree(buf.name);
1145         }
1146         tomoyo_read_unlock(idx);
1147         if (r.mode != TOMOYO_CONFIG_ENFORCING)
1148                 error = 0;
1149         return error;
1150 }
1151
1152 /**
1153  * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root".
1154  *
1155  * @operation: Type of operation.
1156  * @path1:      Pointer to "struct path".
1157  * @path2:      Pointer to "struct path".
1158  *
1159  * Returns 0 on success, negative value otherwise.
1160  */
1161 int tomoyo_path2_perm(const u8 operation, struct path *path1,
1162                       struct path *path2)
1163 {
1164         int error = -ENOMEM;
1165         struct tomoyo_path_info buf1;
1166         struct tomoyo_path_info buf2;
1167         struct tomoyo_request_info r;
1168         int idx;
1169
1170         if (!path1->mnt || !path2->mnt ||
1171             tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
1172             == TOMOYO_CONFIG_DISABLED)
1173                 return 0;
1174         buf1.name = NULL;
1175         buf2.name = NULL;
1176         idx = tomoyo_read_lock();
1177         if (!tomoyo_get_realpath(&buf1, path1) ||
1178             !tomoyo_get_realpath(&buf2, path2))
1179                 goto out;
1180         switch (operation) {
1181                 struct dentry *dentry;
1182         case TOMOYO_TYPE_RENAME:
1183         case TOMOYO_TYPE_LINK:
1184                 dentry = path1->dentry;
1185                 if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode))
1186                         break;
1187                 /* fall through */
1188         case TOMOYO_TYPE_PIVOT_ROOT:
1189                 tomoyo_add_slash(&buf1);
1190                 tomoyo_add_slash(&buf2);
1191                 break;
1192         }
1193         r.param_type = TOMOYO_TYPE_PATH2_ACL;
1194         r.param.path2.operation = operation;
1195         r.param.path2.filename1 = &buf1;
1196         r.param.path2.filename2 = &buf2;
1197         do {
1198                 tomoyo_check_acl(&r, tomoyo_check_path2_acl);
1199                 error = tomoyo_audit_path2_log(&r);
1200         } while (error == TOMOYO_RETRY_REQUEST);
1201  out:
1202         kfree(buf1.name);
1203         kfree(buf2.name);
1204         tomoyo_read_unlock(idx);
1205         if (r.mode != TOMOYO_CONFIG_ENFORCING)
1206                 error = 0;
1207         return error;
1208 }
1209
1210 /**
1211  * tomoyo_write_file_policy - Update file related list.
1212  *
1213  * @data:      String to parse.
1214  * @domain:    Pointer to "struct tomoyo_domain_info".
1215  * @is_delete: True if it is a delete request.
1216  *
1217  * Returns 0 on success, negative value otherwise.
1218  *
1219  * Caller holds tomoyo_read_lock().
1220  */
1221 int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
1222                              const bool is_delete)
1223 {
1224         char *w[5];
1225         u8 type;
1226         if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
1227                 return -EINVAL;
1228         if (strncmp(w[0], "allow_", 6))
1229                 goto out;
1230         w[0] += 6;
1231         for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) {
1232                 if (strcmp(w[0], tomoyo_path_keyword[type]))
1233                         continue;
1234                 return tomoyo_update_path_acl(type, w[1], domain, is_delete);
1235         }
1236         if (!w[2][0])
1237                 goto out;
1238         for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) {
1239                 if (strcmp(w[0], tomoyo_path2_keyword[type]))
1240                         continue;
1241                 return tomoyo_update_path2_acl(type, w[1], w[2], domain,
1242                                                is_delete);
1243         }
1244         for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) {
1245                 if (strcmp(w[0], tomoyo_path_number_keyword[type]))
1246                         continue;
1247                 return tomoyo_update_path_number_acl(type, w[1], w[2], domain,
1248                                                      is_delete);
1249         }
1250         if (!w[3][0] || !w[4][0])
1251                 goto out;
1252         for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) {
1253                 if (strcmp(w[0], tomoyo_mkdev_keyword[type]))
1254                         continue;
1255                 return tomoyo_update_mkdev_acl(type, w[1], w[2], w[3],
1256                                                w[4], domain, is_delete);
1257         }
1258  out:
1259         return -EINVAL;
1260 }