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