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