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

Subversion リポジトリの参照

Annotation of /trunk/1.8.x/ccs-patch/security/ccsecurity/domain.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1058 - (hide annotations) (download) (as text)
Wed Mar 26 08:49:28 2008 UTC (16 years, 1 month ago) by kumaneko
Original Path: trunk/1.6.x/ccs-patch/fs/tomoyo_domain.c
File MIME type: text/x-csrc
File size: 43994 byte(s)


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

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