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