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