]> bbs.cooldavid.org Git - net-next-2.6.git/blob - security/tomoyo/domain.c
7d0b0bc48201d022981ce5ac05422c38c5e5aab7
[net-next-2.6.git] / security / tomoyo / domain.c
1 /*
2  * security/tomoyo/domain.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 #include <linux/binfmts.h>
16
17 /* Variables definitions.*/
18
19 /* The initial domain. */
20 struct tomoyo_domain_info tomoyo_kernel_domain;
21
22 /*
23  * tomoyo_domain_list is used for holding list of domains.
24  * The ->acl_info_list of "struct tomoyo_domain_info" is used for holding
25  * permissions (e.g. "allow_read /lib/libc-2.5.so") given to each domain.
26  *
27  * An entry is added by
28  *
29  * # ( echo "<kernel>"; echo "allow_execute /sbin/init" ) > \
30  *                                  /sys/kernel/security/tomoyo/domain_policy
31  *
32  * and is deleted by
33  *
34  * # ( echo "<kernel>"; echo "delete allow_execute /sbin/init" ) > \
35  *                                  /sys/kernel/security/tomoyo/domain_policy
36  *
37  * and all entries are retrieved by
38  *
39  * # cat /sys/kernel/security/tomoyo/domain_policy
40  *
41  * A domain is added by
42  *
43  * # echo "<kernel>" > /sys/kernel/security/tomoyo/domain_policy
44  *
45  * and is deleted by
46  *
47  * # echo "delete <kernel>" > /sys/kernel/security/tomoyo/domain_policy
48  *
49  * and all domains are retrieved by
50  *
51  * # grep '^<kernel>' /sys/kernel/security/tomoyo/domain_policy
52  *
53  * Normally, a domainname is monotonically getting longer because a domainname
54  * which the process will belong to if an execve() operation succeeds is
55  * defined as a concatenation of "current domainname" + "pathname passed to
56  * execve()".
57  * See tomoyo_domain_initializer_list and tomoyo_domain_keeper_list for
58  * exceptions.
59  */
60 LIST_HEAD(tomoyo_domain_list);
61
62 /*
63  * tomoyo_domain_initializer_entry is a structure which is used for holding
64  * "initialize_domain" and "no_initialize_domain" entries.
65  * It has following fields.
66  *
67  *  (1) "list" which is linked to tomoyo_domain_initializer_list .
68  *  (2) "domainname" which is "a domainname" or "the last component of a
69  *      domainname". This field is NULL if "from" clause is not specified.
70  *  (3) "program" which is a program's pathname.
71  *  (4) "is_deleted" is a bool which is true if marked as deleted, false
72  *      otherwise.
73  *  (5) "is_not" is a bool which is true if "no_initialize_domain", false
74  *      otherwise.
75  *  (6) "is_last_name" is a bool which is true if "domainname" is "the last
76  *      component of a domainname", false otherwise.
77  */
78 struct tomoyo_domain_initializer_entry {
79         struct list_head list;
80         const struct tomoyo_path_info *domainname;    /* This may be NULL */
81         const struct tomoyo_path_info *program;
82         bool is_deleted;
83         bool is_not;       /* True if this entry is "no_initialize_domain".  */
84         /* True if the domainname is tomoyo_get_last_name(). */
85         bool is_last_name;
86 };
87
88 /*
89  * tomoyo_domain_keeper_entry is a structure which is used for holding
90  * "keep_domain" and "no_keep_domain" entries.
91  * It has following fields.
92  *
93  *  (1) "list" which is linked to tomoyo_domain_keeper_list .
94  *  (2) "domainname" which is "a domainname" or "the last component of a
95  *      domainname".
96  *  (3) "program" which is a program's pathname.
97  *      This field is NULL if "from" clause is not specified.
98  *  (4) "is_deleted" is a bool which is true if marked as deleted, false
99  *      otherwise.
100  *  (5) "is_not" is a bool which is true if "no_initialize_domain", false
101  *      otherwise.
102  *  (6) "is_last_name" is a bool which is true if "domainname" is "the last
103  *      component of a domainname", false otherwise.
104  */
105 struct tomoyo_domain_keeper_entry {
106         struct list_head list;
107         const struct tomoyo_path_info *domainname;
108         const struct tomoyo_path_info *program;       /* This may be NULL */
109         bool is_deleted;
110         bool is_not;       /* True if this entry is "no_keep_domain".        */
111         /* True if the domainname is tomoyo_get_last_name(). */
112         bool is_last_name;
113 };
114
115 /*
116  * tomoyo_alias_entry is a structure which is used for holding "alias" entries.
117  * It has following fields.
118  *
119  *  (1) "list" which is linked to tomoyo_alias_list .
120  *  (2) "original_name" which is a dereferenced pathname.
121  *  (3) "aliased_name" which is a symlink's pathname.
122  *  (4) "is_deleted" is a bool which is true if marked as deleted, false
123  *      otherwise.
124  */
125 struct tomoyo_alias_entry {
126         struct list_head list;
127         const struct tomoyo_path_info *original_name;
128         const struct tomoyo_path_info *aliased_name;
129         bool is_deleted;
130 };
131
132 /**
133  * tomoyo_set_domain_flag - Set or clear domain's attribute flags.
134  *
135  * @domain:    Pointer to "struct tomoyo_domain_info".
136  * @is_delete: True if it is a delete request.
137  * @flags:     Flags to set or clear.
138  *
139  * Returns nothing.
140  */
141 void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
142                             const bool is_delete, const u8 flags)
143 {
144         /* We need to serialize because this is bitfield operation. */
145         static DEFINE_SPINLOCK(lock);
146         spin_lock(&lock);
147         if (!is_delete)
148                 domain->flags |= flags;
149         else
150                 domain->flags &= ~flags;
151         spin_unlock(&lock);
152 }
153
154 /**
155  * tomoyo_get_last_name - Get last component of a domainname.
156  *
157  * @domain: Pointer to "struct tomoyo_domain_info".
158  *
159  * Returns the last component of the domainname.
160  */
161 const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
162 {
163         const char *cp0 = domain->domainname->name;
164         const char *cp1 = strrchr(cp0, ' ');
165
166         if (cp1)
167                 return cp1 + 1;
168         return cp0;
169 }
170
171 /*
172  * tomoyo_domain_initializer_list is used for holding list of programs which
173  * triggers reinitialization of domainname. Normally, a domainname is
174  * monotonically getting longer. But sometimes, we restart daemon programs.
175  * It would be convenient for us that "a daemon started upon system boot" and
176  * "the daemon restarted from console" belong to the same domain. Thus, TOMOYO
177  * provides a way to shorten domainnames.
178  *
179  * An entry is added by
180  *
181  * # echo 'initialize_domain /usr/sbin/httpd' > \
182  *                               /sys/kernel/security/tomoyo/exception_policy
183  *
184  * and is deleted by
185  *
186  * # echo 'delete initialize_domain /usr/sbin/httpd' > \
187  *                               /sys/kernel/security/tomoyo/exception_policy
188  *
189  * and all entries are retrieved by
190  *
191  * # grep ^initialize_domain /sys/kernel/security/tomoyo/exception_policy
192  *
193  * In the example above, /usr/sbin/httpd will belong to
194  * "<kernel> /usr/sbin/httpd" domain.
195  *
196  * You may specify a domainname using "from" keyword.
197  * "initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
198  * will cause "/usr/sbin/httpd" executed from "<kernel> /etc/rc.d/init.d/httpd"
199  * domain to belong to "<kernel> /usr/sbin/httpd" domain.
200  *
201  * You may add "no_" prefix to "initialize_domain".
202  * "initialize_domain /usr/sbin/httpd" and
203  * "no_initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
204  * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain
205  * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain.
206  */
207 static LIST_HEAD(tomoyo_domain_initializer_list);
208
209 /**
210  * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
211  *
212  * @domainname: The name of domain. May be NULL.
213  * @program:    The name of program.
214  * @is_not:     True if it is "no_initialize_domain" entry.
215  * @is_delete:  True if it is a delete request.
216  *
217  * Returns 0 on success, negative value otherwise.
218  *
219  * Caller holds tomoyo_read_lock().
220  */
221 static int tomoyo_update_domain_initializer_entry(const char *domainname,
222                                                   const char *program,
223                                                   const bool is_not,
224                                                   const bool is_delete)
225 {
226         struct tomoyo_domain_initializer_entry *new_entry;
227         struct tomoyo_domain_initializer_entry *ptr;
228         const struct tomoyo_path_info *saved_program;
229         const struct tomoyo_path_info *saved_domainname = NULL;
230         int error = -ENOMEM;
231         bool is_last_name = false;
232
233         if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
234                 return -EINVAL; /* No patterns allowed. */
235         if (domainname) {
236                 if (!tomoyo_is_domain_def(domainname) &&
237                     tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
238                         is_last_name = true;
239                 else if (!tomoyo_is_correct_domain(domainname, __func__))
240                         return -EINVAL;
241                 saved_domainname = tomoyo_save_name(domainname);
242                 if (!saved_domainname)
243                         return -ENOMEM;
244         }
245         saved_program = tomoyo_save_name(program);
246         if (!saved_program)
247                 return -ENOMEM;
248         mutex_lock(&tomoyo_policy_lock);
249         list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
250                 if (ptr->is_not != is_not ||
251                     ptr->domainname != saved_domainname ||
252                     ptr->program != saved_program)
253                         continue;
254                 ptr->is_deleted = is_delete;
255                 error = 0;
256                 goto out;
257         }
258         if (is_delete) {
259                 error = -ENOENT;
260                 goto out;
261         }
262         new_entry = tomoyo_alloc_element(sizeof(*new_entry));
263         if (!new_entry)
264                 goto out;
265         new_entry->domainname = saved_domainname;
266         new_entry->program = saved_program;
267         new_entry->is_not = is_not;
268         new_entry->is_last_name = is_last_name;
269         list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list);
270         error = 0;
271  out:
272         mutex_unlock(&tomoyo_policy_lock);
273         return error;
274 }
275
276 /**
277  * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list.
278  *
279  * @head: Pointer to "struct tomoyo_io_buffer".
280  *
281  * Returns true on success, false otherwise.
282  *
283  * Caller holds tomoyo_read_lock().
284  */
285 bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
286 {
287         struct list_head *pos;
288         bool done = true;
289
290         list_for_each_cookie(pos, head->read_var2,
291                              &tomoyo_domain_initializer_list) {
292                 const char *no;
293                 const char *from = "";
294                 const char *domain = "";
295                 struct tomoyo_domain_initializer_entry *ptr;
296                 ptr = list_entry(pos, struct tomoyo_domain_initializer_entry,
297                                   list);
298                 if (ptr->is_deleted)
299                         continue;
300                 no = ptr->is_not ? "no_" : "";
301                 if (ptr->domainname) {
302                         from = " from ";
303                         domain = ptr->domainname->name;
304                 }
305                 done = tomoyo_io_printf(head,
306                                         "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN
307                                         "%s%s%s\n", no, ptr->program->name,
308                                         from, domain);
309                 if (!done)
310                         break;
311         }
312         return done;
313 }
314
315 /**
316  * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list.
317  *
318  * @data:      String to parse.
319  * @is_not:    True if it is "no_initialize_domain" entry.
320  * @is_delete: True if it is a delete request.
321  *
322  * Returns 0 on success, negative value otherwise.
323  *
324  * Caller holds tomoyo_read_lock().
325  */
326 int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
327                                            const bool is_delete)
328 {
329         char *cp = strstr(data, " from ");
330
331         if (cp) {
332                 *cp = '\0';
333                 return tomoyo_update_domain_initializer_entry(cp + 6, data,
334                                                               is_not,
335                                                               is_delete);
336         }
337         return tomoyo_update_domain_initializer_entry(NULL, data, is_not,
338                                                       is_delete);
339 }
340
341 /**
342  * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization.
343  *
344  * @domainname: The name of domain.
345  * @program:    The name of program.
346  * @last_name:  The last component of @domainname.
347  *
348  * Returns true if executing @program reinitializes domain transition,
349  * false otherwise.
350  *
351  * Caller holds tomoyo_read_lock().
352  */
353 static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
354                                          domainname,
355                                          const struct tomoyo_path_info *program,
356                                          const struct tomoyo_path_info *
357                                          last_name)
358 {
359         struct tomoyo_domain_initializer_entry *ptr;
360         bool flag = false;
361
362         list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
363                 if (ptr->is_deleted)
364                         continue;
365                 if (ptr->domainname) {
366                         if (!ptr->is_last_name) {
367                                 if (ptr->domainname != domainname)
368                                         continue;
369                         } else {
370                                 if (tomoyo_pathcmp(ptr->domainname, last_name))
371                                         continue;
372                         }
373                 }
374                 if (tomoyo_pathcmp(ptr->program, program))
375                         continue;
376                 if (ptr->is_not) {
377                         flag = false;
378                         break;
379                 }
380                 flag = true;
381         }
382         return flag;
383 }
384
385 /*
386  * tomoyo_domain_keeper_list is used for holding list of domainnames which
387  * suppresses domain transition. Normally, a domainname is monotonically
388  * getting longer. But sometimes, we want to suppress domain transition.
389  * It would be convenient for us that programs executed from a login session
390  * belong to the same domain. Thus, TOMOYO provides a way to suppress domain
391  * transition.
392  *
393  * An entry is added by
394  *
395  * # echo 'keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
396  *                              /sys/kernel/security/tomoyo/exception_policy
397  *
398  * and is deleted by
399  *
400  * # echo 'delete keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
401  *                              /sys/kernel/security/tomoyo/exception_policy
402  *
403  * and all entries are retrieved by
404  *
405  * # grep ^keep_domain /sys/kernel/security/tomoyo/exception_policy
406  *
407  * In the example above, any process which belongs to
408  * "<kernel> /usr/sbin/sshd /bin/bash" domain will remain in that domain,
409  * unless explicitly specified by "initialize_domain" or "no_keep_domain".
410  *
411  * You may specify a program using "from" keyword.
412  * "keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash"
413  * will cause "/bin/pwd" executed from "<kernel> /usr/sbin/sshd /bin/bash"
414  * domain to remain in "<kernel> /usr/sbin/sshd /bin/bash" domain.
415  *
416  * You may add "no_" prefix to "keep_domain".
417  * "keep_domain <kernel> /usr/sbin/sshd /bin/bash" and
418  * "no_keep_domain /usr/bin/passwd from <kernel> /usr/sbin/sshd /bin/bash" will
419  * cause "/usr/bin/passwd" to belong to
420  * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless
421  * explicitly specified by "initialize_domain".
422  */
423 static LIST_HEAD(tomoyo_domain_keeper_list);
424
425 /**
426  * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
427  *
428  * @domainname: The name of domain.
429  * @program:    The name of program. May be NULL.
430  * @is_not:     True if it is "no_keep_domain" entry.
431  * @is_delete:  True if it is a delete request.
432  *
433  * Returns 0 on success, negative value otherwise.
434  *
435  * Caller holds tomoyo_read_lock().
436  */
437 static int tomoyo_update_domain_keeper_entry(const char *domainname,
438                                              const char *program,
439                                              const bool is_not,
440                                              const bool is_delete)
441 {
442         struct tomoyo_domain_keeper_entry *new_entry;
443         struct tomoyo_domain_keeper_entry *ptr;
444         const struct tomoyo_path_info *saved_domainname;
445         const struct tomoyo_path_info *saved_program = NULL;
446         int error = -ENOMEM;
447         bool is_last_name = false;
448
449         if (!tomoyo_is_domain_def(domainname) &&
450             tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
451                 is_last_name = true;
452         else if (!tomoyo_is_correct_domain(domainname, __func__))
453                 return -EINVAL;
454         if (program) {
455                 if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
456                         return -EINVAL;
457                 saved_program = tomoyo_save_name(program);
458                 if (!saved_program)
459                         return -ENOMEM;
460         }
461         saved_domainname = tomoyo_save_name(domainname);
462         if (!saved_domainname)
463                 return -ENOMEM;
464         mutex_lock(&tomoyo_policy_lock);
465         list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
466                 if (ptr->is_not != is_not ||
467                     ptr->domainname != saved_domainname ||
468                     ptr->program != saved_program)
469                         continue;
470                 ptr->is_deleted = is_delete;
471                 error = 0;
472                 goto out;
473         }
474         if (is_delete) {
475                 error = -ENOENT;
476                 goto out;
477         }
478         new_entry = tomoyo_alloc_element(sizeof(*new_entry));
479         if (!new_entry)
480                 goto out;
481         new_entry->domainname = saved_domainname;
482         new_entry->program = saved_program;
483         new_entry->is_not = is_not;
484         new_entry->is_last_name = is_last_name;
485         list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list);
486         error = 0;
487  out:
488         mutex_unlock(&tomoyo_policy_lock);
489         return error;
490 }
491
492 /**
493  * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list.
494  *
495  * @data:      String to parse.
496  * @is_not:    True if it is "no_keep_domain" entry.
497  * @is_delete: True if it is a delete request.
498  *
499  * Caller holds tomoyo_read_lock().
500  */
501 int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
502                                       const bool is_delete)
503 {
504         char *cp = strstr(data, " from ");
505
506         if (cp) {
507                 *cp = '\0';
508                 return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not,
509                                                          is_delete);
510         }
511         return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete);
512 }
513
514 /**
515  * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list.
516  *
517  * @head: Pointer to "struct tomoyo_io_buffer".
518  *
519  * Returns true on success, false otherwise.
520  *
521  * Caller holds tomoyo_read_lock().
522  */
523 bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
524 {
525         struct list_head *pos;
526         bool done = true;
527
528         list_for_each_cookie(pos, head->read_var2,
529                              &tomoyo_domain_keeper_list) {
530                 struct tomoyo_domain_keeper_entry *ptr;
531                 const char *no;
532                 const char *from = "";
533                 const char *program = "";
534
535                 ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, list);
536                 if (ptr->is_deleted)
537                         continue;
538                 no = ptr->is_not ? "no_" : "";
539                 if (ptr->program) {
540                         from = " from ";
541                         program = ptr->program->name;
542                 }
543                 done = tomoyo_io_printf(head,
544                                         "%s" TOMOYO_KEYWORD_KEEP_DOMAIN
545                                         "%s%s%s\n", no, program, from,
546                                         ptr->domainname->name);
547                 if (!done)
548                         break;
549         }
550         return done;
551 }
552
553 /**
554  * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression.
555  *
556  * @domainname: The name of domain.
557  * @program:    The name of program.
558  * @last_name:  The last component of @domainname.
559  *
560  * Returns true if executing @program supresses domain transition,
561  * false otherwise.
562  *
563  * Caller holds tomoyo_read_lock().
564  */
565 static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
566                                     const struct tomoyo_path_info *program,
567                                     const struct tomoyo_path_info *last_name)
568 {
569         struct tomoyo_domain_keeper_entry *ptr;
570         bool flag = false;
571
572         list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
573                 if (ptr->is_deleted)
574                         continue;
575                 if (!ptr->is_last_name) {
576                         if (ptr->domainname != domainname)
577                                 continue;
578                 } else {
579                         if (tomoyo_pathcmp(ptr->domainname, last_name))
580                                 continue;
581                 }
582                 if (ptr->program && tomoyo_pathcmp(ptr->program, program))
583                         continue;
584                 if (ptr->is_not) {
585                         flag = false;
586                         break;
587                 }
588                 flag = true;
589         }
590         return flag;
591 }
592
593 /*
594  * tomoyo_alias_list is used for holding list of symlink's pathnames which are
595  * allowed to be passed to an execve() request. Normally, the domainname which
596  * the current process will belong to after execve() succeeds is calculated
597  * using dereferenced pathnames. But some programs behave differently depending
598  * on the name passed to argv[0]. For busybox, calculating domainname using
599  * dereferenced pathnames will cause all programs in the busybox to belong to
600  * the same domain. Thus, TOMOYO provides a way to allow use of symlink's
601  * pathname for checking execve()'s permission and calculating domainname which
602  * the current process will belong to after execve() succeeds.
603  *
604  * An entry is added by
605  *
606  * # echo 'alias /bin/busybox /bin/cat' > \
607  *                            /sys/kernel/security/tomoyo/exception_policy
608  *
609  * and is deleted by
610  *
611  * # echo 'delete alias /bin/busybox /bin/cat' > \
612  *                            /sys/kernel/security/tomoyo/exception_policy
613  *
614  * and all entries are retrieved by
615  *
616  * # grep ^alias /sys/kernel/security/tomoyo/exception_policy
617  *
618  * In the example above, if /bin/cat is a symlink to /bin/busybox and execution
619  * of /bin/cat is requested, permission is checked for /bin/cat rather than
620  * /bin/busybox and domainname which the current process will belong to after
621  * execve() succeeds is calculated using /bin/cat rather than /bin/busybox .
622  */
623 static LIST_HEAD(tomoyo_alias_list);
624
625 /**
626  * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
627  *
628  * @original_name: The original program's real name.
629  * @aliased_name:  The symbolic program's symbolic link's name.
630  * @is_delete:     True if it is a delete request.
631  *
632  * Returns 0 on success, negative value otherwise.
633  *
634  * Caller holds tomoyo_read_lock().
635  */
636 static int tomoyo_update_alias_entry(const char *original_name,
637                                      const char *aliased_name,
638                                      const bool is_delete)
639 {
640         struct tomoyo_alias_entry *new_entry;
641         struct tomoyo_alias_entry *ptr;
642         const struct tomoyo_path_info *saved_original_name;
643         const struct tomoyo_path_info *saved_aliased_name;
644         int error = -ENOMEM;
645
646         if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) ||
647             !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__))
648                 return -EINVAL; /* No patterns allowed. */
649         saved_original_name = tomoyo_save_name(original_name);
650         saved_aliased_name = tomoyo_save_name(aliased_name);
651         if (!saved_original_name || !saved_aliased_name)
652                 return -ENOMEM;
653         mutex_lock(&tomoyo_policy_lock);
654         list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
655                 if (ptr->original_name != saved_original_name ||
656                     ptr->aliased_name != saved_aliased_name)
657                         continue;
658                 ptr->is_deleted = is_delete;
659                 error = 0;
660                 goto out;
661         }
662         if (is_delete) {
663                 error = -ENOENT;
664                 goto out;
665         }
666         new_entry = tomoyo_alloc_element(sizeof(*new_entry));
667         if (!new_entry)
668                 goto out;
669         new_entry->original_name = saved_original_name;
670         new_entry->aliased_name = saved_aliased_name;
671         list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list);
672         error = 0;
673  out:
674         mutex_unlock(&tomoyo_policy_lock);
675         return error;
676 }
677
678 /**
679  * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list.
680  *
681  * @head: Pointer to "struct tomoyo_io_buffer".
682  *
683  * Returns true on success, false otherwise.
684  *
685  * Caller holds tomoyo_read_lock().
686  */
687 bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
688 {
689         struct list_head *pos;
690         bool done = true;
691
692         list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
693                 struct tomoyo_alias_entry *ptr;
694
695                 ptr = list_entry(pos, struct tomoyo_alias_entry, list);
696                 if (ptr->is_deleted)
697                         continue;
698                 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n",
699                                         ptr->original_name->name,
700                                         ptr->aliased_name->name);
701                 if (!done)
702                         break;
703         }
704         return done;
705 }
706
707 /**
708  * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list.
709  *
710  * @data:      String to parse.
711  * @is_delete: True if it is a delete request.
712  *
713  * Returns 0 on success, negative value otherwise.
714  *
715  * Caller holds tomoyo_read_lock().
716  */
717 int tomoyo_write_alias_policy(char *data, const bool is_delete)
718 {
719         char *cp = strchr(data, ' ');
720
721         if (!cp)
722                 return -EINVAL;
723         *cp++ = '\0';
724         return tomoyo_update_alias_entry(data, cp, is_delete);
725 }
726
727 /**
728  * tomoyo_find_or_assign_new_domain - Create a domain.
729  *
730  * @domainname: The name of domain.
731  * @profile:    Profile number to assign if the domain was newly created.
732  *
733  * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
734  *
735  * Caller holds tomoyo_read_lock().
736  */
737 struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
738                                                             domainname,
739                                                             const u8 profile)
740 {
741         struct tomoyo_domain_info *domain = NULL;
742         const struct tomoyo_path_info *saved_domainname;
743
744         mutex_lock(&tomoyo_policy_lock);
745         domain = tomoyo_find_domain(domainname);
746         if (domain)
747                 goto out;
748         if (!tomoyo_is_correct_domain(domainname, __func__))
749                 goto out;
750         saved_domainname = tomoyo_save_name(domainname);
751         if (!saved_domainname)
752                 goto out;
753         /* Can I reuse memory of deleted domain? */
754         list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
755                 struct task_struct *p;
756                 struct tomoyo_acl_info *ptr;
757                 bool flag;
758                 if (!domain->is_deleted ||
759                     domain->domainname != saved_domainname)
760                         continue;
761                 flag = false;
762                 read_lock(&tasklist_lock);
763                 for_each_process(p) {
764                         if (tomoyo_real_domain(p) != domain)
765                                 continue;
766                         flag = true;
767                         break;
768                 }
769                 read_unlock(&tasklist_lock);
770                 if (flag)
771                         continue;
772                 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
773                         ptr->type |= TOMOYO_ACL_DELETED;
774                 }
775                 tomoyo_set_domain_flag(domain, true, domain->flags);
776                 domain->profile = profile;
777                 domain->quota_warned = false;
778                 mb(); /* Avoid out-of-order execution. */
779                 domain->is_deleted = false;
780                 goto out;
781         }
782         /* No memory reusable. Create using new memory. */
783         domain = tomoyo_alloc_element(sizeof(*domain));
784         if (domain) {
785                 INIT_LIST_HEAD(&domain->acl_info_list);
786                 domain->domainname = saved_domainname;
787                 domain->profile = profile;
788                 list_add_tail_rcu(&domain->list, &tomoyo_domain_list);
789         }
790  out:
791         mutex_unlock(&tomoyo_policy_lock);
792         return domain;
793 }
794
795 /**
796  * tomoyo_find_next_domain - Find a domain.
797  *
798  * @bprm: Pointer to "struct linux_binprm".
799  *
800  * Returns 0 on success, negative value otherwise.
801  *
802  * Caller holds tomoyo_read_lock().
803  */
804 int tomoyo_find_next_domain(struct linux_binprm *bprm)
805 {
806         /*
807          * This function assumes that the size of buffer returned by
808          * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
809          */
810         struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp));
811         struct tomoyo_domain_info *old_domain = tomoyo_domain();
812         struct tomoyo_domain_info *domain = NULL;
813         const char *old_domain_name = old_domain->domainname->name;
814         const char *original_name = bprm->filename;
815         char *new_domain_name = NULL;
816         char *real_program_name = NULL;
817         char *symlink_program_name = NULL;
818         const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE);
819         const bool is_enforce = (mode == 3);
820         int retval = -ENOMEM;
821         struct tomoyo_path_info r; /* real name */
822         struct tomoyo_path_info s; /* symlink name */
823         struct tomoyo_path_info l; /* last name */
824         static bool initialized;
825
826         if (!tmp)
827                 goto out;
828
829         if (!initialized) {
830                 /*
831                  * Built-in initializers. This is needed because policies are
832                  * not loaded until starting /sbin/init.
833                  */
834                 tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug",
835                                                        false, false);
836                 tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe",
837                                                        false, false);
838                 initialized = true;
839         }
840
841         /* Get tomoyo_realpath of program. */
842         retval = -ENOENT;
843         /* I hope tomoyo_realpath() won't fail with -ENOMEM. */
844         real_program_name = tomoyo_realpath(original_name);
845         if (!real_program_name)
846                 goto out;
847         /* Get tomoyo_realpath of symbolic link. */
848         symlink_program_name = tomoyo_realpath_nofollow(original_name);
849         if (!symlink_program_name)
850                 goto out;
851
852         r.name = real_program_name;
853         tomoyo_fill_path_info(&r);
854         s.name = symlink_program_name;
855         tomoyo_fill_path_info(&s);
856         l.name = tomoyo_get_last_name(old_domain);
857         tomoyo_fill_path_info(&l);
858
859         /* Check 'alias' directive. */
860         if (tomoyo_pathcmp(&r, &s)) {
861                 struct tomoyo_alias_entry *ptr;
862                 /* Is this program allowed to be called via symbolic links? */
863                 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
864                         if (ptr->is_deleted ||
865                             tomoyo_pathcmp(&r, ptr->original_name) ||
866                             tomoyo_pathcmp(&s, ptr->aliased_name))
867                                 continue;
868                         memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN);
869                         strncpy(real_program_name, ptr->aliased_name->name,
870                                 TOMOYO_MAX_PATHNAME_LEN - 1);
871                         tomoyo_fill_path_info(&r);
872                         break;
873                 }
874         }
875
876         /* Check execute permission. */
877         retval = tomoyo_check_exec_perm(old_domain, &r);
878         if (retval < 0)
879                 goto out;
880
881         new_domain_name = tmp->buffer;
882         if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) {
883                 /* Transit to the child of tomoyo_kernel_domain domain. */
884                 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
885                          TOMOYO_ROOT_NAME " " "%s", real_program_name);
886         } else if (old_domain == &tomoyo_kernel_domain &&
887                    !tomoyo_policy_loaded) {
888                 /*
889                  * Needn't to transit from kernel domain before starting
890                  * /sbin/init. But transit from kernel domain if executing
891                  * initializers because they might start before /sbin/init.
892                  */
893                 domain = old_domain;
894         } else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) {
895                 /* Keep current domain. */
896                 domain = old_domain;
897         } else {
898                 /* Normal domain transition. */
899                 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
900                          "%s %s", old_domain_name, real_program_name);
901         }
902         if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
903                 goto done;
904         domain = tomoyo_find_domain(new_domain_name);
905         if (domain)
906                 goto done;
907         if (is_enforce)
908                 goto done;
909         domain = tomoyo_find_or_assign_new_domain(new_domain_name,
910                                                   old_domain->profile);
911  done:
912         if (domain)
913                 goto out;
914         printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
915                new_domain_name);
916         if (is_enforce)
917                 retval = -EPERM;
918         else
919                 tomoyo_set_domain_flag(old_domain, false,
920                                        TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED);
921  out:
922         if (!domain)
923                 domain = old_domain;
924         bprm->cred->security = domain;
925         tomoyo_free(real_program_name);
926         tomoyo_free(symlink_program_name);
927         tomoyo_free(tmp);
928         return retval;
929 }