adf786d7421db1984e628a6fbaebea9bafb433ca
[safe/jmp/linux-2.6] / security / tomoyo / file.c
1 /*
2  * security/tomoyo/file.c
3  *
4  * Implementation of the Domain-Based Mandatory Access Control.
5  *
6  * Copyright (C) 2005-2009  NTT DATA CORPORATION
7  *
8  * Version: 2.2.0   2009/04/01
9  *
10  */
11
12 #include "common.h"
13 #include "tomoyo.h"
14 #include "realpath.h"
15 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
16
17 /* Structure for "allow_read" keyword. */
18 struct tomoyo_globally_readable_file_entry {
19         struct list_head list;
20         const struct tomoyo_path_info *filename;
21         bool is_deleted;
22 };
23
24 /* Structure for "file_pattern" keyword. */
25 struct tomoyo_pattern_entry {
26         struct list_head list;
27         const struct tomoyo_path_info *pattern;
28         bool is_deleted;
29 };
30
31 /* Structure for "deny_rewrite" keyword. */
32 struct tomoyo_no_rewrite_entry {
33         struct list_head list;
34         const struct tomoyo_path_info *pattern;
35         bool is_deleted;
36 };
37
38 /* Keyword array for single path operations. */
39 static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = {
40         [TOMOYO_TYPE_READ_WRITE_ACL] = "read/write",
41         [TOMOYO_TYPE_EXECUTE_ACL]    = "execute",
42         [TOMOYO_TYPE_READ_ACL]       = "read",
43         [TOMOYO_TYPE_WRITE_ACL]      = "write",
44         [TOMOYO_TYPE_CREATE_ACL]     = "create",
45         [TOMOYO_TYPE_UNLINK_ACL]     = "unlink",
46         [TOMOYO_TYPE_MKDIR_ACL]      = "mkdir",
47         [TOMOYO_TYPE_RMDIR_ACL]      = "rmdir",
48         [TOMOYO_TYPE_MKFIFO_ACL]     = "mkfifo",
49         [TOMOYO_TYPE_MKSOCK_ACL]     = "mksock",
50         [TOMOYO_TYPE_MKBLOCK_ACL]    = "mkblock",
51         [TOMOYO_TYPE_MKCHAR_ACL]     = "mkchar",
52         [TOMOYO_TYPE_TRUNCATE_ACL]   = "truncate",
53         [TOMOYO_TYPE_SYMLINK_ACL]    = "symlink",
54         [TOMOYO_TYPE_REWRITE_ACL]    = "rewrite",
55 };
56
57 /* Keyword array for double path operations. */
58 static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = {
59         [TOMOYO_TYPE_LINK_ACL]    = "link",
60         [TOMOYO_TYPE_RENAME_ACL]  = "rename",
61 };
62
63 /**
64  * tomoyo_sp2keyword - Get the name of single path operation.
65  *
66  * @operation: Type of operation.
67  *
68  * Returns the name of single path operation.
69  */
70 const char *tomoyo_sp2keyword(const u8 operation)
71 {
72         return (operation < TOMOYO_MAX_SINGLE_PATH_OPERATION)
73                 ? tomoyo_sp_keyword[operation] : NULL;
74 }
75
76 /**
77  * tomoyo_dp2keyword - Get the name of double path operation.
78  *
79  * @operation: Type of operation.
80  *
81  * Returns the name of double path operation.
82  */
83 const char *tomoyo_dp2keyword(const u8 operation)
84 {
85         return (operation < TOMOYO_MAX_DOUBLE_PATH_OPERATION)
86                 ? tomoyo_dp_keyword[operation] : NULL;
87 }
88
89 /**
90  * tomoyo_strendswith - Check whether the token ends with the given token.
91  *
92  * @name: The token to check.
93  * @tail: The token to find.
94  *
95  * Returns true if @name ends with @tail, false otherwise.
96  */
97 static bool tomoyo_strendswith(const char *name, const char *tail)
98 {
99         int len;
100
101         if (!name || !tail)
102                 return false;
103         len = strlen(name) - strlen(tail);
104         return len >= 0 && !strcmp(name + len, tail);
105 }
106
107 /**
108  * tomoyo_get_path - Get realpath.
109  *
110  * @path: Pointer to "struct path".
111  *
112  * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
113  */
114 static struct tomoyo_path_info *tomoyo_get_path(struct path *path)
115 {
116         int error;
117         struct tomoyo_path_info_with_data *buf = tomoyo_alloc(sizeof(*buf));
118
119         if (!buf)
120                 return NULL;
121         /* Reserve one byte for appending "/". */
122         error = tomoyo_realpath_from_path2(path, buf->body,
123                                            sizeof(buf->body) - 2);
124         if (!error) {
125                 buf->head.name = buf->body;
126                 tomoyo_fill_path_info(&buf->head);
127                 return &buf->head;
128         }
129         tomoyo_free(buf);
130         return NULL;
131 }
132
133 /* Lock for domain->acl_info_list. */
134 DECLARE_RWSEM(tomoyo_domain_acl_info_list_lock);
135
136 static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
137                                          const char *filename2,
138                                          struct tomoyo_domain_info *
139                                          const domain, const bool is_delete);
140 static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
141                                          struct tomoyo_domain_info *
142                                          const domain, const bool is_delete);
143
144 /* The list for "struct tomoyo_globally_readable_file_entry". */
145 static LIST_HEAD(tomoyo_globally_readable_list);
146 static DECLARE_RWSEM(tomoyo_globally_readable_list_lock);
147
148 /**
149  * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list.
150  *
151  * @filename:  Filename unconditionally permitted to open() for reading.
152  * @is_delete: True if it is a delete request.
153  *
154  * Returns 0 on success, negative value otherwise.
155  */
156 static int tomoyo_update_globally_readable_entry(const char *filename,
157                                                  const bool is_delete)
158 {
159         struct tomoyo_globally_readable_file_entry *new_entry;
160         struct tomoyo_globally_readable_file_entry *ptr;
161         const struct tomoyo_path_info *saved_filename;
162         int error = -ENOMEM;
163
164         if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__))
165                 return -EINVAL;
166         saved_filename = tomoyo_save_name(filename);
167         if (!saved_filename)
168                 return -ENOMEM;
169         down_write(&tomoyo_globally_readable_list_lock);
170         list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
171                 if (ptr->filename != saved_filename)
172                         continue;
173                 ptr->is_deleted = is_delete;
174                 error = 0;
175                 goto out;
176         }
177         if (is_delete) {
178                 error = -ENOENT;
179                 goto out;
180         }
181         new_entry = tomoyo_alloc_element(sizeof(*new_entry));
182         if (!new_entry)
183                 goto out;
184         new_entry->filename = saved_filename;
185         list_add_tail(&new_entry->list, &tomoyo_globally_readable_list);
186         error = 0;
187  out:
188         up_write(&tomoyo_globally_readable_list_lock);
189         return error;
190 }
191
192 /**
193  * tomoyo_is_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading.
194  *
195  * @filename: The filename to check.
196  *
197  * Returns true if any domain can open @filename for reading, false otherwise.
198  */
199 static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
200                                              filename)
201 {
202         struct tomoyo_globally_readable_file_entry *ptr;
203         bool found = false;
204         down_read(&tomoyo_globally_readable_list_lock);
205         list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
206                 if (!ptr->is_deleted &&
207                     tomoyo_path_matches_pattern(filename, ptr->filename)) {
208                         found = true;
209                         break;
210                 }
211         }
212         up_read(&tomoyo_globally_readable_list_lock);
213         return found;
214 }
215
216 /**
217  * tomoyo_write_globally_readable_policy - Write "struct tomoyo_globally_readable_file_entry" list.
218  *
219  * @data:      String to parse.
220  * @is_delete: True if it is a delete request.
221  *
222  * Returns 0 on success, negative value otherwise.
223  */
224 int tomoyo_write_globally_readable_policy(char *data, const bool is_delete)
225 {
226         return tomoyo_update_globally_readable_entry(data, is_delete);
227 }
228
229 /**
230  * tomoyo_read_globally_readable_policy - Read "struct tomoyo_globally_readable_file_entry" list.
231  *
232  * @head: Pointer to "struct tomoyo_io_buffer".
233  *
234  * Returns true on success, false otherwise.
235  */
236 bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
237 {
238         struct list_head *pos;
239         bool done = true;
240
241         down_read(&tomoyo_globally_readable_list_lock);
242         list_for_each_cookie(pos, head->read_var2,
243                              &tomoyo_globally_readable_list) {
244                 struct tomoyo_globally_readable_file_entry *ptr;
245                 ptr = list_entry(pos,
246                                  struct tomoyo_globally_readable_file_entry,
247                                  list);
248                 if (ptr->is_deleted)
249                         continue;
250                 if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_READ "%s\n",
251                                       ptr->filename->name)) {
252                         done = false;
253                         break;
254                 }
255         }
256         up_read(&tomoyo_globally_readable_list_lock);
257         return done;
258 }
259
260 /* The list for "struct tomoyo_pattern_entry". */
261 static LIST_HEAD(tomoyo_pattern_list);
262 static DECLARE_RWSEM(tomoyo_pattern_list_lock);
263
264 /**
265  * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list.
266  *
267  * @pattern:   Pathname pattern.
268  * @is_delete: True if it is a delete request.
269  *
270  * Returns 0 on success, negative value otherwise.
271  */
272 static int tomoyo_update_file_pattern_entry(const char *pattern,
273                                             const bool is_delete)
274 {
275         struct tomoyo_pattern_entry *new_entry;
276         struct tomoyo_pattern_entry *ptr;
277         const struct tomoyo_path_info *saved_pattern;
278         int error = -ENOMEM;
279
280         if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__))
281                 return -EINVAL;
282         saved_pattern = tomoyo_save_name(pattern);
283         if (!saved_pattern)
284                 return -ENOMEM;
285         down_write(&tomoyo_pattern_list_lock);
286         list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
287                 if (saved_pattern != ptr->pattern)
288                         continue;
289                 ptr->is_deleted = is_delete;
290                 error = 0;
291                 goto out;
292         }
293         if (is_delete) {
294                 error = -ENOENT;
295                 goto out;
296         }
297         new_entry = tomoyo_alloc_element(sizeof(*new_entry));
298         if (!new_entry)
299                 goto out;
300         new_entry->pattern = saved_pattern;
301         list_add_tail(&new_entry->list, &tomoyo_pattern_list);
302         error = 0;
303  out:
304         up_write(&tomoyo_pattern_list_lock);
305         return error;
306 }
307
308 /**
309  * tomoyo_get_file_pattern - Get patterned pathname.
310  *
311  * @filename: The filename to find patterned pathname.
312  *
313  * Returns pointer to pathname pattern if matched, @filename otherwise.
314  */
315 static const struct tomoyo_path_info *
316 tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
317 {
318         struct tomoyo_pattern_entry *ptr;
319         const struct tomoyo_path_info *pattern = NULL;
320
321         down_read(&tomoyo_pattern_list_lock);
322         list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
323                 if (ptr->is_deleted)
324                         continue;
325                 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
326                         continue;
327                 pattern = ptr->pattern;
328                 if (tomoyo_strendswith(pattern->name, "/\\*")) {
329                         /* Do nothing. Try to find the better match. */
330                 } else {
331                         /* This would be the better match. Use this. */
332                         break;
333                 }
334         }
335         up_read(&tomoyo_pattern_list_lock);
336         if (pattern)
337                 filename = pattern;
338         return filename;
339 }
340
341 /**
342  * tomoyo_write_pattern_policy - Write "struct tomoyo_pattern_entry" list.
343  *
344  * @data:      String to parse.
345  * @is_delete: True if it is a delete request.
346  *
347  * Returns 0 on success, negative value otherwise.
348  */
349 int tomoyo_write_pattern_policy(char *data, const bool is_delete)
350 {
351         return tomoyo_update_file_pattern_entry(data, is_delete);
352 }
353
354 /**
355  * tomoyo_read_file_pattern - Read "struct tomoyo_pattern_entry" list.
356  *
357  * @head: Pointer to "struct tomoyo_io_buffer".
358  *
359  * Returns true on success, false otherwise.
360  */
361 bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
362 {
363         struct list_head *pos;
364         bool done = true;
365
366         down_read(&tomoyo_pattern_list_lock);
367         list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) {
368                 struct tomoyo_pattern_entry *ptr;
369                 ptr = list_entry(pos, struct tomoyo_pattern_entry, list);
370                 if (ptr->is_deleted)
371                         continue;
372                 if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_FILE_PATTERN "%s\n",
373                                       ptr->pattern->name)) {
374                         done = false;
375                         break;
376                 }
377         }
378         up_read(&tomoyo_pattern_list_lock);
379         return done;
380 }
381
382 /* The list for "struct tomoyo_no_rewrite_entry". */
383 static LIST_HEAD(tomoyo_no_rewrite_list);
384 static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock);
385
386 /**
387  * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list.
388  *
389  * @pattern:   Pathname pattern that are not rewritable by default.
390  * @is_delete: True if it is a delete request.
391  *
392  * Returns 0 on success, negative value otherwise.
393  */
394 static int tomoyo_update_no_rewrite_entry(const char *pattern,
395                                           const bool is_delete)
396 {
397         struct tomoyo_no_rewrite_entry *new_entry, *ptr;
398         const struct tomoyo_path_info *saved_pattern;
399         int error = -ENOMEM;
400
401         if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__))
402                 return -EINVAL;
403         saved_pattern = tomoyo_save_name(pattern);
404         if (!saved_pattern)
405                 return -ENOMEM;
406         down_write(&tomoyo_no_rewrite_list_lock);
407         list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
408                 if (ptr->pattern != saved_pattern)
409                         continue;
410                 ptr->is_deleted = is_delete;
411                 error = 0;
412                 goto out;
413         }
414         if (is_delete) {
415                 error = -ENOENT;
416                 goto out;
417         }
418         new_entry = tomoyo_alloc_element(sizeof(*new_entry));
419         if (!new_entry)
420                 goto out;
421         new_entry->pattern = saved_pattern;
422         list_add_tail(&new_entry->list, &tomoyo_no_rewrite_list);
423         error = 0;
424  out:
425         up_write(&tomoyo_no_rewrite_list_lock);
426         return error;
427 }
428
429 /**
430  * tomoyo_is_no_rewrite_file - Check if the given pathname is not permitted to be rewrited.
431  *
432  * @filename: Filename to check.
433  *
434  * Returns true if @filename is specified by "deny_rewrite" directive,
435  * false otherwise.
436  */
437 static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
438 {
439         struct tomoyo_no_rewrite_entry *ptr;
440         bool found = false;
441
442         down_read(&tomoyo_no_rewrite_list_lock);
443         list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
444                 if (ptr->is_deleted)
445                         continue;
446                 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
447                         continue;
448                 found = true;
449                 break;
450         }
451         up_read(&tomoyo_no_rewrite_list_lock);
452         return found;
453 }
454
455 /**
456  * tomoyo_write_no_rewrite_policy - Write "struct tomoyo_no_rewrite_entry" list.
457  *
458  * @data:      String to parse.
459  * @is_delete: True if it is a delete request.
460  *
461  * Returns 0 on success, negative value otherwise.
462  */
463 int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete)
464 {
465         return tomoyo_update_no_rewrite_entry(data, is_delete);
466 }
467
468 /**
469  * tomoyo_read_no_rewrite_policy - Read "struct tomoyo_no_rewrite_entry" list.
470  *
471  * @head: Pointer to "struct tomoyo_io_buffer".
472  *
473  * Returns true on success, false otherwise.
474  */
475 bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
476 {
477         struct list_head *pos;
478         bool done = true;
479
480         down_read(&tomoyo_no_rewrite_list_lock);
481         list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) {
482                 struct tomoyo_no_rewrite_entry *ptr;
483                 ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list);
484                 if (ptr->is_deleted)
485                         continue;
486                 if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_DENY_REWRITE "%s\n",
487                                       ptr->pattern->name)) {
488                         done = false;
489                         break;
490                 }
491         }
492         up_read(&tomoyo_no_rewrite_list_lock);
493         return done;
494 }
495
496 /**
497  * tomoyo_update_file_acl - Update file's read/write/execute ACL.
498  *
499  * @filename:  Filename.
500  * @perm:      Permission (between 1 to 7).
501  * @domain:    Pointer to "struct tomoyo_domain_info".
502  * @is_delete: True if it is a delete request.
503  *
504  * Returns 0 on success, negative value otherwise.
505  *
506  * This is legacy support interface for older policy syntax.
507  * Current policy syntax uses "allow_read/write" instead of "6",
508  * "allow_read" instead of "4", "allow_write" instead of "2",
509  * "allow_execute" instead of "1".
510  */
511 static int tomoyo_update_file_acl(const char *filename, u8 perm,
512                                   struct tomoyo_domain_info * const domain,
513                                   const bool is_delete)
514 {
515         if (perm > 7 || !perm) {
516                 printk(KERN_DEBUG "%s: Invalid permission '%d %s'\n",
517                        __func__, perm, filename);
518                 return -EINVAL;
519         }
520         if (filename[0] != '@' && tomoyo_strendswith(filename, "/"))
521                 /*
522                  * Only 'allow_mkdir' and 'allow_rmdir' are valid for
523                  * directory permissions.
524                  */
525                 return 0;
526         if (perm & 4)
527                 tomoyo_update_single_path_acl(TOMOYO_TYPE_READ_ACL, filename,
528                                               domain, is_delete);
529         if (perm & 2)
530                 tomoyo_update_single_path_acl(TOMOYO_TYPE_WRITE_ACL, filename,
531                                               domain, is_delete);
532         if (perm & 1)
533                 tomoyo_update_single_path_acl(TOMOYO_TYPE_EXECUTE_ACL,
534                                               filename, domain, is_delete);
535         return 0;
536 }
537
538 /**
539  * tomoyo_check_single_path_acl2 - Check permission for single path operation.
540  *
541  * @domain:          Pointer to "struct tomoyo_domain_info".
542  * @filename:        Filename to check.
543  * @perm:            Permission.
544  * @may_use_pattern: True if patterned ACL is permitted.
545  *
546  * Returns 0 on success, -EPERM otherwise.
547  */
548 static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info *
549                                          domain,
550                                          const struct tomoyo_path_info *
551                                          filename,
552                                          const u16 perm,
553                                          const bool may_use_pattern)
554 {
555         struct tomoyo_acl_info *ptr;
556         int error = -EPERM;
557
558         down_read(&tomoyo_domain_acl_info_list_lock);
559         list_for_each_entry(ptr, &domain->acl_info_list, list) {
560                 struct tomoyo_single_path_acl_record *acl;
561                 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
562                         continue;
563                 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
564                                    head);
565                 if (!(acl->perm & perm))
566                         continue;
567                 if (may_use_pattern || !acl->filename->is_patterned) {
568                         if (!tomoyo_path_matches_pattern(filename,
569                                                          acl->filename))
570                                 continue;
571                 } else {
572                         continue;
573                 }
574                 error = 0;
575                 break;
576         }
577         up_read(&tomoyo_domain_acl_info_list_lock);
578         return error;
579 }
580
581 /**
582  * tomoyo_check_file_acl - Check permission for opening files.
583  *
584  * @domain:    Pointer to "struct tomoyo_domain_info".
585  * @filename:  Filename to check.
586  * @operation: Mode ("read" or "write" or "read/write" or "execute").
587  *
588  * Returns 0 on success, -EPERM otherwise.
589  */
590 static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain,
591                                  const struct tomoyo_path_info *filename,
592                                  const u8 operation)
593 {
594         u16 perm = 0;
595
596         if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
597                 return 0;
598         if (operation == 6)
599                 perm = 1 << TOMOYO_TYPE_READ_WRITE_ACL;
600         else if (operation == 4)
601                 perm = 1 << TOMOYO_TYPE_READ_ACL;
602         else if (operation == 2)
603                 perm = 1 << TOMOYO_TYPE_WRITE_ACL;
604         else if (operation == 1)
605                 perm = 1 << TOMOYO_TYPE_EXECUTE_ACL;
606         else
607                 BUG();
608         return tomoyo_check_single_path_acl2(domain, filename, perm,
609                                              operation != 1);
610 }
611
612 /**
613  * tomoyo_check_file_perm2 - Check permission for opening files.
614  *
615  * @domain:    Pointer to "struct tomoyo_domain_info".
616  * @filename:  Filename to check.
617  * @perm:      Mode ("read" or "write" or "read/write" or "execute").
618  * @operation: Operation name passed used for verbose mode.
619  * @mode:      Access control mode.
620  *
621  * Returns 0 on success, negative value otherwise.
622  */
623 static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
624                                    const struct tomoyo_path_info *filename,
625                                    const u8 perm, const char *operation,
626                                    const u8 mode)
627 {
628         const bool is_enforce = (mode == 3);
629         const char *msg = "<unknown>";
630         int error = 0;
631
632         if (!filename)
633                 return 0;
634         error = tomoyo_check_file_acl(domain, filename, perm);
635         if (error && perm == 4 &&
636             (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0
637             && tomoyo_is_globally_readable_file(filename))
638                 error = 0;
639         if (perm == 6)
640                 msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_WRITE_ACL);
641         else if (perm == 4)
642                 msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_ACL);
643         else if (perm == 2)
644                 msg = tomoyo_sp2keyword(TOMOYO_TYPE_WRITE_ACL);
645         else if (perm == 1)
646                 msg = tomoyo_sp2keyword(TOMOYO_TYPE_EXECUTE_ACL);
647         else
648                 BUG();
649         if (!error)
650                 return 0;
651         if (tomoyo_verbose_mode(domain))
652                 printk(KERN_WARNING "TOMOYO-%s: Access '%s(%s) %s' denied "
653                        "for %s\n", tomoyo_get_msg(is_enforce), msg, operation,
654                        filename->name, tomoyo_get_last_name(domain));
655         if (is_enforce)
656                 return error;
657         if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
658                 /* Don't use patterns for execute permission. */
659                 const struct tomoyo_path_info *patterned_file = (perm != 1) ?
660                         tomoyo_get_file_pattern(filename) : filename;
661                 tomoyo_update_file_acl(patterned_file->name, perm,
662                                        domain, false);
663         }
664         return 0;
665 }
666
667 /**
668  * tomoyo_write_file_policy - Update file related list.
669  *
670  * @data:      String to parse.
671  * @domain:    Pointer to "struct tomoyo_domain_info".
672  * @is_delete: True if it is a delete request.
673  *
674  * Returns 0 on success, negative value otherwise.
675  */
676 int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
677                              const bool is_delete)
678 {
679         char *filename = strchr(data, ' ');
680         char *filename2;
681         unsigned int perm;
682         u8 type;
683
684         if (!filename)
685                 return -EINVAL;
686         *filename++ = '\0';
687         if (sscanf(data, "%u", &perm) == 1)
688                 return tomoyo_update_file_acl(filename, (u8) perm, domain,
689                                               is_delete);
690         if (strncmp(data, "allow_", 6))
691                 goto out;
692         data += 6;
693         for (type = 0; type < TOMOYO_MAX_SINGLE_PATH_OPERATION; type++) {
694                 if (strcmp(data, tomoyo_sp_keyword[type]))
695                         continue;
696                 return tomoyo_update_single_path_acl(type, filename,
697                                                      domain, is_delete);
698         }
699         filename2 = strchr(filename, ' ');
700         if (!filename2)
701                 goto out;
702         *filename2++ = '\0';
703         for (type = 0; type < TOMOYO_MAX_DOUBLE_PATH_OPERATION; type++) {
704                 if (strcmp(data, tomoyo_dp_keyword[type]))
705                         continue;
706                 return tomoyo_update_double_path_acl(type, filename, filename2,
707                                                      domain, is_delete);
708         }
709  out:
710         return -EINVAL;
711 }
712
713 /**
714  * tomoyo_update_single_path_acl - Update "struct tomoyo_single_path_acl_record" list.
715  *
716  * @type:      Type of operation.
717  * @filename:  Filename.
718  * @domain:    Pointer to "struct tomoyo_domain_info".
719  * @is_delete: True if it is a delete request.
720  *
721  * Returns 0 on success, negative value otherwise.
722  */
723 static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
724                                          struct tomoyo_domain_info *
725                                          const domain, const bool is_delete)
726 {
727         static const u16 rw_mask =
728                 (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL);
729         const struct tomoyo_path_info *saved_filename;
730         struct tomoyo_acl_info *ptr;
731         struct tomoyo_single_path_acl_record *acl;
732         int error = -ENOMEM;
733         const u16 perm = 1 << type;
734
735         if (!domain)
736                 return -EINVAL;
737         if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__))
738                 return -EINVAL;
739         saved_filename = tomoyo_save_name(filename);
740         if (!saved_filename)
741                 return -ENOMEM;
742         down_write(&tomoyo_domain_acl_info_list_lock);
743         if (is_delete)
744                 goto delete;
745         list_for_each_entry(ptr, &domain->acl_info_list, list) {
746                 if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
747                         continue;
748                 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
749                                    head);
750                 if (acl->filename != saved_filename)
751                         continue;
752                 /* Special case. Clear all bits if marked as deleted. */
753                 if (ptr->type & TOMOYO_ACL_DELETED)
754                         acl->perm = 0;
755                 acl->perm |= perm;
756                 if ((acl->perm & rw_mask) == rw_mask)
757                         acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL;
758                 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))
759                         acl->perm |= rw_mask;
760                 ptr->type &= ~TOMOYO_ACL_DELETED;
761                 error = 0;
762                 goto out;
763         }
764         /* Not found. Append it to the tail. */
765         acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL);
766         if (!acl)
767                 goto out;
768         acl->perm = perm;
769         if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL))
770                 acl->perm |= rw_mask;
771         acl->filename = saved_filename;
772         list_add_tail(&acl->head.list, &domain->acl_info_list);
773         error = 0;
774         goto out;
775  delete:
776         error = -ENOENT;
777         list_for_each_entry(ptr, &domain->acl_info_list, list) {
778                 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
779                         continue;
780                 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
781                                    head);
782                 if (acl->filename != saved_filename)
783                         continue;
784                 acl->perm &= ~perm;
785                 if ((acl->perm & rw_mask) != rw_mask)
786                         acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL);
787                 else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
788                         acl->perm &= ~rw_mask;
789                 if (!acl->perm)
790                         ptr->type |= TOMOYO_ACL_DELETED;
791                 error = 0;
792                 break;
793         }
794  out:
795         up_write(&tomoyo_domain_acl_info_list_lock);
796         return error;
797 }
798
799 /**
800  * tomoyo_update_double_path_acl - Update "struct tomoyo_double_path_acl_record" list.
801  *
802  * @type:      Type of operation.
803  * @filename1: First filename.
804  * @filename2: Second filename.
805  * @domain:    Pointer to "struct tomoyo_domain_info".
806  * @is_delete: True if it is a delete request.
807  *
808  * Returns 0 on success, negative value otherwise.
809  */
810 static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
811                                          const char *filename2,
812                                          struct tomoyo_domain_info *
813                                          const domain, const bool is_delete)
814 {
815         const struct tomoyo_path_info *saved_filename1;
816         const struct tomoyo_path_info *saved_filename2;
817         struct tomoyo_acl_info *ptr;
818         struct tomoyo_double_path_acl_record *acl;
819         int error = -ENOMEM;
820         const u8 perm = 1 << type;
821
822         if (!domain)
823                 return -EINVAL;
824         if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) ||
825             !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__))
826                 return -EINVAL;
827         saved_filename1 = tomoyo_save_name(filename1);
828         saved_filename2 = tomoyo_save_name(filename2);
829         if (!saved_filename1 || !saved_filename2)
830                 return -ENOMEM;
831         down_write(&tomoyo_domain_acl_info_list_lock);
832         if (is_delete)
833                 goto delete;
834         list_for_each_entry(ptr, &domain->acl_info_list, list) {
835                 if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
836                         continue;
837                 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
838                                    head);
839                 if (acl->filename1 != saved_filename1 ||
840                     acl->filename2 != saved_filename2)
841                         continue;
842                 /* Special case. Clear all bits if marked as deleted. */
843                 if (ptr->type & TOMOYO_ACL_DELETED)
844                         acl->perm = 0;
845                 acl->perm |= perm;
846                 ptr->type &= ~TOMOYO_ACL_DELETED;
847                 error = 0;
848                 goto out;
849         }
850         /* Not found. Append it to the tail. */
851         acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL);
852         if (!acl)
853                 goto out;
854         acl->perm = perm;
855         acl->filename1 = saved_filename1;
856         acl->filename2 = saved_filename2;
857         list_add_tail(&acl->head.list, &domain->acl_info_list);
858         error = 0;
859         goto out;
860  delete:
861         error = -ENOENT;
862         list_for_each_entry(ptr, &domain->acl_info_list, list) {
863                 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
864                         continue;
865                 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
866                                    head);
867                 if (acl->filename1 != saved_filename1 ||
868                     acl->filename2 != saved_filename2)
869                         continue;
870                 acl->perm &= ~perm;
871                 if (!acl->perm)
872                         ptr->type |= TOMOYO_ACL_DELETED;
873                 error = 0;
874                 break;
875         }
876  out:
877         up_write(&tomoyo_domain_acl_info_list_lock);
878         return error;
879 }
880
881 /**
882  * tomoyo_check_single_path_acl - Check permission for single path operation.
883  *
884  * @domain:   Pointer to "struct tomoyo_domain_info".
885  * @type:     Type of operation.
886  * @filename: Filename to check.
887  *
888  * Returns 0 on success, negative value otherwise.
889  */
890 static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain,
891                                         const u8 type,
892                                         const struct tomoyo_path_info *filename)
893 {
894         if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
895                 return 0;
896         return tomoyo_check_single_path_acl2(domain, filename, 1 << type, 1);
897 }
898
899 /**
900  * tomoyo_check_double_path_acl - Check permission for double path operation.
901  *
902  * @domain:    Pointer to "struct tomoyo_domain_info".
903  * @type:      Type of operation.
904  * @filename1: First filename to check.
905  * @filename2: Second filename to check.
906  *
907  * Returns 0 on success, -EPERM otherwise.
908  */
909 static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain,
910                                         const u8 type,
911                                         const struct tomoyo_path_info *
912                                         filename1,
913                                         const struct tomoyo_path_info *
914                                         filename2)
915 {
916         struct tomoyo_acl_info *ptr;
917         const u8 perm = 1 << type;
918         int error = -EPERM;
919
920         if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
921                 return 0;
922         down_read(&tomoyo_domain_acl_info_list_lock);
923         list_for_each_entry(ptr, &domain->acl_info_list, list) {
924                 struct tomoyo_double_path_acl_record *acl;
925                 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
926                         continue;
927                 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
928                                    head);
929                 if (!(acl->perm & perm))
930                         continue;
931                 if (!tomoyo_path_matches_pattern(filename1, acl->filename1))
932                         continue;
933                 if (!tomoyo_path_matches_pattern(filename2, acl->filename2))
934                         continue;
935                 error = 0;
936                 break;
937         }
938         up_read(&tomoyo_domain_acl_info_list_lock);
939         return error;
940 }
941
942 /**
943  * tomoyo_check_single_path_permission2 - Check permission for single path operation.
944  *
945  * @domain:    Pointer to "struct tomoyo_domain_info".
946  * @operation: Type of operation.
947  * @filename:  Filename to check.
948  * @mode:      Access control mode.
949  *
950  * Returns 0 on success, negative value otherwise.
951  */
952 static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info *
953                                                 const domain, u8 operation,
954                                                 const struct tomoyo_path_info *
955                                                 filename, const u8 mode)
956 {
957         const char *msg;
958         int error;
959         const bool is_enforce = (mode == 3);
960
961         if (!mode)
962                 return 0;
963  next:
964         error = tomoyo_check_single_path_acl(domain, operation, filename);
965         msg = tomoyo_sp2keyword(operation);
966         if (!error)
967                 goto ok;
968         if (tomoyo_verbose_mode(domain))
969                 printk(KERN_WARNING "TOMOYO-%s: Access '%s %s' denied for %s\n",
970                        tomoyo_get_msg(is_enforce), msg, filename->name,
971                        tomoyo_get_last_name(domain));
972         if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
973                 const char *name = tomoyo_get_file_pattern(filename)->name;
974                 tomoyo_update_single_path_acl(operation, name, domain, false);
975         }
976         if (!is_enforce)
977                 error = 0;
978  ok:
979         /*
980          * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
981          * we need to check "allow_rewrite" permission if the filename is
982          * specified by "deny_rewrite" keyword.
983          */
984         if (!error && operation == TOMOYO_TYPE_TRUNCATE_ACL &&
985             tomoyo_is_no_rewrite_file(filename)) {
986                 operation = TOMOYO_TYPE_REWRITE_ACL;
987                 goto next;
988         }
989         return error;
990 }
991
992 /**
993  * tomoyo_check_file_perm - Check permission for sysctl()'s "read" and "write".
994  *
995  * @domain:    Pointer to "struct tomoyo_domain_info".
996  * @filename:  Filename to check.
997  * @perm:      Mode ("read" or "write" or "read/write").
998  * Returns 0 on success, negative value otherwise.
999  */
1000 int tomoyo_check_file_perm(struct tomoyo_domain_info *domain,
1001                            const char *filename, const u8 perm)
1002 {
1003         struct tomoyo_path_info name;
1004         const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1005
1006         if (!mode)
1007                 return 0;
1008         name.name = filename;
1009         tomoyo_fill_path_info(&name);
1010         return tomoyo_check_file_perm2(domain, &name, perm, "sysctl", mode);
1011 }
1012
1013 /**
1014  * tomoyo_check_exec_perm - Check permission for "execute".
1015  *
1016  * @domain:   Pointer to "struct tomoyo_domain_info".
1017  * @filename: Check permission for "execute".
1018  * @tmp:      Buffer for temporary use.
1019  *
1020  * Returns 0 on success, negativevalue otherwise.
1021  */
1022 int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
1023                            const struct tomoyo_path_info *filename,
1024                            struct tomoyo_page_buffer *tmp)
1025 {
1026         const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1027
1028         if (!mode)
1029                 return 0;
1030         return tomoyo_check_file_perm2(domain, filename, 1, "do_execve", mode);
1031 }
1032
1033 /**
1034  * tomoyo_check_open_permission - Check permission for "read" and "write".
1035  *
1036  * @domain: Pointer to "struct tomoyo_domain_info".
1037  * @path:   Pointer to "struct path".
1038  * @flag:   Flags for open().
1039  *
1040  * Returns 0 on success, negative value otherwise.
1041  */
1042 int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1043                                  struct path *path, const int flag)
1044 {
1045         const u8 acc_mode = ACC_MODE(flag);
1046         int error = -ENOMEM;
1047         struct tomoyo_path_info *buf;
1048         const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1049         const bool is_enforce = (mode == 3);
1050
1051         if (!mode || !path->mnt)
1052                 return 0;
1053         if (acc_mode == 0)
1054                 return 0;
1055         if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))
1056                 /*
1057                  * I don't check directories here because mkdir() and rmdir()
1058                  * don't call me.
1059                  */
1060                 return 0;
1061         buf = tomoyo_get_path(path);
1062         if (!buf)
1063                 goto out;
1064         error = 0;
1065         /*
1066          * If the filename is specified by "deny_rewrite" keyword,
1067          * we need to check "allow_rewrite" permission when the filename is not
1068          * opened for append mode or the filename is truncated at open time.
1069          */
1070         if ((acc_mode & MAY_WRITE) &&
1071             ((flag & O_TRUNC) || !(flag & O_APPEND)) &&
1072             (tomoyo_is_no_rewrite_file(buf))) {
1073                 error = tomoyo_check_single_path_permission2(domain,
1074                                                      TOMOYO_TYPE_REWRITE_ACL,
1075                                                              buf, mode);
1076         }
1077         if (!error)
1078                 error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open",
1079                                                 mode);
1080         if (!error && (flag & O_TRUNC))
1081                 error = tomoyo_check_single_path_permission2(domain,
1082                                                      TOMOYO_TYPE_TRUNCATE_ACL,
1083                                                              buf, mode);
1084  out:
1085         tomoyo_free(buf);
1086         if (!is_enforce)
1087                 error = 0;
1088         return error;
1089 }
1090
1091 /**
1092  * tomoyo_check_1path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate" and "symlink".
1093  *
1094  * @domain:    Pointer to "struct tomoyo_domain_info".
1095  * @operation: Type of operation.
1096  * @path:      Pointer to "struct path".
1097  *
1098  * Returns 0 on success, negative value otherwise.
1099  */
1100 int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
1101                             const u8 operation, struct path *path)
1102 {
1103         int error = -ENOMEM;
1104         struct tomoyo_path_info *buf;
1105         const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1106         const bool is_enforce = (mode == 3);
1107
1108         if (!mode || !path->mnt)
1109                 return 0;
1110         buf = tomoyo_get_path(path);
1111         if (!buf)
1112                 goto out;
1113         switch (operation) {
1114         case TOMOYO_TYPE_MKDIR_ACL:
1115         case TOMOYO_TYPE_RMDIR_ACL:
1116                 if (!buf->is_dir) {
1117                         /*
1118                          * tomoyo_get_path() reserves space for appending "/."
1119                          */
1120                         strcat((char *) buf->name, "/");
1121                         tomoyo_fill_path_info(buf);
1122                 }
1123         }
1124         error = tomoyo_check_single_path_permission2(domain, operation, buf,
1125                                                      mode);
1126  out:
1127         tomoyo_free(buf);
1128         if (!is_enforce)
1129                 error = 0;
1130         return error;
1131 }
1132
1133 /**
1134  * tomoyo_check_rewrite_permission - Check permission for "rewrite".
1135  *
1136  * @domain: Pointer to "struct tomoyo_domain_info".
1137  * @filp: Pointer to "struct file".
1138  *
1139  * Returns 0 on success, negative value otherwise.
1140  */
1141 int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
1142                                     struct file *filp)
1143 {
1144         int error = -ENOMEM;
1145         const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1146         const bool is_enforce = (mode == 3);
1147         struct tomoyo_path_info *buf;
1148
1149         if (!mode || !filp->f_path.mnt)
1150                 return 0;
1151         buf = tomoyo_get_path(&filp->f_path);
1152         if (!buf)
1153                 goto out;
1154         if (!tomoyo_is_no_rewrite_file(buf)) {
1155                 error = 0;
1156                 goto out;
1157         }
1158         error = tomoyo_check_single_path_permission2(domain,
1159                                                      TOMOYO_TYPE_REWRITE_ACL,
1160                                                      buf, mode);
1161  out:
1162         tomoyo_free(buf);
1163         if (!is_enforce)
1164                 error = 0;
1165         return error;
1166 }
1167
1168 /**
1169  * tomoyo_check_2path_perm - Check permission for "rename" and "link".
1170  *
1171  * @domain:    Pointer to "struct tomoyo_domain_info".
1172  * @operation: Type of operation.
1173  * @path1:      Pointer to "struct path".
1174  * @path2:      Pointer to "struct path".
1175  *
1176  * Returns 0 on success, negative value otherwise.
1177  */
1178 int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain,
1179                             const u8 operation, struct path *path1,
1180                             struct path *path2)
1181 {
1182         int error = -ENOMEM;
1183         struct tomoyo_path_info *buf1, *buf2;
1184         const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1185         const bool is_enforce = (mode == 3);
1186         const char *msg;
1187
1188         if (!mode || !path1->mnt || !path2->mnt)
1189                 return 0;
1190         buf1 = tomoyo_get_path(path1);
1191         buf2 = tomoyo_get_path(path2);
1192         if (!buf1 || !buf2)
1193                 goto out;
1194         {
1195                 struct dentry *dentry = path1->dentry;
1196                 if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
1197                         /*
1198                          * tomoyo_get_path() reserves space for appending "/."
1199                          */
1200                         if (!buf1->is_dir) {
1201                                 strcat((char *) buf1->name, "/");
1202                                 tomoyo_fill_path_info(buf1);
1203                         }
1204                         if (!buf2->is_dir) {
1205                                 strcat((char *) buf2->name, "/");
1206                                 tomoyo_fill_path_info(buf2);
1207                         }
1208                 }
1209         }
1210         error = tomoyo_check_double_path_acl(domain, operation, buf1, buf2);
1211         msg = tomoyo_dp2keyword(operation);
1212         if (!error)
1213                 goto out;
1214         if (tomoyo_verbose_mode(domain))
1215                 printk(KERN_WARNING "TOMOYO-%s: Access '%s %s %s' "
1216                        "denied for %s\n", tomoyo_get_msg(is_enforce),
1217                        msg, buf1->name, buf2->name,
1218                        tomoyo_get_last_name(domain));
1219         if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
1220                 const char *name1 = tomoyo_get_file_pattern(buf1)->name;
1221                 const char *name2 = tomoyo_get_file_pattern(buf2)->name;
1222                 tomoyo_update_double_path_acl(operation, name1, name2, domain,
1223                                               false);
1224         }
1225  out:
1226         tomoyo_free(buf1);
1227         tomoyo_free(buf2);
1228         if (!is_enforce)
1229                 error = 0;
1230         return error;
1231 }