]> Pileus Git - ~andy/linux/blob - security/tomoyo/file.c
TOMOYO: Use struct for passing ACL line.
[~andy/linux] / 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_EXECUTE]    = "execute",
15         [TOMOYO_TYPE_READ]       = "read",
16         [TOMOYO_TYPE_WRITE]      = "write",
17         [TOMOYO_TYPE_APPEND]     = "append",
18         [TOMOYO_TYPE_UNLINK]     = "unlink",
19         [TOMOYO_TYPE_GETATTR]    = "getattr",
20         [TOMOYO_TYPE_RMDIR]      = "rmdir",
21         [TOMOYO_TYPE_TRUNCATE]   = "truncate",
22         [TOMOYO_TYPE_SYMLINK]    = "symlink",
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 /*
53  * Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index".
54  */
55 static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
56         [TOMOYO_TYPE_EXECUTE]    = TOMOYO_MAC_FILE_EXECUTE,
57         [TOMOYO_TYPE_READ]       = TOMOYO_MAC_FILE_OPEN,
58         [TOMOYO_TYPE_WRITE]      = TOMOYO_MAC_FILE_OPEN,
59         [TOMOYO_TYPE_APPEND]     = TOMOYO_MAC_FILE_OPEN,
60         [TOMOYO_TYPE_UNLINK]     = TOMOYO_MAC_FILE_UNLINK,
61         [TOMOYO_TYPE_GETATTR]    = TOMOYO_MAC_FILE_GETATTR,
62         [TOMOYO_TYPE_RMDIR]      = TOMOYO_MAC_FILE_RMDIR,
63         [TOMOYO_TYPE_TRUNCATE]   = TOMOYO_MAC_FILE_TRUNCATE,
64         [TOMOYO_TYPE_SYMLINK]    = TOMOYO_MAC_FILE_SYMLINK,
65         [TOMOYO_TYPE_CHROOT]     = TOMOYO_MAC_FILE_CHROOT,
66         [TOMOYO_TYPE_UMOUNT]     = TOMOYO_MAC_FILE_UMOUNT,
67 };
68
69 /*
70  * Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index".
71  */
72 static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
73         [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK,
74         [TOMOYO_TYPE_MKCHAR]  = TOMOYO_MAC_FILE_MKCHAR,
75 };
76
77 /*
78  * Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index".
79  */
80 static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
81         [TOMOYO_TYPE_LINK]       = TOMOYO_MAC_FILE_LINK,
82         [TOMOYO_TYPE_RENAME]     = TOMOYO_MAC_FILE_RENAME,
83         [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT,
84 };
85
86 /*
87  * Mapping table from "enum tomoyo_path_number_acl_index" to
88  * "enum tomoyo_mac_index".
89  */
90 static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
91         [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE,
92         [TOMOYO_TYPE_MKDIR]  = TOMOYO_MAC_FILE_MKDIR,
93         [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO,
94         [TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK,
95         [TOMOYO_TYPE_IOCTL]  = TOMOYO_MAC_FILE_IOCTL,
96         [TOMOYO_TYPE_CHMOD]  = TOMOYO_MAC_FILE_CHMOD,
97         [TOMOYO_TYPE_CHOWN]  = TOMOYO_MAC_FILE_CHOWN,
98         [TOMOYO_TYPE_CHGRP]  = TOMOYO_MAC_FILE_CHGRP,
99 };
100
101 /**
102  * tomoyo_put_name_union - Drop reference on "struct tomoyo_name_union".
103  *
104  * @ptr: Pointer to "struct tomoyo_name_union".
105  *
106  * Returns nothing.
107  */
108 void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
109 {
110         tomoyo_put_group(ptr->group);
111         tomoyo_put_name(ptr->filename);
112 }
113
114 /**
115  * tomoyo_compare_name_union - Check whether a name matches "struct tomoyo_name_union" or not.
116  *
117  * @name: Pointer to "struct tomoyo_path_info".
118  * @ptr:  Pointer to "struct tomoyo_name_union".
119  *
120  * Returns "struct tomoyo_path_info" if @name matches @ptr, NULL otherwise.
121  */
122 const struct tomoyo_path_info *
123 tomoyo_compare_name_union(const struct tomoyo_path_info *name,
124                           const struct tomoyo_name_union *ptr)
125 {
126         if (ptr->group)
127                 return tomoyo_path_matches_group(name, ptr->group);
128         if (tomoyo_path_matches_pattern(name, ptr->filename))
129                 return ptr->filename;
130         return NULL;
131 }
132
133 /**
134  * tomoyo_put_number_union - Drop reference on "struct tomoyo_number_union".
135  *
136  * @ptr: Pointer to "struct tomoyo_number_union".
137  *
138  * Returns nothing.
139  */
140 void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
141 {
142         tomoyo_put_group(ptr->group);
143 }
144
145 /**
146  * tomoyo_compare_number_union - Check whether a value matches "struct tomoyo_number_union" or not.
147  *
148  * @value: Number to check.
149  * @ptr:   Pointer to "struct tomoyo_number_union".
150  *
151  * Returns true if @value matches @ptr, false otherwise.
152  */
153 bool tomoyo_compare_number_union(const unsigned long value,
154                                  const struct tomoyo_number_union *ptr)
155 {
156         if (ptr->group)
157                 return tomoyo_number_matches_group(value, value, ptr->group);
158         return value >= ptr->values[0] && value <= ptr->values[1];
159 }
160
161 /**
162  * tomoyo_add_slash - Add trailing '/' if needed.
163  *
164  * @buf: Pointer to "struct tomoyo_path_info".
165  *
166  * Returns nothing.
167  *
168  * @buf must be generated by tomoyo_encode() because this function does not
169  * allocate memory for adding '/'.
170  */
171 static void tomoyo_add_slash(struct tomoyo_path_info *buf)
172 {
173         if (buf->is_dir)
174                 return;
175         /*
176          * This is OK because tomoyo_encode() reserves space for appending "/".
177          */
178         strcat((char *) buf->name, "/");
179         tomoyo_fill_path_info(buf);
180 }
181
182 /**
183  * tomoyo_get_realpath - Get realpath.
184  *
185  * @buf:  Pointer to "struct tomoyo_path_info".
186  * @path: Pointer to "struct path".
187  *
188  * Returns true on success, false otherwise.
189  */
190 static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path)
191 {
192         buf->name = tomoyo_realpath_from_path(path);
193         if (buf->name) {
194                 tomoyo_fill_path_info(buf);
195                 return true;
196         }
197         return false;
198 }
199
200 /**
201  * tomoyo_audit_path_log - Audit path request log.
202  *
203  * @r: Pointer to "struct tomoyo_request_info".
204  *
205  * Returns 0 on success, negative value otherwise.
206  */
207 static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
208 {
209         const char *operation = tomoyo_path_keyword[r->param.path.operation];
210         const struct tomoyo_path_info *filename = r->param.path.filename;
211         if (r->granted)
212                 return 0;
213         tomoyo_warn_log(r, "%s %s", operation, filename->name);
214         return tomoyo_supervisor(r, "allow_%s %s\n", operation,
215                                  filename->name);
216 }
217
218 /**
219  * tomoyo_audit_path2_log - Audit path/path request log.
220  *
221  * @r: Pointer to "struct tomoyo_request_info".
222  *
223  * Returns 0 on success, negative value otherwise.
224  */
225 static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
226 {
227         const char *operation = tomoyo_path2_keyword[r->param.path2.operation];
228         const struct tomoyo_path_info *filename1 = r->param.path2.filename1;
229         const struct tomoyo_path_info *filename2 = r->param.path2.filename2;
230         if (r->granted)
231                 return 0;
232         tomoyo_warn_log(r, "%s %s %s", operation, filename1->name,
233                         filename2->name);
234         return tomoyo_supervisor(r, "allow_%s %s %s\n", operation,
235                                  filename1->name, filename2->name);
236 }
237
238 /**
239  * tomoyo_audit_mkdev_log - Audit path/number/number/number request log.
240  *
241  * @r: Pointer to "struct tomoyo_request_info".
242  *
243  * Returns 0 on success, negative value otherwise.
244  */
245 static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r)
246 {
247         const char *operation = tomoyo_mkdev_keyword[r->param.mkdev.operation];
248         const struct tomoyo_path_info *filename = r->param.mkdev.filename;
249         const unsigned int major = r->param.mkdev.major;
250         const unsigned int minor = r->param.mkdev.minor;
251         const unsigned int mode = r->param.mkdev.mode;
252         if (r->granted)
253                 return 0;
254         tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode,
255                         major, minor);
256         return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation,
257                                  filename->name, mode, major, minor);
258 }
259
260 /**
261  * tomoyo_audit_path_number_log - Audit path/number request log.
262  *
263  * @r: Pointer to "struct tomoyo_request_info".
264  *
265  * Returns 0 on success, negative value otherwise.
266  */
267 static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
268 {
269         const u8 type = r->param.path_number.operation;
270         u8 radix;
271         const struct tomoyo_path_info *filename = r->param.path_number.filename;
272         const char *operation = tomoyo_path_number_keyword[type];
273         char buffer[64];
274         if (r->granted)
275                 return 0;
276         switch (type) {
277         case TOMOYO_TYPE_CREATE:
278         case TOMOYO_TYPE_MKDIR:
279         case TOMOYO_TYPE_MKFIFO:
280         case TOMOYO_TYPE_MKSOCK:
281         case TOMOYO_TYPE_CHMOD:
282                 radix = TOMOYO_VALUE_TYPE_OCTAL;
283                 break;
284         case TOMOYO_TYPE_IOCTL:
285                 radix = TOMOYO_VALUE_TYPE_HEXADECIMAL;
286                 break;
287         default:
288                 radix = TOMOYO_VALUE_TYPE_DECIMAL;
289                 break;
290         }
291         tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number,
292                            radix);
293         tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer);
294         return tomoyo_supervisor(r, "allow_%s %s %s\n", operation,
295                                  filename->name, buffer);
296 }
297
298 /**
299  * tomoyo_check_path_acl - Check permission for path operation.
300  *
301  * @r:   Pointer to "struct tomoyo_request_info".
302  * @ptr: Pointer to "struct tomoyo_acl_info".
303  *
304  * Returns true if granted, false otherwise.
305  *
306  * To be able to use wildcard for domain transition, this function sets
307  * matching entry on success. Since the caller holds tomoyo_read_lock(),
308  * it is safe to set matching entry.
309  */
310 static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
311                                   const struct tomoyo_acl_info *ptr)
312 {
313         const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl),
314                                                          head);
315         if (acl->perm & (1 << r->param.path.operation)) {
316                 r->param.path.matched_path =
317                         tomoyo_compare_name_union(r->param.path.filename,
318                                                   &acl->name);
319                 return r->param.path.matched_path != NULL;
320         }
321         return false;
322 }
323
324 /**
325  * tomoyo_check_path_number_acl - Check permission for path number operation.
326  *
327  * @r:   Pointer to "struct tomoyo_request_info".
328  * @ptr: Pointer to "struct tomoyo_acl_info".
329  *
330  * Returns true if granted, false otherwise.
331  */
332 static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
333                                          const struct tomoyo_acl_info *ptr)
334 {
335         const struct tomoyo_path_number_acl *acl =
336                 container_of(ptr, typeof(*acl), head);
337         return (acl->perm & (1 << r->param.path_number.operation)) &&
338                 tomoyo_compare_number_union(r->param.path_number.number,
339                                             &acl->number) &&
340                 tomoyo_compare_name_union(r->param.path_number.filename,
341                                           &acl->name);
342 }
343
344 /**
345  * tomoyo_check_path2_acl - Check permission for path path operation.
346  *
347  * @r:   Pointer to "struct tomoyo_request_info".
348  * @ptr: Pointer to "struct tomoyo_acl_info".
349  *
350  * Returns true if granted, false otherwise.
351  */
352 static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
353                                    const struct tomoyo_acl_info *ptr)
354 {
355         const struct tomoyo_path2_acl *acl =
356                 container_of(ptr, typeof(*acl), head);
357         return (acl->perm & (1 << r->param.path2.operation)) &&
358                 tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1)
359                 && tomoyo_compare_name_union(r->param.path2.filename2,
360                                              &acl->name2);
361 }
362
363 /**
364  * tomoyo_check_mkdev_acl - Check permission for path number number number operation.
365  *
366  * @r:   Pointer to "struct tomoyo_request_info".
367  * @ptr: Pointer to "struct tomoyo_acl_info".
368  *
369  * Returns true if granted, false otherwise.
370  */
371 static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
372                                    const struct tomoyo_acl_info *ptr)
373 {
374         const struct tomoyo_mkdev_acl *acl =
375                 container_of(ptr, typeof(*acl), head);
376         return (acl->perm & (1 << r->param.mkdev.operation)) &&
377                 tomoyo_compare_number_union(r->param.mkdev.mode,
378                                             &acl->mode) &&
379                 tomoyo_compare_number_union(r->param.mkdev.major,
380                                             &acl->major) &&
381                 tomoyo_compare_number_union(r->param.mkdev.minor,
382                                             &acl->minor) &&
383                 tomoyo_compare_name_union(r->param.mkdev.filename,
384                                           &acl->name);
385 }
386
387 /**
388  * tomoyo_same_path_acl - Check for duplicated "struct tomoyo_path_acl" entry.
389  *
390  * @a: Pointer to "struct tomoyo_acl_info".
391  * @b: Pointer to "struct tomoyo_acl_info".
392  *
393  * Returns true if @a == @b except permission bits, false otherwise.
394  */
395 static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
396                                  const struct tomoyo_acl_info *b)
397 {
398         const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
399         const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
400         return tomoyo_same_name_union(&p1->name, &p2->name);
401 }
402
403 /**
404  * tomoyo_merge_path_acl - Merge duplicated "struct tomoyo_path_acl" entry.
405  *
406  * @a:         Pointer to "struct tomoyo_acl_info".
407  * @b:         Pointer to "struct tomoyo_acl_info".
408  * @is_delete: True for @a &= ~@b, false for @a |= @b.
409  *
410  * Returns true if @a is empty, false otherwise.
411  */
412 static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
413                                   struct tomoyo_acl_info *b,
414                                   const bool is_delete)
415 {
416         u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
417                 ->perm;
418         u16 perm = *a_perm;
419         const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
420         if (is_delete)
421                 perm &= ~b_perm;
422         else
423                 perm |= b_perm;
424         *a_perm = perm;
425         return !perm;
426 }
427
428 /**
429  * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
430  *
431  * @perm:  Permission.
432  * @param: Pointer to "struct tomoyo_acl_param".
433  *
434  * Returns 0 on success, negative value otherwise.
435  *
436  * Caller holds tomoyo_read_lock().
437  */
438 static int tomoyo_update_path_acl(const u16 perm,
439                                   struct tomoyo_acl_param *param)
440 {
441         struct tomoyo_path_acl e = {
442                 .head.type = TOMOYO_TYPE_PATH_ACL,
443                 .perm = perm
444         };
445         int error;
446         if (!tomoyo_parse_name_union(param, &e.name))
447                 error = -EINVAL;
448         else
449                 error = tomoyo_update_domain(&e.head, sizeof(e), param,
450                                              tomoyo_same_path_acl,
451                                              tomoyo_merge_path_acl);
452         tomoyo_put_name_union(&e.name);
453         return error;
454 }
455
456 /**
457  * tomoyo_same_mkdev_acl - Check for duplicated "struct tomoyo_mkdev_acl" entry.
458  *
459  * @a: Pointer to "struct tomoyo_acl_info".
460  * @b: Pointer to "struct tomoyo_acl_info".
461  *
462  * Returns true if @a == @b except permission bits, false otherwise.
463  */
464 static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
465                                          const struct tomoyo_acl_info *b)
466 {
467         const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head);
468         const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head);
469         return tomoyo_same_name_union(&p1->name, &p2->name) &&
470                 tomoyo_same_number_union(&p1->mode, &p2->mode) &&
471                 tomoyo_same_number_union(&p1->major, &p2->major) &&
472                 tomoyo_same_number_union(&p1->minor, &p2->minor);
473 }
474
475 /**
476  * tomoyo_merge_mkdev_acl - Merge duplicated "struct tomoyo_mkdev_acl" entry.
477  *
478  * @a:         Pointer to "struct tomoyo_acl_info".
479  * @b:         Pointer to "struct tomoyo_acl_info".
480  * @is_delete: True for @a &= ~@b, false for @a |= @b.
481  *
482  * Returns true if @a is empty, false otherwise.
483  */
484 static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
485                                    struct tomoyo_acl_info *b,
486                                    const bool is_delete)
487 {
488         u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
489                                          head)->perm;
490         u8 perm = *a_perm;
491         const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head)
492                 ->perm;
493         if (is_delete)
494                 perm &= ~b_perm;
495         else
496                 perm |= b_perm;
497         *a_perm = perm;
498         return !perm;
499 }
500
501 /**
502  * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list.
503  *
504  * @perm:  Permission.
505  * @param: Pointer to "struct tomoyo_acl_param".
506  *
507  * Returns 0 on success, negative value otherwise.
508  *
509  * Caller holds tomoyo_read_lock().
510  */
511 static int tomoyo_update_mkdev_acl(const u8 perm,
512                                    struct tomoyo_acl_param *param)
513 {
514         struct tomoyo_mkdev_acl e = {
515                 .head.type = TOMOYO_TYPE_MKDEV_ACL,
516                 .perm = perm
517         };
518         int error;
519         if (!tomoyo_parse_name_union(param, &e.name) ||
520             !tomoyo_parse_number_union(param, &e.mode) ||
521             !tomoyo_parse_number_union(param, &e.major) ||
522             !tomoyo_parse_number_union(param, &e.minor))
523                 error = -EINVAL;
524         else
525                 error = tomoyo_update_domain(&e.head, sizeof(e), param,
526                                              tomoyo_same_mkdev_acl,
527                                              tomoyo_merge_mkdev_acl);
528         tomoyo_put_name_union(&e.name);
529         tomoyo_put_number_union(&e.mode);
530         tomoyo_put_number_union(&e.major);
531         tomoyo_put_number_union(&e.minor);
532         return error;
533 }
534
535 /**
536  * tomoyo_same_path2_acl - Check for duplicated "struct tomoyo_path2_acl" entry.
537  *
538  * @a: Pointer to "struct tomoyo_acl_info".
539  * @b: Pointer to "struct tomoyo_acl_info".
540  *
541  * Returns true if @a == @b except permission bits, false otherwise.
542  */
543 static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
544                                   const struct tomoyo_acl_info *b)
545 {
546         const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
547         const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
548         return tomoyo_same_name_union(&p1->name1, &p2->name1) &&
549                 tomoyo_same_name_union(&p1->name2, &p2->name2);
550 }
551
552 /**
553  * tomoyo_merge_path2_acl - Merge duplicated "struct tomoyo_path2_acl" entry.
554  *
555  * @a:         Pointer to "struct tomoyo_acl_info".
556  * @b:         Pointer to "struct tomoyo_acl_info".
557  * @is_delete: True for @a &= ~@b, false for @a |= @b.
558  *
559  * Returns true if @a is empty, false otherwise.
560  */
561 static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
562                                    struct tomoyo_acl_info *b,
563                                    const bool is_delete)
564 {
565         u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
566                 ->perm;
567         u8 perm = *a_perm;
568         const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
569         if (is_delete)
570                 perm &= ~b_perm;
571         else
572                 perm |= b_perm;
573         *a_perm = perm;
574         return !perm;
575 }
576
577 /**
578  * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
579  *
580  * @perm:  Permission.
581  * @param: Pointer to "struct tomoyo_acl_param".
582  *
583  * Returns 0 on success, negative value otherwise.
584  *
585  * Caller holds tomoyo_read_lock().
586  */
587 static int tomoyo_update_path2_acl(const u8 perm,
588                                    struct tomoyo_acl_param *param)
589 {
590         struct tomoyo_path2_acl e = {
591                 .head.type = TOMOYO_TYPE_PATH2_ACL,
592                 .perm = perm
593         };
594         int error;
595         if (!tomoyo_parse_name_union(param, &e.name1) ||
596             !tomoyo_parse_name_union(param, &e.name2))
597                 error = -EINVAL;
598         else
599                 error = tomoyo_update_domain(&e.head, sizeof(e), param,
600                                              tomoyo_same_path2_acl,
601                                              tomoyo_merge_path2_acl);
602         tomoyo_put_name_union(&e.name1);
603         tomoyo_put_name_union(&e.name2);
604         return error;
605 }
606
607 /**
608  * tomoyo_path_permission - Check permission for single path operation.
609  *
610  * @r:         Pointer to "struct tomoyo_request_info".
611  * @operation: Type of operation.
612  * @filename:  Filename to check.
613  *
614  * Returns 0 on success, negative value otherwise.
615  *
616  * Caller holds tomoyo_read_lock().
617  */
618 int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
619                            const struct tomoyo_path_info *filename)
620 {
621         int error;
622
623         r->type = tomoyo_p2mac[operation];
624         r->mode = tomoyo_get_mode(r->profile, r->type);
625         if (r->mode == TOMOYO_CONFIG_DISABLED)
626                 return 0;
627         r->param_type = TOMOYO_TYPE_PATH_ACL;
628         r->param.path.filename = filename;
629         r->param.path.operation = operation;
630         do {
631                 tomoyo_check_acl(r, tomoyo_check_path_acl);
632                 error = tomoyo_audit_path_log(r);
633                 /*
634                  * Do not retry for execute request, for alias may have
635                  * changed.
636                  */
637         } while (error == TOMOYO_RETRY_REQUEST &&
638                  operation != TOMOYO_TYPE_EXECUTE);
639         return error;
640 }
641
642 /**
643  * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry.
644  *
645  * @a: Pointer to "struct tomoyo_acl_info".
646  * @b: Pointer to "struct tomoyo_acl_info".
647  *
648  * Returns true if @a == @b except permission bits, false otherwise.
649  */
650 static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
651                                         const struct tomoyo_acl_info *b)
652 {
653         const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1),
654                                                                head);
655         const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
656                                                                head);
657         return tomoyo_same_name_union(&p1->name, &p2->name) &&
658                 tomoyo_same_number_union(&p1->number, &p2->number);
659 }
660
661 /**
662  * tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry.
663  *
664  * @a:         Pointer to "struct tomoyo_acl_info".
665  * @b:         Pointer to "struct tomoyo_acl_info".
666  * @is_delete: True for @a &= ~@b, false for @a |= @b.
667  *
668  * Returns true if @a is empty, false otherwise.
669  */
670 static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
671                                          struct tomoyo_acl_info *b,
672                                          const bool is_delete)
673 {
674         u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl,
675                                           head)->perm;
676         u8 perm = *a_perm;
677         const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
678                 ->perm;
679         if (is_delete)
680                 perm &= ~b_perm;
681         else
682                 perm |= b_perm;
683         *a_perm = perm;
684         return !perm;
685 }
686
687 /**
688  * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
689  *
690  * @perm:  Permission.
691  * @param: Pointer to "struct tomoyo_acl_param".
692  *
693  * Returns 0 on success, negative value otherwise.
694  */
695 static int tomoyo_update_path_number_acl(const u8 perm,
696                                          struct tomoyo_acl_param *param)
697 {
698         struct tomoyo_path_number_acl e = {
699                 .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
700                 .perm = perm
701         };
702         int error;
703         if (!tomoyo_parse_name_union(param, &e.name) ||
704             !tomoyo_parse_number_union(param, &e.number))
705                 error = -EINVAL;
706         else
707                 error = tomoyo_update_domain(&e.head, sizeof(e), param,
708                                              tomoyo_same_path_number_acl,
709                                              tomoyo_merge_path_number_acl);
710         tomoyo_put_name_union(&e.name);
711         tomoyo_put_number_union(&e.number);
712         return error;
713 }
714
715 /**
716  * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp".
717  *
718  * @type:   Type of operation.
719  * @path:   Pointer to "struct path".
720  * @number: Number.
721  *
722  * Returns 0 on success, negative value otherwise.
723  */
724 int tomoyo_path_number_perm(const u8 type, struct path *path,
725                             unsigned long number)
726 {
727         struct tomoyo_request_info r;
728         int error = -ENOMEM;
729         struct tomoyo_path_info buf;
730         int idx;
731
732         if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type])
733             == TOMOYO_CONFIG_DISABLED || !path->mnt || !path->dentry)
734                 return 0;
735         idx = tomoyo_read_lock();
736         if (!tomoyo_get_realpath(&buf, path))
737                 goto out;
738         if (type == TOMOYO_TYPE_MKDIR)
739                 tomoyo_add_slash(&buf);
740         r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
741         r.param.path_number.operation = type;
742         r.param.path_number.filename = &buf;
743         r.param.path_number.number = number;
744         do {
745                 tomoyo_check_acl(&r, tomoyo_check_path_number_acl);
746                 error = tomoyo_audit_path_number_log(&r);
747         } while (error == TOMOYO_RETRY_REQUEST);
748         kfree(buf.name);
749  out:
750         tomoyo_read_unlock(idx);
751         if (r.mode != TOMOYO_CONFIG_ENFORCING)
752                 error = 0;
753         return error;
754 }
755
756 /**
757  * tomoyo_check_open_permission - Check permission for "read" and "write".
758  *
759  * @domain: Pointer to "struct tomoyo_domain_info".
760  * @path:   Pointer to "struct path".
761  * @flag:   Flags for open().
762  *
763  * Returns 0 on success, negative value otherwise.
764  */
765 int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
766                                  struct path *path, const int flag)
767 {
768         const u8 acc_mode = ACC_MODE(flag);
769         int error = 0;
770         struct tomoyo_path_info buf;
771         struct tomoyo_request_info r;
772         int idx;
773
774         if (!path->mnt)
775                 return 0;
776         buf.name = NULL;
777         r.mode = TOMOYO_CONFIG_DISABLED;
778         idx = tomoyo_read_lock();
779         if (acc_mode &&
780             tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
781             != TOMOYO_CONFIG_DISABLED) {
782                 if (!tomoyo_get_realpath(&buf, path)) {
783                         error = -ENOMEM;
784                         goto out;
785                 }
786                 if (acc_mode & MAY_READ)
787                         error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ,
788                                                        &buf);
789                 if (!error && (acc_mode & MAY_WRITE))
790                         error = tomoyo_path_permission(&r, (flag & O_APPEND) ?
791                                                        TOMOYO_TYPE_APPEND :
792                                                        TOMOYO_TYPE_WRITE,
793                                                        &buf);
794         }
795  out:
796         kfree(buf.name);
797         tomoyo_read_unlock(idx);
798         if (r.mode != TOMOYO_CONFIG_ENFORCING)
799                 error = 0;
800         return error;
801 }
802
803 /**
804  * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount".
805  *
806  * @operation: Type of operation.
807  * @path:      Pointer to "struct path".
808  *
809  * Returns 0 on success, negative value otherwise.
810  */
811 int tomoyo_path_perm(const u8 operation, struct path *path)
812 {
813         struct tomoyo_request_info r;
814         int error;
815         struct tomoyo_path_info buf;
816         bool is_enforce;
817         int idx;
818
819         if (!path->mnt)
820                 return 0;
821         if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
822             == TOMOYO_CONFIG_DISABLED)
823                 return 0;
824         is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING);
825         error = -ENOMEM;
826         buf.name = NULL;
827         idx = tomoyo_read_lock();
828         if (!tomoyo_get_realpath(&buf, path))
829                 goto out;
830         switch (operation) {
831         case TOMOYO_TYPE_RMDIR:
832         case TOMOYO_TYPE_CHROOT:
833                 tomoyo_add_slash(&buf);
834                 break;
835         }
836         error = tomoyo_path_permission(&r, operation, &buf);
837  out:
838         kfree(buf.name);
839         tomoyo_read_unlock(idx);
840         if (!is_enforce)
841                 error = 0;
842         return error;
843 }
844
845 /**
846  * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar".
847  *
848  * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK)
849  * @path:      Pointer to "struct path".
850  * @mode:      Create mode.
851  * @dev:       Device number.
852  *
853  * Returns 0 on success, negative value otherwise.
854  */
855 int tomoyo_mkdev_perm(const u8 operation, struct path *path,
856                       const unsigned int mode, unsigned int dev)
857 {
858         struct tomoyo_request_info r;
859         int error = -ENOMEM;
860         struct tomoyo_path_info buf;
861         int idx;
862
863         if (!path->mnt ||
864             tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
865             == TOMOYO_CONFIG_DISABLED)
866                 return 0;
867         idx = tomoyo_read_lock();
868         error = -ENOMEM;
869         if (tomoyo_get_realpath(&buf, path)) {
870                 dev = new_decode_dev(dev);
871                 r.param_type = TOMOYO_TYPE_MKDEV_ACL;
872                 r.param.mkdev.filename = &buf;
873                 r.param.mkdev.operation = operation;
874                 r.param.mkdev.mode = mode;
875                 r.param.mkdev.major = MAJOR(dev);
876                 r.param.mkdev.minor = MINOR(dev);
877                 tomoyo_check_acl(&r, tomoyo_check_mkdev_acl);
878                 error = tomoyo_audit_mkdev_log(&r);
879                 kfree(buf.name);
880         }
881         tomoyo_read_unlock(idx);
882         if (r.mode != TOMOYO_CONFIG_ENFORCING)
883                 error = 0;
884         return error;
885 }
886
887 /**
888  * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root".
889  *
890  * @operation: Type of operation.
891  * @path1:      Pointer to "struct path".
892  * @path2:      Pointer to "struct path".
893  *
894  * Returns 0 on success, negative value otherwise.
895  */
896 int tomoyo_path2_perm(const u8 operation, struct path *path1,
897                       struct path *path2)
898 {
899         int error = -ENOMEM;
900         struct tomoyo_path_info buf1;
901         struct tomoyo_path_info buf2;
902         struct tomoyo_request_info r;
903         int idx;
904
905         if (!path1->mnt || !path2->mnt ||
906             tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
907             == TOMOYO_CONFIG_DISABLED)
908                 return 0;
909         buf1.name = NULL;
910         buf2.name = NULL;
911         idx = tomoyo_read_lock();
912         if (!tomoyo_get_realpath(&buf1, path1) ||
913             !tomoyo_get_realpath(&buf2, path2))
914                 goto out;
915         switch (operation) {
916                 struct dentry *dentry;
917         case TOMOYO_TYPE_RENAME:
918         case TOMOYO_TYPE_LINK:
919                 dentry = path1->dentry;
920                 if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode))
921                         break;
922                 /* fall through */
923         case TOMOYO_TYPE_PIVOT_ROOT:
924                 tomoyo_add_slash(&buf1);
925                 tomoyo_add_slash(&buf2);
926                 break;
927         }
928         r.param_type = TOMOYO_TYPE_PATH2_ACL;
929         r.param.path2.operation = operation;
930         r.param.path2.filename1 = &buf1;
931         r.param.path2.filename2 = &buf2;
932         do {
933                 tomoyo_check_acl(&r, tomoyo_check_path2_acl);
934                 error = tomoyo_audit_path2_log(&r);
935         } while (error == TOMOYO_RETRY_REQUEST);
936  out:
937         kfree(buf1.name);
938         kfree(buf2.name);
939         tomoyo_read_unlock(idx);
940         if (r.mode != TOMOYO_CONFIG_ENFORCING)
941                 error = 0;
942         return error;
943 }
944
945 /**
946  * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry.
947  *
948  * @a: Pointer to "struct tomoyo_acl_info".
949  * @b: Pointer to "struct tomoyo_acl_info".
950  *
951  * Returns true if @a == @b, false otherwise.
952  */
953 static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
954                                   const struct tomoyo_acl_info *b)
955 {
956         const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
957         const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
958         return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
959                 tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) &&
960                 tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) &&
961                 tomoyo_same_number_union(&p1->flags, &p2->flags);
962 }
963
964 /**
965  * tomoyo_update_mount_acl - Write "struct tomoyo_mount_acl" list.
966  *
967  * @param: Pointer to "struct tomoyo_acl_param".
968  *
969  * Returns 0 on success, negative value otherwise.
970  *
971  * Caller holds tomoyo_read_lock().
972  */
973 static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param)
974 {
975         struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
976         int error;
977         if (!tomoyo_parse_name_union(param, &e.dev_name) ||
978             !tomoyo_parse_name_union(param, &e.dir_name) ||
979             !tomoyo_parse_name_union(param, &e.fs_type) ||
980             !tomoyo_parse_number_union(param, &e.flags))
981                 error = -EINVAL;
982         else
983                 error = tomoyo_update_domain(&e.head, sizeof(e), param,
984                                              tomoyo_same_mount_acl, NULL);
985         tomoyo_put_name_union(&e.dev_name);
986         tomoyo_put_name_union(&e.dir_name);
987         tomoyo_put_name_union(&e.fs_type);
988         tomoyo_put_number_union(&e.flags);
989         return error;
990 }
991
992 /**
993  * tomoyo_write_file - Update file related list.
994  *
995  * @param: Pointer to "struct tomoyo_acl_param".
996  *
997  * Returns 0 on success, negative value otherwise.
998  *
999  * Caller holds tomoyo_read_lock().
1000  */
1001 int tomoyo_write_file(struct tomoyo_acl_param *param)
1002 {
1003         u16 perm = 0;
1004         u8 type;
1005         const char *operation = tomoyo_read_token(param);
1006         for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++)
1007                 if (tomoyo_permstr(operation, tomoyo_path_keyword[type]))
1008                         perm |= 1 << type;
1009         if (perm)
1010                 return tomoyo_update_path_acl(perm, param);
1011         for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++)
1012                 if (tomoyo_permstr(operation, tomoyo_path2_keyword[type]))
1013                         perm |= 1 << type;
1014         if (perm)
1015                 return tomoyo_update_path2_acl(perm, param);
1016         for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++)
1017                 if (tomoyo_permstr(operation,
1018                                    tomoyo_path_number_keyword[type]))
1019                         perm |= 1 << type;
1020         if (perm)
1021                 return tomoyo_update_path_number_acl(perm, param);
1022         for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++)
1023                 if (tomoyo_permstr(operation, tomoyo_mkdev_keyword[type]))
1024                         perm |= 1 << type;
1025         if (perm)
1026                 return tomoyo_update_mkdev_acl(perm, param);
1027         if (tomoyo_permstr(operation, "mount"))
1028                 return tomoyo_update_mount_acl(param);
1029         return -EINVAL;
1030 }