オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Annotation of /branches/ccs-patch/security/ccsecurity/domain.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2030 - (hide annotations) (download) (as text)
Thu Jan 1 01:40:06 2009 UTC (15 years, 5 months ago) by kumaneko
Original Path: trunk/1.6.x/ccs-patch/fs/tomoyo_domain.c
File MIME type: text/x-csrc
File size: 46845 byte(s)


1 kumaneko 111 /*
2     * fs/tomoyo_domain.c
3     *
4     * Implementation of the Domain-Based Mandatory Access Control.
5     *
6 kumaneko 2030 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 kumaneko 111 *
8 kumaneko 2002 * Version: 1.6.6-pre 2008/12/24
9 kumaneko 111 *
10     * This file is applicable to both 2.4.30 and 2.6.11 and later.
11     * See README.ccs for ChangeLog.
12     *
13     */
14    
15     #include <linux/ccs_common.h>
16     #include <linux/tomoyo.h>
17     #include <linux/realpath.h>
18 kumaneko 115 #include <linux/highmem.h>
19 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
20     #include <linux/namei.h>
21     #include <linux/mount.h>
22     #endif
23 kumaneko 115
24 kumaneko 1052 /* For compatibility with older kernels. */
25 kumaneko 111 #ifndef for_each_process
26     #define for_each_process for_each_task
27     #endif
28    
29 kumaneko 1052 /* Variables definitions.*/
30 kumaneko 111
31     /* The initial domain. */
32 kumaneko 708 struct domain_info KERNEL_DOMAIN;
33 kumaneko 111
34 kumaneko 1052 /* The list for "struct domain_info". */
35 kumaneko 2002 LIST1_HEAD(ccs_domain_list);
36 kumaneko 708
37 kumaneko 111 #ifdef CONFIG_TOMOYO
38    
39 kumaneko 1052 /* Domain creation lock. */
40 kumaneko 2002 static DEFINE_MUTEX(ccs_domain_list_lock);
41 kumaneko 111
42 kumaneko 1052 /* Structure for "initialize_domain" and "no_initialize_domain" keyword. */
43 kumaneko 2002 struct ccs_domain_initializer_entry {
44 kumaneko 722 struct list1_head list;
45 kumaneko 2002 const struct ccs_path_info *domainname; /* This may be NULL */
46     const struct ccs_path_info *program;
47 kumaneko 621 bool is_deleted;
48 kumaneko 1052 bool is_not; /* True if this entry is "no_initialize_domain". */
49     bool is_last_name; /* True if the domainname is ccs_get_last_name(). */
50 kumaneko 214 };
51 kumaneko 111
52 kumaneko 1052 /* Structure for "keep_domain" and "no_keep_domain" keyword. */
53 kumaneko 2002 struct ccs_domain_keeper_entry {
54 kumaneko 722 struct list1_head list;
55 kumaneko 2002 const struct ccs_path_info *domainname;
56     const struct ccs_path_info *program; /* This may be NULL */
57 kumaneko 621 bool is_deleted;
58 kumaneko 1052 bool is_not; /* True if this entry is "no_keep_domain". */
59     bool is_last_name; /* True if the domainname is ccs_get_last_name(). */
60 kumaneko 214 };
61 kumaneko 111
62 kumaneko 1052 /* Structure for "aggregator" keyword. */
63 kumaneko 2002 struct ccs_aggregator_entry {
64 kumaneko 722 struct list1_head list;
65 kumaneko 2002 const struct ccs_path_info *original_name;
66     const struct ccs_path_info *aggregated_name;
67 kumaneko 621 bool is_deleted;
68 kumaneko 214 };
69 kumaneko 111
70 kumaneko 1052 /* Structure for "alias" keyword. */
71 kumaneko 2002 struct ccs_alias_entry {
72 kumaneko 722 struct list1_head list;
73 kumaneko 2002 const struct ccs_path_info *original_name;
74     const struct ccs_path_info *aliased_name;
75 kumaneko 621 bool is_deleted;
76 kumaneko 214 };
77 kumaneko 111
78 kumaneko 1052 /**
79     * ccs_set_domain_flag - Set or clear domain's attribute flags.
80     *
81     * @domain: Pointer to "struct domain_info".
82     * @is_delete: True if it is a delete request.
83     * @flags: Flags to set or clear.
84     *
85     * Returns nothing.
86     */
87     void ccs_set_domain_flag(struct domain_info *domain, const bool is_delete,
88     const u8 flags)
89 kumaneko 1029 {
90 kumaneko 1700 /* We need to serialize because this is bitfield operation. */
91     static DEFINE_SPINLOCK(lock);
92     /***** CRITICAL SECTION START *****/
93     spin_lock(&lock);
94 kumaneko 1052 if (!is_delete)
95     domain->flags |= flags;
96     else
97     domain->flags &= ~flags;
98 kumaneko 1700 spin_unlock(&lock);
99     /***** CRITICAL SECTION END *****/
100 kumaneko 1029 }
101    
102 kumaneko 1052 /**
103     * ccs_get_last_name - Get last component of a domainname.
104     *
105     * @domain: Pointer to "struct domain_info".
106     *
107     * Returns the last component of the domainname.
108     */
109     const char *ccs_get_last_name(const struct domain_info *domain)
110 kumaneko 111 {
111 kumaneko 1687 const char *cp0 = domain->domainname->name;
112     const char *cp1 = strrchr(cp0, ' ');
113 kumaneko 1052 if (cp1)
114     return cp1 + 1;
115 kumaneko 111 return cp0;
116     }
117    
118 kumaneko 1052 /**
119     * ccs_add_domain_acl - Add the given ACL to the given domain.
120     *
121 kumaneko 1064 * @domain: Pointer to "struct domain_info". May be NULL.
122 kumaneko 2002 * @acl: Pointer to "struct ccs_acl_info".
123 kumaneko 1052 *
124     * Returns 0.
125     */
126 kumaneko 2002 int ccs_add_domain_acl(struct domain_info *domain, struct ccs_acl_info *acl)
127 kumaneko 111 {
128 kumaneko 1695 if (domain) {
129     /*
130     * We need to serialize because this function is called by
131     * various update functions.
132     */
133     static DEFINE_SPINLOCK(lock);
134     /***** CRITICAL SECTION START *****/
135     spin_lock(&lock);
136 kumaneko 1052 list1_add_tail_mb(&acl->list, &domain->acl_info_list);
137 kumaneko 1695 spin_unlock(&lock);
138     /***** CRITICAL SECTION END *****/
139     } else {
140 kumaneko 1052 acl->type &= ~ACL_DELETED;
141 kumaneko 1695 }
142 kumaneko 1052 ccs_update_counter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);
143 kumaneko 111 return 0;
144     }
145    
146 kumaneko 1052 /**
147     * ccs_del_domain_acl - Delete the given ACL from the domain.
148     *
149 kumaneko 2002 * @acl: Pointer to "struct ccs_acl_info". May be NULL.
150 kumaneko 1052 *
151     * Returns 0.
152     */
153 kumaneko 2002 int ccs_del_domain_acl(struct ccs_acl_info *acl)
154 kumaneko 111 {
155 kumaneko 1052 if (acl)
156     acl->type |= ACL_DELETED;
157     ccs_update_counter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);
158 kumaneko 111 return 0;
159     }
160    
161 kumaneko 1052 /**
162 kumaneko 2002 * ccs_audit_execute_handler_log - Audit execute_handler log.
163 kumaneko 1052 *
164 kumaneko 1064 * @is_default: True if it is "execute_handler" log.
165     * @handler: The realpath of the handler.
166     * @bprm: Pointer to "struct linux_binprm".
167 kumaneko 1052 *
168     * Returns 0 on success, negative value otherwise.
169     */
170 kumaneko 2002 static int ccs_audit_execute_handler_log(const bool is_default,
171     const char *handler,
172     struct linux_binprm *bprm)
173 kumaneko 1052 {
174 kumaneko 1657 struct ccs_request_info r;
175     ccs_init_request_info(&r, NULL, CCS_TOMOYO_MAC_FOR_FILE);
176     r.bprm = bprm;
177     return ccs_write_audit_log(true, &r, "%s %s\n",
178     is_default ? KEYWORD_EXECUTE_HANDLER :
179     KEYWORD_DENIED_EXECUTE_HANDLER, handler);
180 kumaneko 1052 }
181 kumaneko 111
182 kumaneko 1052 /**
183 kumaneko 2002 * ccs_audit_domain_creation_log - Audit domain creation log.
184 kumaneko 1052 *
185 kumaneko 1657 * @domain: Pointer to "struct domain_info".
186 kumaneko 1052 *
187     * Returns 0 on success, negative value otherwise.
188     */
189 kumaneko 2002 static int ccs_audit_domain_creation_log(struct domain_info *domain)
190 kumaneko 1052 {
191 kumaneko 1657 struct ccs_request_info r;
192     ccs_init_request_info(&r, domain, CCS_TOMOYO_MAC_FOR_FILE);
193     return ccs_write_audit_log(false, &r, "use_profile %u\n", r.profile);
194 kumaneko 1052 }
195    
196 kumaneko 2002 /* The list for "struct ccs_domain_initializer_entry". */
197     static LIST1_HEAD(ccs_domain_initializer_list);
198 kumaneko 111
199 kumaneko 1052 /**
200 kumaneko 2002 * ccs_update_domain_initializer_entry - Update "struct ccs_domain_initializer_entry" list.
201 kumaneko 1052 *
202     * @domainname: The name of domain. May be NULL.
203     * @program: The name of program.
204     * @is_not: True if it is "no_initialize_domain" entry.
205     * @is_delete: True if it is a delete request.
206     *
207     * Returns 0 on success, negative value otherwise.
208     */
209 kumaneko 2002 static int ccs_update_domain_initializer_entry(const char *domainname,
210     const char *program,
211     const bool is_not,
212     const bool is_delete)
213 kumaneko 111 {
214 kumaneko 2002 struct ccs_domain_initializer_entry *new_entry;
215     struct ccs_domain_initializer_entry *ptr;
216 kumaneko 652 static DEFINE_MUTEX(lock);
217 kumaneko 2002 const struct ccs_path_info *saved_program;
218     const struct ccs_path_info *saved_domainname = NULL;
219 kumaneko 111 int error = -ENOMEM;
220 kumaneko 1016 bool is_last_name = false;
221 kumaneko 1052 if (!ccs_is_correct_path(program, 1, -1, -1, __func__))
222     return -EINVAL; /* No patterns allowed. */
223 kumaneko 111 if (domainname) {
224 kumaneko 1052 if (!ccs_is_domain_def(domainname) &&
225     ccs_is_correct_path(domainname, 1, -1, -1, __func__))
226 kumaneko 1016 is_last_name = true;
227 kumaneko 1052 else if (!ccs_is_correct_domain(domainname, __func__))
228 kumaneko 111 return -EINVAL;
229 kumaneko 1052 saved_domainname = ccs_save_name(domainname);
230     if (!saved_domainname)
231     return -ENOMEM;
232 kumaneko 111 }
233 kumaneko 1052 saved_program = ccs_save_name(program);
234     if (!saved_program)
235     return -ENOMEM;
236 kumaneko 652 mutex_lock(&lock);
237 kumaneko 2002 list1_for_each_entry(ptr, &ccs_domain_initializer_list, list) {
238 kumaneko 1052 if (ptr->is_not != is_not ||
239     ptr->domainname != saved_domainname ||
240     ptr->program != saved_program)
241     continue;
242     ptr->is_deleted = is_delete;
243     error = 0;
244     goto out;
245 kumaneko 111 }
246     if (is_delete) {
247     error = -ENOENT;
248     goto out;
249     }
250 kumaneko 1052 new_entry = ccs_alloc_element(sizeof(*new_entry));
251     if (!new_entry)
252     goto out;
253 kumaneko 111 new_entry->domainname = saved_domainname;
254     new_entry->program = saved_program;
255     new_entry->is_not = is_not;
256     new_entry->is_last_name = is_last_name;
257 kumaneko 2002 list1_add_tail_mb(&new_entry->list, &ccs_domain_initializer_list);
258 kumaneko 111 error = 0;
259     out:
260 kumaneko 652 mutex_unlock(&lock);
261 kumaneko 1064 ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
262 kumaneko 111 return error;
263     }
264    
265 kumaneko 1052 /**
266 kumaneko 2002 * ccs_read_domain_initializer_policy - Read "struct ccs_domain_initializer_entry" list.
267 kumaneko 1052 *
268     * @head: Pointer to "struct ccs_io_buffer".
269     *
270     * Returns true on success, false otherwise.
271     */
272     bool ccs_read_domain_initializer_policy(struct ccs_io_buffer *head)
273 kumaneko 111 {
274 kumaneko 722 struct list1_head *pos;
275 kumaneko 2002 list1_for_each_cookie(pos, head->read_var2,
276     &ccs_domain_initializer_list) {
277 kumaneko 1064 const char *no;
278     const char *from = "";
279     const char *domain = "";
280 kumaneko 2002 struct ccs_domain_initializer_entry *ptr;
281     ptr = list1_entry(pos, struct ccs_domain_initializer_entry,
282     list);
283 kumaneko 1052 if (ptr->is_deleted)
284     continue;
285 kumaneko 1064 no = ptr->is_not ? "no_" : "";
286 kumaneko 708 if (ptr->domainname) {
287 kumaneko 1064 from = " from ";
288     domain = ptr->domainname->name;
289     }
290     if (!ccs_io_printf(head,
291     "%s" KEYWORD_INITIALIZE_DOMAIN "%s%s%s\n",
292     no, ptr->program->name, from, domain))
293 kumaneko 2002 goto out;
294 kumaneko 111 }
295 kumaneko 1052 return true;
296     out:
297     return false;
298 kumaneko 111 }
299    
300 kumaneko 1052 /**
301 kumaneko 2002 * ccs_write_domain_initializer_policy - Write "struct ccs_domain_initializer_entry" list.
302 kumaneko 1052 *
303     * @data: String to parse.
304     * @is_not: True if it is "no_initialize_domain" entry.
305     * @is_delete: True if it is a delete request.
306     *
307     * Returns 0 on success, negative value otherwise.
308     */
309     int ccs_write_domain_initializer_policy(char *data, const bool is_not,
310     const bool is_delete)
311 kumaneko 111 {
312     char *cp = strstr(data, " from ");
313     if (cp) {
314     *cp = '\0';
315 kumaneko 2002 return ccs_update_domain_initializer_entry(cp + 6, data,
316     is_not, is_delete);
317 kumaneko 111 }
318 kumaneko 2002 return ccs_update_domain_initializer_entry(NULL, data, is_not,
319     is_delete);
320 kumaneko 111 }
321    
322 kumaneko 1052 /**
323 kumaneko 2002 * ccs_is_domain_initializer - Check whether the given program causes domainname reinitialization.
324 kumaneko 1052 *
325     * @domainname: The name of domain.
326     * @program: The name of program.
327     * @last_name: The last component of @domainname.
328     *
329     * Returns true if executing @program reinitializes domain transition,
330     * false otherwise.
331     */
332 kumaneko 2002 static bool ccs_is_domain_initializer(const struct ccs_path_info *domainname,
333     const struct ccs_path_info *program,
334     const struct ccs_path_info *last_name)
335 kumaneko 111 {
336 kumaneko 2002 struct ccs_domain_initializer_entry *ptr;
337 kumaneko 1016 bool flag = false;
338 kumaneko 2002 list1_for_each_entry(ptr, &ccs_domain_initializer_list, list) {
339 kumaneko 1052 if (ptr->is_deleted)
340     continue;
341 kumaneko 111 if (ptr->domainname) {
342     if (!ptr->is_last_name) {
343 kumaneko 1052 if (ptr->domainname != domainname)
344     continue;
345 kumaneko 111 } else {
346 kumaneko 1052 if (ccs_pathcmp(ptr->domainname, last_name))
347     continue;
348 kumaneko 111 }
349     }
350 kumaneko 1052 if (ccs_pathcmp(ptr->program, program))
351     continue;
352     if (ptr->is_not)
353     return false;
354 kumaneko 1016 flag = true;
355 kumaneko 111 }
356     return flag;
357     }
358    
359 kumaneko 2002 /* The list for "struct ccs_domain_keeper_entry". */
360     static LIST1_HEAD(ccs_domain_keeper_list);
361 kumaneko 111
362 kumaneko 1052 /**
363 kumaneko 2002 * ccs_update_domain_keeper_entry - Update "struct ccs_domain_keeper_entry" list.
364 kumaneko 1052 *
365     * @domainname: The name of domain.
366     * @program: The name of program. May be NULL.
367     * @is_not: True if it is "no_keep_domain" entry.
368     * @is_delete: True if it is a delete request.
369     *
370     * Returns 0 on success, negative value otherwise.
371     */
372 kumaneko 2002 static int ccs_update_domain_keeper_entry(const char *domainname,
373     const char *program,
374     const bool is_not,
375     const bool is_delete)
376 kumaneko 111 {
377 kumaneko 2002 struct ccs_domain_keeper_entry *new_entry;
378     struct ccs_domain_keeper_entry *ptr;
379     const struct ccs_path_info *saved_domainname;
380     const struct ccs_path_info *saved_program = NULL;
381 kumaneko 652 static DEFINE_MUTEX(lock);
382 kumaneko 111 int error = -ENOMEM;
383 kumaneko 1016 bool is_last_name = false;
384 kumaneko 1052 if (!ccs_is_domain_def(domainname) &&
385     ccs_is_correct_path(domainname, 1, -1, -1, __func__))
386 kumaneko 1016 is_last_name = true;
387 kumaneko 1052 else if (!ccs_is_correct_domain(domainname, __func__))
388 kumaneko 111 return -EINVAL;
389     if (program) {
390 kumaneko 1052 if (!ccs_is_correct_path(program, 1, -1, -1, __func__))
391     return -EINVAL;
392     saved_program = ccs_save_name(program);
393     if (!saved_program)
394     return -ENOMEM;
395 kumaneko 111 }
396 kumaneko 1052 saved_domainname = ccs_save_name(domainname);
397     if (!saved_domainname)
398     return -ENOMEM;
399 kumaneko 652 mutex_lock(&lock);
400 kumaneko 2002 list1_for_each_entry(ptr, &ccs_domain_keeper_list, list) {
401 kumaneko 1052 if (ptr->is_not != is_not ||
402     ptr->domainname != saved_domainname ||
403     ptr->program != saved_program)
404     continue;
405     ptr->is_deleted = is_delete;
406     error = 0;
407     goto out;
408 kumaneko 111 }
409     if (is_delete) {
410     error = -ENOENT;
411     goto out;
412     }
413 kumaneko 1052 new_entry = ccs_alloc_element(sizeof(*new_entry));
414     if (!new_entry)
415     goto out;
416 kumaneko 111 new_entry->domainname = saved_domainname;
417     new_entry->program = saved_program;
418     new_entry->is_not = is_not;
419     new_entry->is_last_name = is_last_name;
420 kumaneko 2002 list1_add_tail_mb(&new_entry->list, &ccs_domain_keeper_list);
421 kumaneko 111 error = 0;
422     out:
423 kumaneko 652 mutex_unlock(&lock);
424 kumaneko 1064 ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
425 kumaneko 111 return error;
426     }
427    
428 kumaneko 1052 /**
429 kumaneko 2002 * ccs_write_domain_keeper_policy - Write "struct ccs_domain_keeper_entry" list.
430 kumaneko 1052 *
431     * @data: String to parse.
432     * @is_not: True if it is "no_keep_domain" entry.
433     * @is_delete: True if it is a delete request.
434     *
435     */
436     int ccs_write_domain_keeper_policy(char *data, const bool is_not,
437     const bool is_delete)
438 kumaneko 111 {
439     char *cp = strstr(data, " from ");
440     if (cp) {
441     *cp = '\0';
442 kumaneko 2002 return ccs_update_domain_keeper_entry(cp + 6, data,
443     is_not, is_delete);
444 kumaneko 111 }
445 kumaneko 2002 return ccs_update_domain_keeper_entry(data, NULL, is_not, is_delete);
446 kumaneko 111 }
447    
448 kumaneko 1052 /**
449 kumaneko 2002 * ccs_read_domain_keeper_policy - Read "struct ccs_domain_keeper_entry" list.
450 kumaneko 1052 *
451     * @head: Pointer to "struct ccs_io_buffer".
452     *
453     * Returns true on success, false otherwise.
454     */
455     bool ccs_read_domain_keeper_policy(struct ccs_io_buffer *head)
456 kumaneko 111 {
457 kumaneko 722 struct list1_head *pos;
458 kumaneko 2002 list1_for_each_cookie(pos, head->read_var2, &ccs_domain_keeper_list) {
459     struct ccs_domain_keeper_entry *ptr;
460 kumaneko 1064 const char *no;
461     const char *from = "";
462     const char *program = "";
463 kumaneko 2002 ptr = list1_entry(pos, struct ccs_domain_keeper_entry, list);
464 kumaneko 1052 if (ptr->is_deleted)
465     continue;
466 kumaneko 1064 no = ptr->is_not ? "no_" : "";
467 kumaneko 708 if (ptr->program) {
468 kumaneko 1064 from = " from ";
469     program = ptr->program->name;
470     }
471     if (!ccs_io_printf(head,
472     "%s" KEYWORD_KEEP_DOMAIN "%s%s%s\n", no,
473     program, from, ptr->domainname->name))
474 kumaneko 2002 goto out;
475 kumaneko 111 }
476 kumaneko 1052 return true;
477     out:
478     return false;
479 kumaneko 111 }
480    
481 kumaneko 1052 /**
482 kumaneko 2002 * ccs_is_domain_keeper - Check whether the given program causes domain transition suppression.
483 kumaneko 1052 *
484     * @domainname: The name of domain.
485     * @program: The name of program.
486     * @last_name: The last component of @domainname.
487     *
488     * Returns true if executing @program supresses domain transition,
489     * false otherwise.
490     */
491 kumaneko 2002 static bool ccs_is_domain_keeper(const struct ccs_path_info *domainname,
492     const struct ccs_path_info *program,
493     const struct ccs_path_info *last_name)
494 kumaneko 111 {
495 kumaneko 2002 struct ccs_domain_keeper_entry *ptr;
496 kumaneko 1016 bool flag = false;
497 kumaneko 2002 list1_for_each_entry(ptr, &ccs_domain_keeper_list, list) {
498 kumaneko 1052 if (ptr->is_deleted)
499     continue;
500 kumaneko 111 if (!ptr->is_last_name) {
501 kumaneko 1052 if (ptr->domainname != domainname)
502     continue;
503 kumaneko 111 } else {
504 kumaneko 1052 if (ccs_pathcmp(ptr->domainname, last_name))
505     continue;
506 kumaneko 111 }
507 kumaneko 1052 if (ptr->program && ccs_pathcmp(ptr->program, program))
508     continue;
509     if (ptr->is_not)
510     return false;
511 kumaneko 1016 flag = true;
512 kumaneko 111 }
513     return flag;
514     }
515    
516 kumaneko 2002 /* The list for "struct ccs_alias_entry". */
517     static LIST1_HEAD(ccs_alias_list);
518 kumaneko 111
519 kumaneko 1052 /**
520 kumaneko 2002 * ccs_update_alias_entry - Update "struct ccs_alias_entry" list.
521 kumaneko 1052 *
522     * @original_name: The original program's real name.
523     * @aliased_name: The symbolic program's symbolic link's name.
524     * @is_delete: True if it is a delete request.
525     *
526     * Returns 0 on success, negative value otherwise.
527     */
528 kumaneko 2002 static int ccs_update_alias_entry(const char *original_name,
529     const char *aliased_name,
530     const bool is_delete)
531 kumaneko 111 {
532 kumaneko 2002 struct ccs_alias_entry *new_entry;
533     struct ccs_alias_entry *ptr;
534 kumaneko 652 static DEFINE_MUTEX(lock);
535 kumaneko 2002 const struct ccs_path_info *saved_original_name;
536     const struct ccs_path_info *saved_aliased_name;
537 kumaneko 111 int error = -ENOMEM;
538 kumaneko 1052 if (!ccs_is_correct_path(original_name, 1, -1, -1, __func__) ||
539     !ccs_is_correct_path(aliased_name, 1, -1, -1, __func__))
540     return -EINVAL; /* No patterns allowed. */
541     saved_original_name = ccs_save_name(original_name);
542     saved_aliased_name = ccs_save_name(aliased_name);
543     if (!saved_original_name || !saved_aliased_name)
544     return -ENOMEM;
545 kumaneko 652 mutex_lock(&lock);
546 kumaneko 2002 list1_for_each_entry(ptr, &ccs_alias_list, list) {
547 kumaneko 1052 if (ptr->original_name != saved_original_name ||
548     ptr->aliased_name != saved_aliased_name)
549     continue;
550     ptr->is_deleted = is_delete;
551     error = 0;
552     goto out;
553 kumaneko 111 }
554     if (is_delete) {
555     error = -ENOENT;
556     goto out;
557     }
558 kumaneko 1052 new_entry = ccs_alloc_element(sizeof(*new_entry));
559     if (!new_entry)
560     goto out;
561 kumaneko 111 new_entry->original_name = saved_original_name;
562     new_entry->aliased_name = saved_aliased_name;
563 kumaneko 2002 list1_add_tail_mb(&new_entry->list, &ccs_alias_list);
564 kumaneko 111 error = 0;
565     out:
566 kumaneko 652 mutex_unlock(&lock);
567 kumaneko 1064 ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
568 kumaneko 111 return error;
569     }
570    
571 kumaneko 1052 /**
572 kumaneko 2002 * ccs_read_alias_policy - Read "struct ccs_alias_entry" list.
573 kumaneko 1052 *
574     * @head: Pointer to "struct ccs_io_buffer".
575     *
576     * Returns true on success, false otherwise.
577     */
578     bool ccs_read_alias_policy(struct ccs_io_buffer *head)
579 kumaneko 111 {
580 kumaneko 722 struct list1_head *pos;
581 kumaneko 2002 list1_for_each_cookie(pos, head->read_var2, &ccs_alias_list) {
582     struct ccs_alias_entry *ptr;
583     ptr = list1_entry(pos, struct ccs_alias_entry, list);
584 kumaneko 1052 if (ptr->is_deleted)
585     continue;
586     if (!ccs_io_printf(head, KEYWORD_ALIAS "%s %s\n",
587     ptr->original_name->name,
588     ptr->aliased_name->name))
589     goto out;
590 kumaneko 111 }
591 kumaneko 1052 return true;
592     out:
593     return false;
594 kumaneko 111 }
595    
596 kumaneko 1052 /**
597 kumaneko 2002 * ccs_write_alias_policy - Write "struct ccs_alias_entry" list.
598 kumaneko 1052 *
599     * @data: String to parse.
600     * @is_delete: True if it is a delete request.
601     *
602     * Returns 0 on success, negative value otherwise.
603     */
604     int ccs_write_alias_policy(char *data, const bool is_delete)
605 kumaneko 111 {
606     char *cp = strchr(data, ' ');
607 kumaneko 1052 if (!cp)
608     return -EINVAL;
609 kumaneko 111 *cp++ = '\0';
610 kumaneko 2002 return ccs_update_alias_entry(data, cp, is_delete);
611 kumaneko 111 }
612    
613 kumaneko 2002 /* The list for "struct ccs_aggregator_entry". */
614     static LIST1_HEAD(ccs_aggregator_list);
615 kumaneko 111
616 kumaneko 1052 /**
617 kumaneko 2002 * ccs_update_aggregator_entry - Update "struct ccs_aggregator_entry" list.
618 kumaneko 1052 *
619     * @original_name: The original program's name.
620     * @aggregated_name: The aggregated program's name.
621     * @is_delete: True if it is a delete request.
622     *
623     * Returns 0 on success, negative value otherwise.
624     */
625 kumaneko 2002 static int ccs_update_aggregator_entry(const char *original_name,
626     const char *aggregated_name,
627     const bool is_delete)
628 kumaneko 111 {
629 kumaneko 2002 struct ccs_aggregator_entry *new_entry;
630     struct ccs_aggregator_entry *ptr;
631 kumaneko 652 static DEFINE_MUTEX(lock);
632 kumaneko 2002 const struct ccs_path_info *saved_original_name;
633     const struct ccs_path_info *saved_aggregated_name;
634 kumaneko 111 int error = -ENOMEM;
635 kumaneko 1052 if (!ccs_is_correct_path(original_name, 1, 0, -1, __func__) ||
636     !ccs_is_correct_path(aggregated_name, 1, -1, -1, __func__))
637     return -EINVAL;
638     saved_original_name = ccs_save_name(original_name);
639     saved_aggregated_name = ccs_save_name(aggregated_name);
640     if (!saved_original_name || !saved_aggregated_name)
641     return -ENOMEM;
642 kumaneko 652 mutex_lock(&lock);
643 kumaneko 2002 list1_for_each_entry(ptr, &ccs_aggregator_list, list) {
644 kumaneko 1052 if (ptr->original_name != saved_original_name ||
645     ptr->aggregated_name != saved_aggregated_name)
646     continue;
647     ptr->is_deleted = is_delete;
648     error = 0;
649     goto out;
650 kumaneko 111 }
651     if (is_delete) {
652     error = -ENOENT;
653     goto out;
654     }
655 kumaneko 1052 new_entry = ccs_alloc_element(sizeof(*new_entry));
656     if (!new_entry)
657     goto out;
658 kumaneko 111 new_entry->original_name = saved_original_name;
659     new_entry->aggregated_name = saved_aggregated_name;
660 kumaneko 2002 list1_add_tail_mb(&new_entry->list, &ccs_aggregator_list);
661 kumaneko 111 error = 0;
662     out:
663 kumaneko 652 mutex_unlock(&lock);
664 kumaneko 1064 ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
665 kumaneko 111 return error;
666     }
667    
668 kumaneko 1052 /**
669 kumaneko 2002 * ccs_read_aggregator_policy - Read "struct ccs_aggregator_entry" list.
670 kumaneko 1052 *
671     * @head: Pointer to "struct ccs_io_buffer".
672     *
673     * Returns true on success, false otherwise.
674     */
675     bool ccs_read_aggregator_policy(struct ccs_io_buffer *head)
676 kumaneko 111 {
677 kumaneko 722 struct list1_head *pos;
678 kumaneko 2002 list1_for_each_cookie(pos, head->read_var2, &ccs_aggregator_list) {
679     struct ccs_aggregator_entry *ptr;
680     ptr = list1_entry(pos, struct ccs_aggregator_entry, list);
681 kumaneko 1052 if (ptr->is_deleted)
682     continue;
683     if (!ccs_io_printf(head, KEYWORD_AGGREGATOR "%s %s\n",
684     ptr->original_name->name,
685     ptr->aggregated_name->name))
686     goto out;
687 kumaneko 111 }
688 kumaneko 1052 return true;
689     out:
690     return false;
691 kumaneko 111 }
692    
693 kumaneko 1052 /**
694 kumaneko 2002 * ccs_write_aggregator_policy - Write "struct ccs_aggregator_entry" list.
695 kumaneko 1052 *
696     * @data: String to parse.
697     * @is_delete: True if it is a delete request.
698     *
699     * Returns 0 on success, negative value otherwise.
700     */
701     int ccs_write_aggregator_policy(char *data, const bool is_delete)
702 kumaneko 111 {
703     char *cp = strchr(data, ' ');
704 kumaneko 1052 if (!cp)
705     return -EINVAL;
706 kumaneko 111 *cp++ = '\0';
707 kumaneko 2002 return ccs_update_aggregator_entry(data, cp, is_delete);
708 kumaneko 111 }
709    
710 kumaneko 1052 /* Domain create/delete/undelete handler. */
711 kumaneko 111
712 kumaneko 240 /* #define DEBUG_DOMAIN_UNDELETE */
713 kumaneko 111
714 kumaneko 1052 /**
715     * ccs_delete_domain - Delete a domain.
716     *
717     * @domainname: The name of domain.
718     *
719     * Returns 0.
720     */
721     int ccs_delete_domain(char *domainname)
722 kumaneko 111 {
723     struct domain_info *domain;
724 kumaneko 2002 struct ccs_path_info name;
725 kumaneko 1052 name.name = domainname;
726     ccs_fill_path_info(&name);
727 kumaneko 2002 mutex_lock(&ccs_domain_list_lock);
728 kumaneko 111 #ifdef DEBUG_DOMAIN_UNDELETE
729 kumaneko 1052 printk(KERN_DEBUG "ccs_delete_domain %s\n", domainname);
730 kumaneko 2002 list1_for_each_entry(domain, &ccs_domain_list, list) {
731 kumaneko 1052 if (ccs_pathcmp(domain->domainname, &name))
732     continue;
733     printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted);
734 kumaneko 111 }
735     #endif
736     /* Is there an active domain? */
737 kumaneko 2002 list1_for_each_entry(domain, &ccs_domain_list, list) {
738 kumaneko 111 struct domain_info *domain2;
739 kumaneko 708 /* Never delete KERNEL_DOMAIN */
740 kumaneko 1052 if (domain == &KERNEL_DOMAIN)
741     continue;
742     if (domain->is_deleted ||
743     ccs_pathcmp(domain->domainname, &name))
744     continue;
745 kumaneko 111 /* Mark already deleted domains as non undeletable. */
746 kumaneko 2002 list1_for_each_entry(domain2, &ccs_domain_list, list) {
747 kumaneko 1052 if (!domain2->is_deleted ||
748     ccs_pathcmp(domain2->domainname, &name))
749     continue;
750 kumaneko 111 #ifdef DEBUG_DOMAIN_UNDELETE
751 kumaneko 1052 if (domain2->is_deleted != 255)
752     printk(KERN_DEBUG
753     "Marked %p as non undeletable\n",
754     domain2);
755 kumaneko 111 #endif
756     domain2->is_deleted = 255;
757     }
758     /* Delete and mark active domain as undeletable. */
759     domain->is_deleted = 1;
760     #ifdef DEBUG_DOMAIN_UNDELETE
761 kumaneko 1052 printk(KERN_DEBUG "Marked %p as undeletable\n", domain);
762 kumaneko 111 #endif
763 kumaneko 708 break;
764 kumaneko 111 }
765 kumaneko 2002 mutex_unlock(&ccs_domain_list_lock);
766 kumaneko 111 return 0;
767     }
768    
769 kumaneko 1052 /**
770     * ccs_undelete_domain - Undelete a domain.
771     *
772     * @domainname: The name of domain.
773     *
774     * Returns pointer to "struct domain_info" on success, NULL otherwise.
775     */
776     struct domain_info *ccs_undelete_domain(const char *domainname)
777 kumaneko 111 {
778 kumaneko 1064 struct domain_info *domain;
779     struct domain_info *candidate_domain = NULL;
780 kumaneko 2002 struct ccs_path_info name;
781 kumaneko 1052 name.name = domainname;
782     ccs_fill_path_info(&name);
783 kumaneko 2002 mutex_lock(&ccs_domain_list_lock);
784 kumaneko 111 #ifdef DEBUG_DOMAIN_UNDELETE
785 kumaneko 1052 printk(KERN_DEBUG "ccs_undelete_domain %s\n", domainname);
786 kumaneko 2002 list1_for_each_entry(domain, &ccs_domain_list, list) {
787 kumaneko 1052 if (ccs_pathcmp(domain->domainname, &name))
788     continue;
789     printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted);
790 kumaneko 111 }
791     #endif
792 kumaneko 2002 list1_for_each_entry(domain, &ccs_domain_list, list) {
793 kumaneko 1052 if (ccs_pathcmp(&name, domain->domainname))
794     continue;
795 kumaneko 111 if (!domain->is_deleted) {
796     /* This domain is active. I can't undelete. */
797     candidate_domain = NULL;
798     #ifdef DEBUG_DOMAIN_UNDELETE
799 kumaneko 1052 printk(KERN_DEBUG "%p is active. I can't undelete.\n",
800     domain);
801 kumaneko 111 #endif
802     break;
803     }
804     /* Is this domain undeletable? */
805 kumaneko 1052 if (domain->is_deleted == 1)
806     candidate_domain = domain;
807 kumaneko 111 }
808     if (candidate_domain) {
809     candidate_domain->is_deleted = 0;
810     #ifdef DEBUG_DOMAIN_UNDELETE
811 kumaneko 1052 printk(KERN_DEBUG "%p was undeleted.\n", candidate_domain);
812 kumaneko 111 #endif
813     }
814 kumaneko 2002 mutex_unlock(&ccs_domain_list_lock);
815 kumaneko 111 return candidate_domain;
816     }
817    
818 kumaneko 1052 /**
819     * ccs_find_or_assign_new_domain - Create a domain.
820     *
821     * @domainname: The name of domain.
822     * @profile: Profile number to assign if the domain was newly created.
823     *
824     * Returns pointer to "struct domain_info" on success, NULL otherwise.
825     */
826     struct domain_info *ccs_find_or_assign_new_domain(const char *domainname,
827     const u8 profile)
828 kumaneko 111 {
829     struct domain_info *domain = NULL;
830 kumaneko 2002 const struct ccs_path_info *saved_domainname;
831     mutex_lock(&ccs_domain_list_lock);
832 kumaneko 1052 domain = ccs_find_domain(domainname);
833     if (domain)
834     goto out;
835     if (!ccs_is_correct_domain(domainname, __func__))
836     goto out;
837     saved_domainname = ccs_save_name(domainname);
838     if (!saved_domainname)
839     goto out;
840 kumaneko 111 /* Can I reuse memory of deleted domain? */
841 kumaneko 2002 list1_for_each_entry(domain, &ccs_domain_list, list) {
842 kumaneko 111 struct task_struct *p;
843 kumaneko 2002 struct ccs_acl_info *ptr;
844 kumaneko 853 bool flag;
845 kumaneko 1052 if (!domain->is_deleted ||
846     domain->domainname != saved_domainname)
847     continue;
848 kumaneko 1016 flag = false;
849 kumaneko 111 /***** CRITICAL SECTION START *****/
850     read_lock(&tasklist_lock);
851     for_each_process(p) {
852 kumaneko 1064 if (p->domain_info != domain)
853     continue;
854     flag = true;
855     break;
856 kumaneko 111 }
857     read_unlock(&tasklist_lock);
858     /***** CRITICAL SECTION END *****/
859 kumaneko 1052 if (flag)
860     continue;
861 kumaneko 111 #ifdef DEBUG_DOMAIN_UNDELETE
862 kumaneko 1052 printk(KERN_DEBUG "Reusing %p %s\n", domain,
863     domain->domainname->name);
864 kumaneko 111 #endif
865 kumaneko 860 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
866 kumaneko 906 ptr->type |= ACL_DELETED;
867 kumaneko 860 }
868 kumaneko 1700 ccs_set_domain_flag(domain, true, domain->flags);
869 kumaneko 111 domain->profile = profile;
870 kumaneko 1016 domain->quota_warned = false;
871 kumaneko 708 mb(); /* Avoid out-of-order execution. */
872 kumaneko 111 domain->is_deleted = 0;
873     goto out;
874     }
875     /* No memory reusable. Create using new memory. */
876 kumaneko 1052 domain = ccs_alloc_element(sizeof(*domain));
877     if (domain) {
878 kumaneko 722 INIT_LIST1_HEAD(&domain->acl_info_list);
879 kumaneko 111 domain->domainname = saved_domainname;
880     domain->profile = profile;
881 kumaneko 2002 list1_add_tail_mb(&domain->list, &ccs_domain_list);
882 kumaneko 111 }
883 kumaneko 1052 out:
884 kumaneko 2002 mutex_unlock(&ccs_domain_list_lock);
885 kumaneko 111 return domain;
886     }
887    
888 kumaneko 1052 /**
889 kumaneko 2002 * ccs_get_argv0 - Get argv[0].
890 kumaneko 1052 *
891     * @bprm: Pointer to "struct linux_binprm".
892 kumaneko 1793 * @tmp: Buffer for temporary use.
893 kumaneko 1052 *
894     * Returns true on success, false otherwise.
895     */
896 kumaneko 2002 static bool ccs_get_argv0(struct linux_binprm *bprm,
897     struct ccs_page_buffer *tmp)
898 kumaneko 111 {
899 kumaneko 1031 char *arg_ptr = tmp->buffer;
900 kumaneko 316 int arg_len = 0;
901     unsigned long pos = bprm->p;
902 kumaneko 1052 int offset = pos % PAGE_SIZE;
903 kumaneko 1031 bool done = false;
904 kumaneko 1052 if (!bprm->argc)
905     goto out;
906 kumaneko 316 while (1) {
907 kumaneko 2020 struct page *page = ccs_get_arg_page(bprm, pos);
908 kumaneko 1031 const char *kaddr;
909 kumaneko 2020 if (!page)
910 kumaneko 1052 goto out;
911 kumaneko 1031 pos += PAGE_SIZE - offset;
912     /* Map. */
913     kaddr = kmap(page);
914     /* Read. */
915     while (offset < PAGE_SIZE) {
916     const unsigned char c = kaddr[offset++];
917     if (c && arg_len < CCS_MAX_PATHNAME_LEN - 10) {
918     if (c == '\\') {
919     arg_ptr[arg_len++] = '\\';
920     arg_ptr[arg_len++] = '\\';
921     } else if (c == '/') {
922     arg_len = 0;
923     } else if (c > ' ' && c < 127) {
924     arg_ptr[arg_len++] = c;
925     } else {
926     arg_ptr[arg_len++] = '\\';
927     arg_ptr[arg_len++] = (c >> 6) + '0';
928 kumaneko 1052 arg_ptr[arg_len++]
929     = ((c >> 3) & 7) + '0';
930 kumaneko 1031 arg_ptr[arg_len++] = (c & 7) + '0';
931     }
932     } else {
933     arg_ptr[arg_len] = '\0';
934     done = true;
935     break;
936 kumaneko 316 }
937 kumaneko 115 }
938 kumaneko 1031 /* Unmap. */
939     kunmap(page);
940 kumaneko 2020 ccs_put_arg_page(page);
941 kumaneko 316 offset = 0;
942 kumaneko 1052 if (done)
943     break;
944 kumaneko 115 }
945 kumaneko 1031 return true;
946     out:
947     return false;
948 kumaneko 115 }
949    
950 kumaneko 1052 /**
951 kumaneko 2002 * ccs_find_next_domain - Find a domain.
952 kumaneko 1052 *
953 kumaneko 1657 * @r: Pointer to "struct ccs_request_info".
954     * @handler: Pathname to verify. May be NULL.
955 kumaneko 1052 *
956     * Returns 0 on success, negative value otherwise.
957     */
958 kumaneko 2002 static int ccs_find_next_domain(struct ccs_request_info *r,
959     const struct ccs_path_info *handler)
960 kumaneko 115 {
961 kumaneko 1052 /*
962     * This function assumes that the size of buffer returned by
963     * ccs_realpath() = CCS_MAX_PATHNAME_LEN.
964     */
965     struct domain_info *domain = NULL;
966 kumaneko 1657 const char *old_domain_name = r->domain->domainname->name;
967     struct linux_binprm *bprm = r->bprm;
968     struct ccs_page_buffer *tmp = r->obj->tmp;
969 kumaneko 115 const char *original_name = bprm->filename;
970 kumaneko 1657 const u8 mode = r->mode;
971     const bool is_enforce = (mode == 3);
972 kumaneko 1782 const u32 tomoyo_flags = current->tomoyo_flags;
973 kumaneko 111 char *new_domain_name = NULL;
974 kumaneko 1052 char *real_program_name = NULL;
975     char *symlink_program_name = NULL;
976 kumaneko 2002 struct ccs_path_info rn; /* real name */
977     struct ccs_path_info sn; /* symlink name */
978     struct ccs_path_info ln; /* last name */
979 kumaneko 111 int retval;
980    
981     {
982     /*
983 kumaneko 1052 * Built-in initializers. This is needed because policies are
984 kumaneko 1064 * not loaded until starting /sbin/init.
985 kumaneko 111 */
986 kumaneko 1016 static bool first = true;
987 kumaneko 111 if (first) {
988 kumaneko 2002 ccs_update_domain_initializer_entry(NULL,
989     "/sbin/hotplug",
990     false, false);
991     ccs_update_domain_initializer_entry(NULL,
992     "/sbin/modprobe",
993     false, false);
994 kumaneko 1016 first = false;
995 kumaneko 111 }
996     }
997    
998 kumaneko 1561 retry:
999     current->tomoyo_flags = tomoyo_flags;
1000 kumaneko 1782 r->cond = NULL;
1001 kumaneko 1052 /* Get ccs_realpath of program. */
1002     retval = -ENOENT; /* I hope ccs_realpath() won't fail with -ENOMEM. */
1003 kumaneko 1561 ccs_free(real_program_name);
1004 kumaneko 1052 real_program_name = ccs_realpath(original_name);
1005     if (!real_program_name)
1006     goto out;
1007     /* Get ccs_realpath of symbolic link. */
1008 kumaneko 1561 ccs_free(symlink_program_name);
1009 kumaneko 1052 symlink_program_name = ccs_realpath_nofollow(original_name);
1010     if (!symlink_program_name)
1011     goto out;
1012 kumaneko 111
1013 kumaneko 1657 rn.name = real_program_name;
1014     ccs_fill_path_info(&rn);
1015     sn.name = symlink_program_name;
1016     ccs_fill_path_info(&sn);
1017     ln.name = ccs_get_last_name(r->domain);
1018     ccs_fill_path_info(&ln);
1019 kumaneko 111
1020 kumaneko 1657 if (handler) {
1021     if (ccs_pathcmp(&rn, handler)) {
1022 kumaneko 1064 /* Failed to verify execute handler. */
1023 kumaneko 1029 static u8 counter = 20;
1024     if (counter) {
1025     counter--;
1026 kumaneko 1052 printk(KERN_WARNING "Failed to verify: %s\n",
1027 kumaneko 1657 handler->name);
1028 kumaneko 1029 }
1029     goto out;
1030     }
1031 kumaneko 1052 goto calculate_domain;
1032 kumaneko 1029 }
1033 kumaneko 708
1034 kumaneko 111 /* Check 'alias' directive. */
1035 kumaneko 1657 if (ccs_pathcmp(&rn, &sn)) {
1036 kumaneko 2002 struct ccs_alias_entry *ptr;
1037 kumaneko 111 /* Is this program allowed to be called via symbolic links? */
1038 kumaneko 2002 list1_for_each_entry(ptr, &ccs_alias_list, list) {
1039 kumaneko 1052 if (ptr->is_deleted ||
1040 kumaneko 1657 ccs_pathcmp(&rn, ptr->original_name) ||
1041     ccs_pathcmp(&sn, ptr->aliased_name))
1042 kumaneko 1052 continue;
1043 kumaneko 111 memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);
1044 kumaneko 1052 strncpy(real_program_name, ptr->aliased_name->name,
1045     CCS_MAX_PATHNAME_LEN - 1);
1046 kumaneko 1657 ccs_fill_path_info(&rn);
1047 kumaneko 111 break;
1048     }
1049     }
1050 kumaneko 1032
1051 kumaneko 183 /* Compare basename of real_program_name and argv[0] */
1052 kumaneko 1657 r->mode = ccs_check_flags(r->domain, CCS_TOMOYO_MAC_FOR_ARGV0);
1053     if (bprm->argc > 0 && r->mode) {
1054 kumaneko 1031 char *base_argv0 = tmp->buffer;
1055     const char *base_filename;
1056 kumaneko 115 retval = -ENOMEM;
1057 kumaneko 2002 if (!ccs_get_argv0(bprm, tmp))
1058 kumaneko 1052 goto out;
1059     base_filename = strrchr(real_program_name, '/');
1060     if (!base_filename)
1061     base_filename = real_program_name;
1062     else
1063     base_filename++;
1064 kumaneko 1031 if (strcmp(base_argv0, base_filename)) {
1065 kumaneko 1657 retval = ccs_check_argv0_perm(r, &rn, base_argv0);
1066 kumaneko 1781 if (retval == 1)
1067 kumaneko 1561 goto retry;
1068     if (retval < 0)
1069 kumaneko 1052 goto out;
1070 kumaneko 111 }
1071     }
1072 kumaneko 1032
1073 kumaneko 183 /* Check 'aggregator' directive. */
1074     {
1075 kumaneko 2002 struct ccs_aggregator_entry *ptr;
1076 kumaneko 183 /* Is this program allowed to be aggregated? */
1077 kumaneko 2002 list1_for_each_entry(ptr, &ccs_aggregator_list, list) {
1078 kumaneko 1052 if (ptr->is_deleted ||
1079 kumaneko 1657 !ccs_path_matches_pattern(&rn, ptr->original_name))
1080 kumaneko 1052 continue;
1081 kumaneko 183 memset(real_program_name, 0, CCS_MAX_PATHNAME_LEN);
1082 kumaneko 1052 strncpy(real_program_name, ptr->aggregated_name->name,
1083     CCS_MAX_PATHNAME_LEN - 1);
1084 kumaneko 1657 ccs_fill_path_info(&rn);
1085 kumaneko 183 break;
1086     }
1087     }
1088    
1089 kumaneko 111 /* Check execute permission. */
1090 kumaneko 1657 r->mode = mode;
1091     retval = ccs_check_exec_perm(r, &rn);
1092 kumaneko 1781 if (retval == 1)
1093 kumaneko 1561 goto retry;
1094 kumaneko 1052 if (retval < 0)
1095     goto out;
1096 kumaneko 111
1097 kumaneko 1052 calculate_domain:
1098 kumaneko 1031 new_domain_name = tmp->buffer;
1099 kumaneko 2002 if (ccs_is_domain_initializer(r->domain->domainname, &rn, &ln)) {
1100 kumaneko 111 /* Transit to the child of KERNEL_DOMAIN domain. */
1101 kumaneko 1052 snprintf(new_domain_name, CCS_MAX_PATHNAME_LEN + 1,
1102     ROOT_NAME " " "%s", real_program_name);
1103 kumaneko 2002 } else if (r->domain == &KERNEL_DOMAIN && !ccs_sbin_init_started) {
1104 kumaneko 111 /*
1105 kumaneko 1052 * Needn't to transit from kernel domain before starting
1106 kumaneko 1064 * /sbin/init. But transit from kernel domain if executing
1107     * initializers because they might start before /sbin/init.
1108 kumaneko 111 */
1109 kumaneko 1657 domain = r->domain;
1110 kumaneko 2002 } else if (ccs_is_domain_keeper(r->domain->domainname, &rn, &ln)) {
1111 kumaneko 111 /* Keep current domain. */
1112 kumaneko 1657 domain = r->domain;
1113 kumaneko 111 } else {
1114     /* Normal domain transition. */
1115 kumaneko 1052 snprintf(new_domain_name, CCS_MAX_PATHNAME_LEN + 1,
1116     "%s %s", old_domain_name, real_program_name);
1117 kumaneko 111 }
1118 kumaneko 1052 if (domain || strlen(new_domain_name) >= CCS_MAX_PATHNAME_LEN)
1119     goto done;
1120     domain = ccs_find_domain(new_domain_name);
1121     if (domain)
1122     goto done;
1123 kumaneko 1561 if (is_enforce) {
1124 kumaneko 1657 int error = ccs_check_supervisor(r,
1125 kumaneko 1561 "# wants to create domain\n"
1126     "%s\n", new_domain_name);
1127 kumaneko 1781 if (error == 1)
1128 kumaneko 1561 goto retry;
1129     if (error < 0)
1130 kumaneko 1052 goto done;
1131 kumaneko 1561 }
1132 kumaneko 1657 domain = ccs_find_or_assign_new_domain(new_domain_name, r->profile);
1133 kumaneko 1052 if (domain)
1134 kumaneko 2002 ccs_audit_domain_creation_log(domain);
1135 kumaneko 1052 done:
1136 kumaneko 111 if (!domain) {
1137 kumaneko 1052 printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
1138     new_domain_name);
1139     if (is_enforce)
1140     retval = -EPERM;
1141 kumaneko 1561 else {
1142     retval = 0;
1143 kumaneko 1657 ccs_set_domain_flag(r->domain, false,
1144 kumaneko 1180 DOMAIN_FLAGS_TRANSITION_FAILED);
1145 kumaneko 1561 }
1146 kumaneko 111 } else {
1147     retval = 0;
1148     }
1149 kumaneko 1052 out:
1150 kumaneko 111 ccs_free(real_program_name);
1151     ccs_free(symlink_program_name);
1152 kumaneko 1657 if (domain)
1153     r->domain = domain;
1154 kumaneko 111 return retval;
1155     }
1156    
1157 kumaneko 1052 /**
1158 kumaneko 2002 * ccs_check_environ - Check permission for environment variable names.
1159 kumaneko 1052 *
1160 kumaneko 1657 * @r: Pointer to "struct ccs_request_info".
1161 kumaneko 1052 *
1162     * Returns 0 on success, negative value otherwise.
1163     */
1164 kumaneko 2002 static int ccs_check_environ(struct ccs_request_info *r)
1165 kumaneko 581 {
1166 kumaneko 1657 struct linux_binprm *bprm = r->bprm;
1167     struct ccs_page_buffer *tmp = r->obj->tmp;
1168 kumaneko 1031 char *arg_ptr = tmp->buffer;
1169 kumaneko 581 int arg_len = 0;
1170     unsigned long pos = bprm->p;
1171 kumaneko 1064 int offset = pos % PAGE_SIZE;
1172 kumaneko 581 int argv_count = bprm->argc;
1173     int envp_count = bprm->envc;
1174 kumaneko 1052 /* printk(KERN_DEBUG "start %d %d\n", argv_count, envp_count); */
1175 kumaneko 581 int error = -ENOMEM;
1176 kumaneko 1657 if (!r->mode || !envp_count)
1177 kumaneko 1052 return 0;
1178 kumaneko 581 while (error == -ENOMEM) {
1179 kumaneko 2020 struct page *page = ccs_get_arg_page(bprm, pos);
1180 kumaneko 581 const char *kaddr;
1181 kumaneko 2020 if (!page)
1182 kumaneko 1052 goto out;
1183 kumaneko 986 pos += PAGE_SIZE - offset;
1184 kumaneko 1031 /* Map. */
1185 kumaneko 581 kaddr = kmap(page);
1186     /* Read. */
1187     while (argv_count && offset < PAGE_SIZE) {
1188 kumaneko 1052 if (!kaddr[offset++])
1189     argv_count--;
1190 kumaneko 581 }
1191 kumaneko 1052 if (argv_count)
1192     goto unmap_page;
1193 kumaneko 581 while (offset < PAGE_SIZE) {
1194     const unsigned char c = kaddr[offset++];
1195 kumaneko 652 if (c && arg_len < CCS_MAX_PATHNAME_LEN - 10) {
1196 kumaneko 581 if (c == '=') {
1197     arg_ptr[arg_len++] = '\0';
1198     } else if (c == '\\') {
1199     arg_ptr[arg_len++] = '\\';
1200     arg_ptr[arg_len++] = '\\';
1201     } else if (c > ' ' && c < 127) {
1202     arg_ptr[arg_len++] = c;
1203     } else {
1204     arg_ptr[arg_len++] = '\\';
1205     arg_ptr[arg_len++] = (c >> 6) + '0';
1206 kumaneko 1052 arg_ptr[arg_len++]
1207     = ((c >> 3) & 7) + '0';
1208 kumaneko 581 arg_ptr[arg_len++] = (c & 7) + '0';
1209     }
1210     } else {
1211     arg_ptr[arg_len] = '\0';
1212     }
1213 kumaneko 1052 if (c)
1214     continue;
1215 kumaneko 1657 if (ccs_check_env_perm(r, arg_ptr)) {
1216 kumaneko 581 error = -EPERM;
1217     break;
1218     }
1219     if (!--envp_count) {
1220     error = 0;
1221     break;
1222     }
1223     arg_len = 0;
1224     }
1225 kumaneko 2002 unmap_page:
1226 kumaneko 581 /* Unmap. */
1227     kunmap(page);
1228 kumaneko 2020 ccs_put_arg_page(page);
1229 kumaneko 581 offset = 0;
1230     }
1231     out:
1232 kumaneko 1657 if (r->mode != 3)
1233 kumaneko 1052 error = 0;
1234 kumaneko 581 return error;
1235     }
1236 kumaneko 111
1237 kumaneko 1052 /**
1238 kumaneko 2002 * ccs_unescape - Unescape escaped string.
1239 kumaneko 1052 *
1240 kumaneko 2002 * @dest: String to ccs_unescape.
1241 kumaneko 1052 *
1242     * Returns nothing.
1243     */
1244 kumaneko 2002 static void ccs_unescape(unsigned char *dest)
1245 kumaneko 708 {
1246     unsigned char *src = dest;
1247 kumaneko 1064 unsigned char c;
1248     unsigned char d;
1249     unsigned char e;
1250 kumaneko 1747 while (1) {
1251     c = *src++;
1252     if (!c)
1253     break;
1254 kumaneko 708 if (c != '\\') {
1255     *dest++ = c;
1256     continue;
1257     }
1258     c = *src++;
1259     if (c == '\\') {
1260     *dest++ = c;
1261 kumaneko 1052 continue;
1262     }
1263     if (c < '0' || c > '3')
1264 kumaneko 708 break;
1265 kumaneko 1052 d = *src++;
1266     if (d < '0' || d > '7')
1267     break;
1268     e = *src++;
1269     if (e < '0' || e > '7')
1270     break;
1271     *dest++ = ((c - '0') << 6) + ((d - '0') << 3) + (e - '0');
1272 kumaneko 708 }
1273     *dest = '\0';
1274     }
1275    
1276 kumaneko 1052 /**
1277 kumaneko 2002 * ccs_root_depth - Get number of directories to strip.
1278 kumaneko 1052 *
1279     * @dentry: Pointer to "struct dentry".
1280     * @vfsmnt: Pointer to "struct vfsmount".
1281     *
1282     * Returns number of directories to strip.
1283 kumaneko 1029 */
1284 kumaneko 2002 static inline int ccs_root_depth(struct dentry *dentry, struct vfsmount *vfsmnt)
1285 kumaneko 708 {
1286 kumaneko 1029 int depth = 0;
1287     /***** CRITICAL SECTION START *****/
1288 kumaneko 1474 ccs_realpath_lock();
1289 kumaneko 1029 for (;;) {
1290     if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
1291     /* Global root? */
1292 kumaneko 1052 if (vfsmnt->mnt_parent == vfsmnt)
1293     break;
1294 kumaneko 1029 dentry = vfsmnt->mnt_mountpoint;
1295     vfsmnt = vfsmnt->mnt_parent;
1296     continue;
1297     }
1298     dentry = dentry->d_parent;
1299     depth++;
1300     }
1301 kumaneko 1474 ccs_realpath_unlock();
1302 kumaneko 1029 /***** CRITICAL SECTION END *****/
1303 kumaneko 1052 return depth;
1304     }
1305    
1306     /**
1307 kumaneko 2002 * ccs_get_root_depth - return the depth of root directory.
1308 kumaneko 1052 *
1309     * Returns number of directories to strip.
1310     */
1311 kumaneko 2002 static int ccs_get_root_depth(void)
1312 kumaneko 1052 {
1313     int depth;
1314     struct dentry *dentry;
1315     struct vfsmount *vfsmnt;
1316     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1317     struct path root;
1318     #endif
1319     /***** CRITICAL SECTION START *****/
1320     read_lock(&current->fs->lock);
1321     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1322     root = current->fs->root;
1323     path_get(&current->fs->root);
1324     dentry = root.dentry;
1325     vfsmnt = root.mnt;
1326     #else
1327     dentry = dget(current->fs->root);
1328     vfsmnt = mntget(current->fs->rootmnt);
1329     #endif
1330     read_unlock(&current->fs->lock);
1331     /***** CRITICAL SECTION END *****/
1332 kumaneko 2002 depth = ccs_root_depth(dentry, vfsmnt);
1333 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1334 kumaneko 1029 path_put(&root);
1335     #else
1336 kumaneko 1052 dput(dentry);
1337     mntput(vfsmnt);
1338 kumaneko 1029 #endif
1339     return depth;
1340     }
1341    
1342 kumaneko 1052 /**
1343 kumaneko 2002 * ccs_try_alt_exec - Try to start execute handler.
1344 kumaneko 1052 *
1345 kumaneko 1657 * @r: Pointer to "struct ccs_request_info".
1346 kumaneko 1319 * @handler: Pointer to the name of execute handler.
1347 kumaneko 1317 * @eh_path: Pointer to pointer to the name of execute handler.
1348 kumaneko 1052 *
1349     * Returns 0 on success, negative value otherwise.
1350     */
1351 kumaneko 2002 static int ccs_try_alt_exec(struct ccs_request_info *r,
1352     const struct ccs_path_info *handler, char **eh_path)
1353 kumaneko 1029 {
1354 kumaneko 1005 /*
1355     * Contents of modified bprm.
1356     * The envp[] in original bprm is moved to argv[] so that
1357     * the alternatively executed program won't be affected by
1358 kumaneko 1064 * some dangerous environment variables like LD_PRELOAD.
1359 kumaneko 1005 *
1360     * modified bprm->argc
1361     * = original bprm->argc + original bprm->envc + 7
1362     * modified bprm->envc
1363     * = 0
1364     *
1365     * modified bprm->argv[0]
1366 kumaneko 1029 * = the program's name specified by execute_handler
1367 kumaneko 1005 * modified bprm->argv[1]
1368     * = current->domain_info->domainname->name
1369     * modified bprm->argv[2]
1370     * = the current process's name
1371     * modified bprm->argv[3]
1372     * = the current process's information (e.g. uid/gid).
1373     * modified bprm->argv[4]
1374     * = original bprm->filename
1375     * modified bprm->argv[5]
1376     * = original bprm->argc in string expression
1377     * modified bprm->argv[6]
1378     * = original bprm->envc in string expression
1379     * modified bprm->argv[7]
1380     * = original bprm->argv[0]
1381     * ...
1382     * modified bprm->argv[bprm->argc + 6]
1383     * = original bprm->argv[bprm->argc - 1]
1384     * modified bprm->argv[bprm->argc + 7]
1385     * = original bprm->envp[0]
1386     * ...
1387     * modified bprm->argv[bprm->envc + bprm->argc + 6]
1388     * = original bprm->envp[bprm->envc - 1]
1389     */
1390 kumaneko 1657 struct linux_binprm *bprm = r->bprm;
1391 kumaneko 708 struct file *filp;
1392     int retval;
1393 kumaneko 1005 const int original_argc = bprm->argc;
1394     const int original_envc = bprm->envc;
1395     struct task_struct *task = current;
1396 kumaneko 1657 char *buffer = r->obj->tmp->buffer;
1397 kumaneko 1031 /* Allocate memory for execute handler's pathname. */
1398 kumaneko 1903 char *execute_handler = ccs_alloc(sizeof(struct ccs_page_buffer),
1399     false);
1400 kumaneko 1317 *eh_path = execute_handler;
1401 kumaneko 1052 if (!execute_handler)
1402     return -ENOMEM;
1403 kumaneko 1319 strncpy(execute_handler, handler->name,
1404 kumaneko 1052 sizeof(struct ccs_page_buffer) - 1);
1405 kumaneko 2002 ccs_unescape(execute_handler);
1406 kumaneko 1032
1407 kumaneko 1029 /* Close the requested program's dentry. */
1408 kumaneko 708 allow_write_access(bprm->file);
1409     fput(bprm->file);
1410     bprm->file = NULL;
1411 kumaneko 1005
1412 kumaneko 1031 { /* Adjust root directory for open_exec(). */
1413 kumaneko 2002 int depth = ccs_get_root_depth();
1414 kumaneko 1029 char *cp = execute_handler;
1415 kumaneko 1052 if (!*cp || *cp != '/')
1416     return -ENOENT;
1417 kumaneko 1029 while (depth) {
1418     cp = strchr(cp + 1, '/');
1419 kumaneko 1052 if (!cp)
1420     return -ENOENT;
1421 kumaneko 1029 depth--;
1422     }
1423     memmove(execute_handler, cp, strlen(cp) + 1);
1424     }
1425    
1426 kumaneko 1005 /* Move envp[] to argv[] */
1427     bprm->argc += bprm->envc;
1428     bprm->envc = 0;
1429    
1430     /* Set argv[6] */
1431     {
1432 kumaneko 1052 snprintf(buffer, sizeof(struct ccs_page_buffer) - 1, "%d",
1433     original_envc);
1434 kumaneko 1005 retval = copy_strings_kernel(1, &buffer, bprm);
1435 kumaneko 1052 if (retval < 0)
1436     goto out;
1437 kumaneko 1005 bprm->argc++;
1438     }
1439    
1440     /* Set argv[5] */
1441     {
1442 kumaneko 1052 snprintf(buffer, sizeof(struct ccs_page_buffer) - 1, "%d",
1443     original_argc);
1444 kumaneko 1005 retval = copy_strings_kernel(1, &buffer, bprm);
1445 kumaneko 1052 if (retval < 0)
1446     goto out;
1447 kumaneko 1005 bprm->argc++;
1448     }
1449    
1450     /* Set argv[4] */
1451     {
1452     retval = copy_strings_kernel(1, &bprm->filename, bprm);
1453 kumaneko 1052 if (retval < 0)
1454     goto out;
1455 kumaneko 1005 bprm->argc++;
1456     }
1457    
1458     /* Set argv[3] */
1459     {
1460     const u32 tomoyo_flags = task->tomoyo_flags;
1461 kumaneko 1052 snprintf(buffer, sizeof(struct ccs_page_buffer) - 1,
1462     "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "
1463     "sgid=%d fsuid=%d fsgid=%d state[0]=%u "
1464     "state[1]=%u state[2]=%u",
1465 kumaneko 2016 (pid_t) sys_getpid(), current_uid(), current_gid(),
1466     current_euid(), current_egid(), current_suid(),
1467     current_sgid(), current_fsuid(), current_fsgid(),
1468     (u8) (tomoyo_flags >> 24), (u8) (tomoyo_flags >> 16),
1469     (u8) (tomoyo_flags >> 8));
1470 kumaneko 1005 retval = copy_strings_kernel(1, &buffer, bprm);
1471 kumaneko 1052 if (retval < 0)
1472     goto out;
1473 kumaneko 1005 bprm->argc++;
1474     }
1475    
1476     /* Set argv[2] */
1477     {
1478 kumaneko 1052 char *exe = (char *) ccs_get_exe();
1479 kumaneko 1005 if (exe) {
1480     retval = copy_strings_kernel(1, &exe, bprm);
1481     ccs_free(exe);
1482     } else {
1483 kumaneko 1052 snprintf(buffer, sizeof(struct ccs_page_buffer) - 1,
1484     "<unknown>");
1485 kumaneko 1005 retval = copy_strings_kernel(1, &buffer, bprm);
1486     }
1487 kumaneko 1052 if (retval < 0)
1488     goto out;
1489 kumaneko 1005 bprm->argc++;
1490     }
1491    
1492     /* Set argv[1] */
1493     {
1494 kumaneko 1052 strncpy(buffer, task->domain_info->domainname->name,
1495     sizeof(struct ccs_page_buffer) - 1);
1496 kumaneko 1005 retval = copy_strings_kernel(1, &buffer, bprm);
1497 kumaneko 1052 if (retval < 0)
1498     goto out;
1499 kumaneko 1005 bprm->argc++;
1500     }
1501    
1502     /* Set argv[0] */
1503     {
1504 kumaneko 1029 retval = copy_strings_kernel(1, &execute_handler, bprm);
1505 kumaneko 1052 if (retval < 0)
1506     goto out;
1507 kumaneko 1005 bprm->argc++;
1508     }
1509 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
1510     #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
1511 kumaneko 1007 bprm->argv_len = bprm->exec - bprm->p;
1512     #endif
1513 kumaneko 1052 #endif
1514 kumaneko 1005
1515 kumaneko 1029 /* OK, now restart the process with execute handler program's dentry. */
1516     filp = open_exec(execute_handler);
1517 kumaneko 1005 if (IS_ERR(filp)) {
1518     retval = PTR_ERR(filp);
1519     goto out;
1520     }
1521 kumaneko 1052 bprm->file = filp;
1522 kumaneko 1029 bprm->filename = execute_handler;
1523 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
1524 kumaneko 1029 bprm->interp = execute_handler;
1525 kumaneko 708 #endif
1526 kumaneko 1029 retval = prepare_binprm(bprm);
1527 kumaneko 1052 if (retval < 0)
1528     goto out;
1529 kumaneko 1029 task->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1530 kumaneko 2002 retval = ccs_find_next_domain(r, handler);
1531 kumaneko 1029 task->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1532 kumaneko 1005 out:
1533     return retval;
1534 kumaneko 708 }
1535 kumaneko 581
1536 kumaneko 1052 /**
1537 kumaneko 2002 * ccs_find_execute_handler - Find an execute handler.
1538 kumaneko 1052 *
1539     * @type: Type of execute handler.
1540     *
1541 kumaneko 2002 * Returns pointer to "struct ccs_path_info" if found, NULL otherwise.
1542 kumaneko 1052 */
1543 kumaneko 2002 static const struct ccs_path_info *ccs_find_execute_handler(const u8 type)
1544 kumaneko 1029 {
1545 kumaneko 1064 struct task_struct *task = current;
1546     const struct domain_info *domain = task->domain_info;
1547 kumaneko 2002 struct ccs_acl_info *ptr;
1548 kumaneko 1064 /*
1549     * Don't use execute handler if the current process is
1550     * marked as execute handler to avoid infinite execute handler loop.
1551     */
1552     if (task->tomoyo_flags & TOMOYO_TASK_IS_EXECUTE_HANDLER)
1553     return NULL;
1554 kumaneko 1029 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
1555 kumaneko 2002 struct ccs_execute_handler_record *acl;
1556 kumaneko 1058 if (ptr->type != type)
1557 kumaneko 1052 continue;
1558 kumaneko 2002 acl = container_of(ptr, struct ccs_execute_handler_record,
1559     head);
1560 kumaneko 1029 return acl->handler;
1561     }
1562     return NULL;
1563     }
1564    
1565 kumaneko 1657 /* List of next_domain which is used for checking interpreter's permissions. */
1566 kumaneko 2002 struct ccs_execve_entry {
1567 kumaneko 1657 struct list_head list;
1568     struct task_struct *task;
1569     struct domain_info *next_domain;
1570     };
1571    
1572 kumaneko 2002 static LIST_HEAD(ccs_execve_list);
1573     static DEFINE_SPINLOCK(ccs_execve_list_lock);
1574 kumaneko 1657
1575 kumaneko 1052 /**
1576 kumaneko 1657 * ccs_register_next_domain - Remember next_domain.
1577     *
1578     * @next_domain: Pointer to "struct domain_info".
1579     *
1580     * Returns 0 on success, -ENOMEM otherwise.
1581     */
1582     static int ccs_register_next_domain(struct domain_info *next_domain)
1583     {
1584 kumaneko 2002 struct ccs_execve_entry *ee = kmalloc(sizeof(*ee), GFP_KERNEL);
1585 kumaneko 1657 if (!ee)
1586     return -ENOMEM;
1587     ee->task = current;
1588     ee->next_domain = next_domain;
1589     /***** CRITICAL SECTION START *****/
1590 kumaneko 2002 spin_lock(&ccs_execve_list_lock);
1591     list_add(&ee->list, &ccs_execve_list);
1592     spin_unlock(&ccs_execve_list_lock);
1593 kumaneko 1657 /***** CRITICAL SECTION END *****/
1594     return 0;
1595     }
1596    
1597     /**
1598     * ccs_fetch_next_domain - Fetch next_domain from the list.
1599     *
1600     * Returns pointer to "struct domain_info" which will be used if execve()
1601     * succeeds. This function does not return NULL.
1602     */
1603     struct domain_info *ccs_fetch_next_domain(void)
1604     {
1605     struct task_struct *task = current;
1606     struct domain_info *next_domain = task->domain_info;
1607 kumaneko 2002 struct ccs_execve_entry *p;
1608 kumaneko 1657 /***** CRITICAL SECTION START *****/
1609 kumaneko 2002 spin_lock(&ccs_execve_list_lock);
1610     list_for_each_entry(p, &ccs_execve_list, list) {
1611 kumaneko 1657 if (p->task != task)
1612     continue;
1613     next_domain = p->next_domain;
1614     break;
1615     }
1616 kumaneko 2002 spin_unlock(&ccs_execve_list_lock);
1617 kumaneko 1657 /***** CRITICAL SECTION END *****/
1618     return next_domain;
1619     }
1620    
1621     /**
1622     * ccs_unregister_next_domain - Forget next_domain.
1623     */
1624     static void ccs_unregister_next_domain(void)
1625     {
1626     struct task_struct *task = current;
1627 kumaneko 2002 struct ccs_execve_entry *p;
1628     struct ccs_execve_entry *ee = NULL;
1629 kumaneko 1657 /***** CRITICAL SECTION START *****/
1630 kumaneko 2002 spin_lock(&ccs_execve_list_lock);
1631     list_for_each_entry(p, &ccs_execve_list, list) {
1632 kumaneko 1657 if (p->task != task)
1633     continue;
1634     list_del(&p->list);
1635     ee = p;
1636     break;
1637     }
1638 kumaneko 2002 spin_unlock(&ccs_execve_list_lock);
1639 kumaneko 1657 /***** CRITICAL SECTION END *****/
1640     kfree(ee);
1641     }
1642    
1643     /**
1644 kumaneko 1052 * search_binary_handler_with_transition - Perform domain transition.
1645     *
1646     * @bprm: Pointer to "struct linux_binprm".
1647     * @regs: Pointer to "struct pt_regs".
1648     *
1649     * Returns result of search_binary_handler() on success,
1650     * negative value otherwise.
1651     */
1652     int search_binary_handler_with_transition(struct linux_binprm *bprm,
1653     struct pt_regs *regs)
1654 kumaneko 115 {
1655 kumaneko 1657 int retval;
1656 kumaneko 1029 struct task_struct *task = current;
1657 kumaneko 2002 const struct ccs_path_info *handler;
1658 kumaneko 1657 struct ccs_request_info r;
1659 kumaneko 2002 struct ccs_obj_info obj;
1660 kumaneko 1052 /*
1661 kumaneko 1317 * "eh_path" holds path to execute handler program.
1662 kumaneko 1052 * Thus, keep valid until search_binary_handler() finishes.
1663     */
1664 kumaneko 1317 char *eh_path = NULL;
1665 kumaneko 1903 struct ccs_page_buffer *tmp = ccs_alloc(sizeof(struct ccs_page_buffer),
1666     false);
1667 kumaneko 1657 memset(&obj, 0, sizeof(obj));
1668 kumaneko 2002 if (!ccs_sbin_init_started)
1669 kumaneko 1657 ccs_load_policy(bprm->filename);
1670 kumaneko 1317 if (!tmp)
1671 kumaneko 1052 return -ENOMEM;
1672 kumaneko 1657
1673     ccs_init_request_info(&r, NULL, CCS_TOMOYO_MAC_FOR_FILE);
1674     r.bprm = bprm;
1675     r.obj = &obj;
1676     obj.path1_dentry = bprm->file->f_dentry;
1677     obj.path1_vfsmnt = bprm->file->f_vfsmnt;
1678     obj.tmp = tmp;
1679    
1680 kumaneko 1578 /* Clear manager flag. */
1681     task->tomoyo_flags &= ~CCS_TASK_IS_POLICY_MANAGER;
1682 kumaneko 2002 handler = ccs_find_execute_handler(TYPE_EXECUTE_HANDLER);
1683 kumaneko 1029 if (handler) {
1684 kumaneko 2002 retval = ccs_try_alt_exec(&r, handler, &eh_path);
1685 kumaneko 1052 if (!retval)
1686 kumaneko 2002 ccs_audit_execute_handler_log(true, handler->name,
1687     bprm);
1688 kumaneko 1052 goto ok;
1689 kumaneko 708 }
1690 kumaneko 2002 retval = ccs_find_next_domain(&r, NULL);
1691 kumaneko 1052 if (retval != -EPERM)
1692     goto ok;
1693 kumaneko 2002 handler = ccs_find_execute_handler(TYPE_DENIED_EXECUTE_HANDLER);
1694 kumaneko 1052 if (handler) {
1695 kumaneko 2002 retval = ccs_try_alt_exec(&r, handler, &eh_path);
1696 kumaneko 1052 if (!retval)
1697 kumaneko 2002 ccs_audit_execute_handler_log(false, handler->name,
1698     bprm);
1699 kumaneko 1052 }
1700     ok:
1701 kumaneko 1561 if (retval < 0)
1702 kumaneko 1052 goto out;
1703 kumaneko 1657 r.mode = ccs_check_flags(r.domain, CCS_TOMOYO_MAC_FOR_ENV);
1704 kumaneko 2002 retval = ccs_check_environ(&r);
1705 kumaneko 1561 if (retval < 0)
1706 kumaneko 1052 goto out;
1707 kumaneko 1657 retval = ccs_register_next_domain(r.domain);
1708     if (retval < 0)
1709     goto out;
1710 kumaneko 1029 task->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC;
1711     retval = search_binary_handler(bprm, regs);
1712     task->tomoyo_flags &= ~TOMOYO_CHECK_READ_FOR_OPEN_EXEC;
1713 kumaneko 1052 if (retval < 0)
1714 kumaneko 1657 goto out;
1715     /* Proceed to next domain if execution suceeded. */
1716     task->domain_info = r.domain;
1717     mb(); /* Make domain transition visible to other CPUs. */
1718 kumaneko 1064 /* Mark the current process as execute handler. */
1719 kumaneko 1657 if (handler)
1720 kumaneko 1064 task->tomoyo_flags |= TOMOYO_TASK_IS_EXECUTE_HANDLER;
1721     /* Mark the current process as normal process. */
1722     else
1723     task->tomoyo_flags &= ~TOMOYO_TASK_IS_EXECUTE_HANDLER;
1724 kumaneko 1657 out:
1725     ccs_unregister_next_domain();
1726 kumaneko 1317 ccs_free(eh_path);
1727     ccs_free(tmp);
1728 kumaneko 815 return retval;
1729 kumaneko 115 }
1730    
1731 kumaneko 1015 #else
1732    
1733 kumaneko 1052 /**
1734     * search_binary_handler_with_transition - Wrapper for search_binary_handler().
1735     *
1736     * @bprm: Pointer to "struct linux_binprm".
1737     * @regs: Pointer to "struct pt_regs".
1738     *
1739     * Returns the result of search_binary_handler().
1740     */
1741     int search_binary_handler_with_transition(struct linux_binprm *bprm,
1742     struct pt_regs *regs)
1743 kumaneko 1015 {
1744     #ifdef CONFIG_SAKURA
1745 kumaneko 1578 /* Clear manager flag. */
1746     current->tomoyo_flags &= ~CCS_TASK_IS_POLICY_MANAGER;
1747 kumaneko 1052 ccs_load_policy(bprm->filename);
1748 kumaneko 1012 #endif
1749 kumaneko 1015 return search_binary_handler(bprm, regs);
1750     }
1751 kumaneko 1012
1752 kumaneko 1015 #endif

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26