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