]> bbs.cooldavid.org Git - net-next-2.6.git/blob - security/tomoyo/file.c
TOMOYO: Aggregate reader functions.
[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 static bool tomoyo_same_pattern(const struct tomoyo_acl_head *a,
348                                 const struct tomoyo_acl_head *b)
349 {
350         return container_of(a, struct tomoyo_pattern_entry, head)->pattern ==
351                 container_of(b, struct tomoyo_pattern_entry, head)->pattern;
352 }
353
354 /**
355  * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list.
356  *
357  * @pattern:   Pathname pattern.
358  * @is_delete: True if it is a delete request.
359  *
360  * Returns 0 on success, negative value otherwise.
361  *
362  * Caller holds tomoyo_read_lock().
363  */
364 static int tomoyo_update_file_pattern_entry(const char *pattern,
365                                             const bool is_delete)
366 {
367         struct tomoyo_pattern_entry e = { };
368         int error;
369
370         if (!tomoyo_correct_word(pattern))
371                 return -EINVAL;
372         e.pattern = tomoyo_get_name(pattern);
373         if (!e.pattern)
374                 return -ENOMEM;
375         error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
376                                      &tomoyo_policy_list[TOMOYO_ID_PATTERN],
377                                      tomoyo_same_pattern);
378         tomoyo_put_name(e.pattern);
379         return error;
380 }
381
382 /**
383  * tomoyo_file_pattern - Get patterned pathname.
384  *
385  * @filename: The filename to find patterned pathname.
386  *
387  * Returns pointer to pathname pattern if matched, @filename otherwise.
388  *
389  * Caller holds tomoyo_read_lock().
390  */
391 const char *tomoyo_file_pattern(const struct tomoyo_path_info *filename)
392 {
393         struct tomoyo_pattern_entry *ptr;
394         const struct tomoyo_path_info *pattern = NULL;
395
396         list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_PATTERN],
397                                 head.list) {
398                 if (ptr->head.is_deleted)
399                         continue;
400                 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
401                         continue;
402                 pattern = ptr->pattern;
403                 if (tomoyo_strendswith(pattern->name, "/\\*")) {
404                         /* Do nothing. Try to find the better match. */
405                 } else {
406                         /* This would be the better match. Use this. */
407                         break;
408                 }
409         }
410         if (pattern)
411                 filename = pattern;
412         return filename->name;
413 }
414
415 /**
416  * tomoyo_write_pattern_policy - Write "struct tomoyo_pattern_entry" list.
417  *
418  * @data:      String to parse.
419  * @is_delete: True if it is a delete request.
420  *
421  * Returns 0 on success, negative value otherwise.
422  *
423  * Caller holds tomoyo_read_lock().
424  */
425 int tomoyo_write_pattern_policy(char *data, const bool is_delete)
426 {
427         return tomoyo_update_file_pattern_entry(data, is_delete);
428 }
429
430 static bool tomoyo_same_no_rewrite(const struct tomoyo_acl_head *a,
431                                    const struct tomoyo_acl_head *b)
432 {
433         return container_of(a, struct tomoyo_no_rewrite_entry, head)->pattern
434                 == container_of(b, struct tomoyo_no_rewrite_entry, head)
435                 ->pattern;
436 }
437
438 /**
439  * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list.
440  *
441  * @pattern:   Pathname pattern that are not rewritable by default.
442  * @is_delete: True if it is a delete request.
443  *
444  * Returns 0 on success, negative value otherwise.
445  *
446  * Caller holds tomoyo_read_lock().
447  */
448 static int tomoyo_update_no_rewrite_entry(const char *pattern,
449                                           const bool is_delete)
450 {
451         struct tomoyo_no_rewrite_entry e = { };
452         int error;
453
454         if (!tomoyo_correct_word(pattern))
455                 return -EINVAL;
456         e.pattern = tomoyo_get_name(pattern);
457         if (!e.pattern)
458                 return -ENOMEM;
459         error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
460                                      &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE],
461                                      tomoyo_same_no_rewrite);
462         tomoyo_put_name(e.pattern);
463         return error;
464 }
465
466 /**
467  * tomoyo_no_rewrite_file - Check if the given pathname is not permitted to be rewrited.
468  *
469  * @filename: Filename to check.
470  *
471  * Returns true if @filename is specified by "deny_rewrite" directive,
472  * false otherwise.
473  *
474  * Caller holds tomoyo_read_lock().
475  */
476 static bool tomoyo_no_rewrite_file(const struct tomoyo_path_info *filename)
477 {
478         struct tomoyo_no_rewrite_entry *ptr;
479         bool found = false;
480
481         list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE],
482                                 head.list) {
483                 if (ptr->head.is_deleted)
484                         continue;
485                 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
486                         continue;
487                 found = true;
488                 break;
489         }
490         return found;
491 }
492
493 /**
494  * tomoyo_write_no_rewrite_policy - Write "struct tomoyo_no_rewrite_entry" list.
495  *
496  * @data:      String to parse.
497  * @is_delete: True if it is a delete request.
498  *
499  * Returns 0 on success, negative value otherwise.
500  *
501  * Caller holds tomoyo_read_lock().
502  */
503 int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete)
504 {
505         return tomoyo_update_no_rewrite_entry(data, is_delete);
506 }
507
508 static bool tomoyo_check_path_acl(const struct tomoyo_request_info *r,
509                                   const struct tomoyo_acl_info *ptr)
510 {
511         const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl),
512                                                          head);
513         return (acl->perm & (1 << r->param.path.operation)) &&
514                 tomoyo_compare_name_union(r->param.path.filename, &acl->name);
515 }
516
517 static bool tomoyo_check_path_number_acl(const struct tomoyo_request_info *r,
518                                          const struct tomoyo_acl_info *ptr)
519 {
520         const struct tomoyo_path_number_acl *acl =
521                 container_of(ptr, typeof(*acl), head);
522         return (acl->perm & (1 << r->param.path_number.operation)) &&
523                 tomoyo_compare_number_union(r->param.path_number.number,
524                                             &acl->number) &&
525                 tomoyo_compare_name_union(r->param.path_number.filename,
526                                           &acl->name);
527 }
528
529 static bool tomoyo_check_path2_acl(const struct tomoyo_request_info *r,
530                                    const struct tomoyo_acl_info *ptr)
531 {
532         const struct tomoyo_path2_acl *acl =
533                 container_of(ptr, typeof(*acl), head);
534         return (acl->perm & (1 << r->param.path2.operation)) &&
535                 tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1)
536                 && tomoyo_compare_name_union(r->param.path2.filename2,
537                                              &acl->name2);
538 }
539
540 static bool tomoyo_check_mkdev_acl(const struct tomoyo_request_info *r,
541                                 const struct tomoyo_acl_info *ptr)
542 {
543         const struct tomoyo_mkdev_acl *acl =
544                 container_of(ptr, typeof(*acl), head);
545         return (acl->perm & (1 << r->param.mkdev.operation)) &&
546                 tomoyo_compare_number_union(r->param.mkdev.mode,
547                                             &acl->mode) &&
548                 tomoyo_compare_number_union(r->param.mkdev.major,
549                                             &acl->major) &&
550                 tomoyo_compare_number_union(r->param.mkdev.minor,
551                                             &acl->minor) &&
552                 tomoyo_compare_name_union(r->param.mkdev.filename,
553                                           &acl->name);
554 }
555
556 static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
557                                  const struct tomoyo_acl_info *b)
558 {
559         const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
560         const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
561         return tomoyo_same_acl_head(&p1->head, &p2->head) &&
562                 tomoyo_same_name_union(&p1->name, &p2->name);
563 }
564
565 static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
566                                   struct tomoyo_acl_info *b,
567                                   const bool is_delete)
568 {
569         u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
570                 ->perm;
571         u16 perm = *a_perm;
572         const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
573         if (is_delete) {
574                 perm &= ~b_perm;
575                 if ((perm & TOMOYO_RW_MASK) != TOMOYO_RW_MASK)
576                         perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
577                 else if (!(perm & (1 << TOMOYO_TYPE_READ_WRITE)))
578                         perm &= ~TOMOYO_RW_MASK;
579         } else {
580                 perm |= b_perm;
581                 if ((perm & TOMOYO_RW_MASK) == TOMOYO_RW_MASK)
582                         perm |= (1 << TOMOYO_TYPE_READ_WRITE);
583                 else if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
584                         perm |= TOMOYO_RW_MASK;
585         }
586         *a_perm = perm;
587         return !perm;
588 }
589
590 /**
591  * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
592  *
593  * @type:      Type of operation.
594  * @filename:  Filename.
595  * @domain:    Pointer to "struct tomoyo_domain_info".
596  * @is_delete: True if it is a delete request.
597  *
598  * Returns 0 on success, negative value otherwise.
599  *
600  * Caller holds tomoyo_read_lock().
601  */
602 static int tomoyo_update_path_acl(const u8 type, const char *filename,
603                                   struct tomoyo_domain_info * const domain,
604                                   const bool is_delete)
605 {
606         struct tomoyo_path_acl e = {
607                 .head.type = TOMOYO_TYPE_PATH_ACL,
608                 .perm = 1 << type
609         };
610         int error;
611         if (e.perm == (1 << TOMOYO_TYPE_READ_WRITE))
612                 e.perm |= TOMOYO_RW_MASK;
613         if (!tomoyo_parse_name_union(filename, &e.name))
614                 return -EINVAL;
615         error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
616                                      tomoyo_same_path_acl,
617                                      tomoyo_merge_path_acl);
618         tomoyo_put_name_union(&e.name);
619         return error;
620 }
621
622 static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
623                                          const struct tomoyo_acl_info *b)
624 {
625         const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1),
626                                                                 head);
627         const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2),
628                                                                 head);
629         return tomoyo_same_acl_head(&p1->head, &p2->head)
630                 && tomoyo_same_name_union(&p1->name, &p2->name)
631                 && tomoyo_same_number_union(&p1->mode, &p2->mode)
632                 && tomoyo_same_number_union(&p1->major, &p2->major)
633                 && tomoyo_same_number_union(&p1->minor, &p2->minor);
634 }
635
636 static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
637                                           struct tomoyo_acl_info *b,
638                                           const bool is_delete)
639 {
640         u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
641                                          head)->perm;
642         u8 perm = *a_perm;
643         const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head)
644                 ->perm;
645         if (is_delete)
646                 perm &= ~b_perm;
647         else
648                 perm |= b_perm;
649         *a_perm = perm;
650         return !perm;
651 }
652
653 /**
654  * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list.
655  *
656  * @type:      Type of operation.
657  * @filename:  Filename.
658  * @mode:      Create mode.
659  * @major:     Device major number.
660  * @minor:     Device minor number.
661  * @domain:    Pointer to "struct tomoyo_domain_info".
662  * @is_delete: True if it is a delete request.
663  *
664  * Returns 0 on success, negative value otherwise.
665  *
666  * Caller holds tomoyo_read_lock().
667  */
668 static int tomoyo_update_mkdev_acl(const u8 type, const char *filename,
669                                           char *mode, char *major, char *minor,
670                                           struct tomoyo_domain_info * const
671                                           domain, const bool is_delete)
672 {
673         struct tomoyo_mkdev_acl e = {
674                 .head.type = TOMOYO_TYPE_MKDEV_ACL,
675                 .perm = 1 << type
676         };
677         int error = is_delete ? -ENOENT : -ENOMEM;
678         if (!tomoyo_parse_name_union(filename, &e.name) ||
679             !tomoyo_parse_number_union(mode, &e.mode) ||
680             !tomoyo_parse_number_union(major, &e.major) ||
681             !tomoyo_parse_number_union(minor, &e.minor))
682                 goto out;
683         error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
684                                      tomoyo_same_mkdev_acl,
685                                      tomoyo_merge_mkdev_acl);
686  out:
687         tomoyo_put_name_union(&e.name);
688         tomoyo_put_number_union(&e.mode);
689         tomoyo_put_number_union(&e.major);
690         tomoyo_put_number_union(&e.minor);
691         return error;
692 }
693
694 static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
695                                   const struct tomoyo_acl_info *b)
696 {
697         const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
698         const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
699         return tomoyo_same_acl_head(&p1->head, &p2->head)
700                 && tomoyo_same_name_union(&p1->name1, &p2->name1)
701                 && tomoyo_same_name_union(&p1->name2, &p2->name2);
702 }
703
704 static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
705                                    struct tomoyo_acl_info *b,
706                                    const bool is_delete)
707 {
708         u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
709                 ->perm;
710         u8 perm = *a_perm;
711         const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
712         if (is_delete)
713                 perm &= ~b_perm;
714         else
715                 perm |= b_perm;
716         *a_perm = perm;
717         return !perm;
718 }
719
720 /**
721  * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
722  *
723  * @type:      Type of operation.
724  * @filename1: First filename.
725  * @filename2: Second filename.
726  * @domain:    Pointer to "struct tomoyo_domain_info".
727  * @is_delete: True if it is a delete request.
728  *
729  * Returns 0 on success, negative value otherwise.
730  *
731  * Caller holds tomoyo_read_lock().
732  */
733 static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
734                                    const char *filename2,
735                                    struct tomoyo_domain_info * const domain,
736                                    const bool is_delete)
737 {
738         struct tomoyo_path2_acl e = {
739                 .head.type = TOMOYO_TYPE_PATH2_ACL,
740                 .perm = 1 << type
741         };
742         int error = is_delete ? -ENOENT : -ENOMEM;
743         if (!tomoyo_parse_name_union(filename1, &e.name1) ||
744             !tomoyo_parse_name_union(filename2, &e.name2))
745                 goto out;
746         error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
747                                      tomoyo_same_path2_acl,
748                                      tomoyo_merge_path2_acl);
749  out:
750         tomoyo_put_name_union(&e.name1);
751         tomoyo_put_name_union(&e.name2);
752         return error;
753 }
754
755 /**
756  * tomoyo_path_permission - Check permission for single path operation.
757  *
758  * @r:         Pointer to "struct tomoyo_request_info".
759  * @operation: Type of operation.
760  * @filename:  Filename to check.
761  *
762  * Returns 0 on success, negative value otherwise.
763  *
764  * Caller holds tomoyo_read_lock().
765  */
766 int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
767                            const struct tomoyo_path_info *filename)
768 {
769         int error;
770
771  next:
772         r->type = tomoyo_p2mac[operation];
773         r->mode = tomoyo_get_mode(r->profile, r->type);
774         if (r->mode == TOMOYO_CONFIG_DISABLED)
775                 return 0;
776         r->param_type = TOMOYO_TYPE_PATH_ACL;
777         r->param.path.filename = filename;
778         r->param.path.operation = operation;
779         do {
780                 tomoyo_check_acl(r, tomoyo_check_path_acl);
781                 if (!r->granted && operation == TOMOYO_TYPE_READ &&
782                     !r->domain->ignore_global_allow_read &&
783                     tomoyo_globally_readable_file(filename))
784                         r->granted = true;
785                 error = tomoyo_audit_path_log(r);
786                 /*
787                  * Do not retry for execute request, for alias may have
788                  * changed.
789                  */
790         } while (error == TOMOYO_RETRY_REQUEST &&
791                  operation != TOMOYO_TYPE_EXECUTE);
792         /*
793          * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
794          * we need to check "allow_rewrite" permission if the filename is
795          * specified by "deny_rewrite" keyword.
796          */
797         if (!error && operation == TOMOYO_TYPE_TRUNCATE &&
798             tomoyo_no_rewrite_file(filename)) {
799                 operation = TOMOYO_TYPE_REWRITE;
800                 goto next;
801         }
802         return error;
803 }
804
805 static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
806                                         const struct tomoyo_acl_info *b)
807 {
808         const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1),
809                                                                head);
810         const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
811                                                                head);
812         return tomoyo_same_acl_head(&p1->head, &p2->head)
813                 && tomoyo_same_name_union(&p1->name, &p2->name)
814                 && tomoyo_same_number_union(&p1->number, &p2->number);
815 }
816
817 static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
818                                          struct tomoyo_acl_info *b,
819                                          const bool is_delete)
820 {
821         u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl,
822                                           head)->perm;
823         u8 perm = *a_perm;
824         const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
825                 ->perm;
826         if (is_delete)
827                 perm &= ~b_perm;
828         else
829                 perm |= b_perm;
830         *a_perm = perm;
831         return !perm;
832 }
833
834 /**
835  * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
836  *
837  * @type:      Type of operation.
838  * @filename:  Filename.
839  * @number:    Number.
840  * @domain:    Pointer to "struct tomoyo_domain_info".
841  * @is_delete: True if it is a delete request.
842  *
843  * Returns 0 on success, negative value otherwise.
844  */
845 static int tomoyo_update_path_number_acl(const u8 type, const char *filename,
846                                          char *number,
847                                          struct tomoyo_domain_info * const
848                                          domain,
849                                          const bool is_delete)
850 {
851         struct tomoyo_path_number_acl e = {
852                 .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
853                 .perm = 1 << type
854         };
855         int error = is_delete ? -ENOENT : -ENOMEM;
856         if (!tomoyo_parse_name_union(filename, &e.name))
857                 return -EINVAL;
858         if (!tomoyo_parse_number_union(number, &e.number))
859                 goto out;
860         error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
861                                      tomoyo_same_path_number_acl,
862                                      tomoyo_merge_path_number_acl);
863  out:
864         tomoyo_put_name_union(&e.name);
865         tomoyo_put_number_union(&e.number);
866         return error;
867 }
868
869 /**
870  * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp".
871  *
872  * @type:   Type of operation.
873  * @path:   Pointer to "struct path".
874  * @number: Number.
875  *
876  * Returns 0 on success, negative value otherwise.
877  */
878 int tomoyo_path_number_perm(const u8 type, struct path *path,
879                             unsigned long number)
880 {
881         struct tomoyo_request_info r;
882         int error = -ENOMEM;
883         struct tomoyo_path_info buf;
884         int idx;
885
886         if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type])
887             == TOMOYO_CONFIG_DISABLED || !path->mnt || !path->dentry)
888                 return 0;
889         idx = tomoyo_read_lock();
890         if (!tomoyo_get_realpath(&buf, path))
891                 goto out;
892         if (type == TOMOYO_TYPE_MKDIR)
893                 tomoyo_add_slash(&buf);
894         r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
895         r.param.path_number.operation = type;
896         r.param.path_number.filename = &buf;
897         r.param.path_number.number = number;
898         do {
899                 tomoyo_check_acl(&r, tomoyo_check_path_number_acl);
900                 error = tomoyo_audit_path_number_log(&r);
901         } while (error == TOMOYO_RETRY_REQUEST);
902         kfree(buf.name);
903  out:
904         tomoyo_read_unlock(idx);
905         if (r.mode != TOMOYO_CONFIG_ENFORCING)
906                 error = 0;
907         return error;
908 }
909
910 /**
911  * tomoyo_check_open_permission - Check permission for "read" and "write".
912  *
913  * @domain: Pointer to "struct tomoyo_domain_info".
914  * @path:   Pointer to "struct path".
915  * @flag:   Flags for open().
916  *
917  * Returns 0 on success, negative value otherwise.
918  */
919 int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
920                                  struct path *path, const int flag)
921 {
922         const u8 acc_mode = ACC_MODE(flag);
923         int error = -ENOMEM;
924         struct tomoyo_path_info buf;
925         struct tomoyo_request_info r;
926         int idx;
927
928         if (!path->mnt ||
929             (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode)))
930                 return 0;
931         buf.name = NULL;
932         r.mode = TOMOYO_CONFIG_DISABLED;
933         idx = tomoyo_read_lock();
934         if (!tomoyo_get_realpath(&buf, path))
935                 goto out;
936         error = 0;
937         /*
938          * If the filename is specified by "deny_rewrite" keyword,
939          * we need to check "allow_rewrite" permission when the filename is not
940          * opened for append mode or the filename is truncated at open time.
941          */
942         if ((acc_mode & MAY_WRITE) && !(flag & O_APPEND)
943             && tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_REWRITE)
944             != TOMOYO_CONFIG_DISABLED) {
945                 if (!tomoyo_get_realpath(&buf, path)) {
946                         error = -ENOMEM;
947                         goto out;
948                 }
949                 if (tomoyo_no_rewrite_file(&buf))
950                         error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE,
951                                                        &buf);
952         }
953         if (!error && acc_mode &&
954             tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
955             != TOMOYO_CONFIG_DISABLED) {
956                 u8 operation;
957                 if (!buf.name && !tomoyo_get_realpath(&buf, path)) {
958                         error = -ENOMEM;
959                         goto out;
960                 }
961                 if (acc_mode == (MAY_READ | MAY_WRITE))
962                         operation = TOMOYO_TYPE_READ_WRITE;
963                 else if (acc_mode == MAY_READ)
964                         operation = TOMOYO_TYPE_READ;
965                 else
966                         operation = TOMOYO_TYPE_WRITE;
967                 error = tomoyo_path_permission(&r, operation, &buf);
968         }
969  out:
970         kfree(buf.name);
971         tomoyo_read_unlock(idx);
972         if (r.mode != TOMOYO_CONFIG_ENFORCING)
973                 error = 0;
974         return error;
975 }
976
977 /**
978  * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "rewrite", "chroot" and "unmount".
979  *
980  * @operation: Type of operation.
981  * @path:      Pointer to "struct path".
982  *
983  * Returns 0 on success, negative value otherwise.
984  */
985 int tomoyo_path_perm(const u8 operation, struct path *path)
986 {
987         int error = -ENOMEM;
988         struct tomoyo_path_info buf;
989         struct tomoyo_request_info r;
990         int idx;
991
992         if (!path->mnt)
993                 return 0;
994         if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
995             == TOMOYO_CONFIG_DISABLED)
996                 return 0;
997         buf.name = NULL;
998         idx = tomoyo_read_lock();
999         if (!tomoyo_get_realpath(&buf, path))
1000                 goto out;
1001         switch (operation) {
1002         case TOMOYO_TYPE_REWRITE:
1003                 if (!tomoyo_no_rewrite_file(&buf)) {
1004                         error = 0;
1005                         goto out;
1006                 }
1007                 break;
1008         case TOMOYO_TYPE_RMDIR:
1009         case TOMOYO_TYPE_CHROOT:
1010         case TOMOYO_TYPE_UMOUNT:
1011                 tomoyo_add_slash(&buf);
1012                 break;
1013         }
1014         error = tomoyo_path_permission(&r, operation, &buf);
1015  out:
1016         kfree(buf.name);
1017         tomoyo_read_unlock(idx);
1018         if (r.mode != TOMOYO_CONFIG_ENFORCING)
1019                 error = 0;
1020         return error;
1021 }
1022
1023 /**
1024  * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar".
1025  *
1026  * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK)
1027  * @path:      Pointer to "struct path".
1028  * @mode:      Create mode.
1029  * @dev:       Device number.
1030  *
1031  * Returns 0 on success, negative value otherwise.
1032  */
1033 int tomoyo_mkdev_perm(const u8 operation, struct path *path,
1034                              const unsigned int mode, unsigned int dev)
1035 {
1036         struct tomoyo_request_info r;
1037         int error = -ENOMEM;
1038         struct tomoyo_path_info buf;
1039         int idx;
1040
1041         if (!path->mnt ||
1042             tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
1043             == TOMOYO_CONFIG_DISABLED)
1044                 return 0;
1045         idx = tomoyo_read_lock();
1046         error = -ENOMEM;
1047         if (tomoyo_get_realpath(&buf, path)) {
1048                 dev = new_decode_dev(dev);
1049                 r.param_type = TOMOYO_TYPE_MKDEV_ACL;
1050                 r.param.mkdev.filename = &buf;
1051                 r.param.mkdev.operation = operation;
1052                 r.param.mkdev.mode = mode;
1053                 r.param.mkdev.major = MAJOR(dev);
1054                 r.param.mkdev.minor = MINOR(dev);
1055                 tomoyo_check_acl(&r, tomoyo_check_mkdev_acl);
1056                 error = tomoyo_audit_mkdev_log(&r);
1057                 kfree(buf.name);
1058         }
1059         tomoyo_read_unlock(idx);
1060         if (r.mode != TOMOYO_CONFIG_ENFORCING)
1061                 error = 0;
1062         return error;
1063 }
1064
1065 /**
1066  * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root".
1067  *
1068  * @operation: Type of operation.
1069  * @path1:      Pointer to "struct path".
1070  * @path2:      Pointer to "struct path".
1071  *
1072  * Returns 0 on success, negative value otherwise.
1073  */
1074 int tomoyo_path2_perm(const u8 operation, struct path *path1,
1075                       struct path *path2)
1076 {
1077         int error = -ENOMEM;
1078         struct tomoyo_path_info buf1;
1079         struct tomoyo_path_info buf2;
1080         struct tomoyo_request_info r;
1081         int idx;
1082
1083         if (!path1->mnt || !path2->mnt ||
1084             tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
1085             == TOMOYO_CONFIG_DISABLED)
1086                 return 0;
1087         buf1.name = NULL;
1088         buf2.name = NULL;
1089         idx = tomoyo_read_lock();
1090         if (!tomoyo_get_realpath(&buf1, path1) ||
1091             !tomoyo_get_realpath(&buf2, path2))
1092                 goto out;
1093         switch (operation) {
1094                 struct dentry *dentry;
1095         case TOMOYO_TYPE_RENAME:
1096         case TOMOYO_TYPE_LINK:
1097                 dentry = path1->dentry;
1098                 if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode))
1099                         break;
1100                 /* fall through */
1101         case TOMOYO_TYPE_PIVOT_ROOT:
1102                 tomoyo_add_slash(&buf1);
1103                 tomoyo_add_slash(&buf2);
1104                 break;
1105         }
1106         r.param_type = TOMOYO_TYPE_PATH2_ACL;
1107         r.param.path2.operation = operation;
1108         r.param.path2.filename1 = &buf1;
1109         r.param.path2.filename2 = &buf2;
1110         do {
1111                 tomoyo_check_acl(&r, tomoyo_check_path2_acl);
1112                 error = tomoyo_audit_path2_log(&r);
1113         } while (error == TOMOYO_RETRY_REQUEST);
1114  out:
1115         kfree(buf1.name);
1116         kfree(buf2.name);
1117         tomoyo_read_unlock(idx);
1118         if (r.mode != TOMOYO_CONFIG_ENFORCING)
1119                 error = 0;
1120         return error;
1121 }
1122
1123 /**
1124  * tomoyo_write_file_policy - Update file related list.
1125  *
1126  * @data:      String to parse.
1127  * @domain:    Pointer to "struct tomoyo_domain_info".
1128  * @is_delete: True if it is a delete request.
1129  *
1130  * Returns 0 on success, negative value otherwise.
1131  *
1132  * Caller holds tomoyo_read_lock().
1133  */
1134 int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
1135                              const bool is_delete)
1136 {
1137         char *w[5];
1138         u8 type;
1139         if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
1140                 return -EINVAL;
1141         if (strncmp(w[0], "allow_", 6))
1142                 goto out;
1143         w[0] += 6;
1144         for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) {
1145                 if (strcmp(w[0], tomoyo_path_keyword[type]))
1146                         continue;
1147                 return tomoyo_update_path_acl(type, w[1], domain, is_delete);
1148         }
1149         if (!w[2][0])
1150                 goto out;
1151         for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) {
1152                 if (strcmp(w[0], tomoyo_path2_keyword[type]))
1153                         continue;
1154                 return tomoyo_update_path2_acl(type, w[1], w[2], domain,
1155                                                is_delete);
1156         }
1157         for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) {
1158                 if (strcmp(w[0], tomoyo_path_number_keyword[type]))
1159                         continue;
1160                 return tomoyo_update_path_number_acl(type, w[1], w[2], domain,
1161                                                      is_delete);
1162         }
1163         if (!w[3][0] || !w[4][0])
1164                 goto out;
1165         for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) {
1166                 if (strcmp(w[0], tomoyo_mkdev_keyword[type]))
1167                         continue;
1168                 return tomoyo_update_mkdev_acl(type, w[1], w[2], w[3],
1169                                                w[4], domain, is_delete);
1170         }
1171  out:
1172         return -EINVAL;
1173 }