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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2853 - (hide annotations) (download) (as text)
Wed Aug 5 11:43:05 2009 UTC (14 years, 9 months ago) by kumaneko
Original Path: branches/ccs-patch/fs/ccsecurity/domain.c
File MIME type: text/x-csrc
File size: 39418 byte(s)
Move directory.
1 kumaneko 111 /*
2 kumaneko 2853 * fs/ccsecurity/domain.c
3 kumaneko 111 *
4 kumaneko 2030 * Copyright (C) 2005-2009 NTT DATA CORPORATION
5 kumaneko 111 *
6 kumaneko 2727 * Version: 1.7.0-pre 2009/07/03
7 kumaneko 111 *
8     * This file is applicable to both 2.4.30 and 2.6.11 and later.
9     * See README.ccs for ChangeLog.
10     *
11     */
12    
13 kumaneko 2763 #include <linux/slab.h>
14 kumaneko 115 #include <linux/highmem.h>
15 kumaneko 2763 #include <linux/version.h>
16 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
17     #include <linux/namei.h>
18     #include <linux/mount.h>
19     #endif
20 kumaneko 2402 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
21     #include <linux/fs_struct.h>
22     #endif
23 kumaneko 2853 #include "ccs_common.h"
24     #include <linux/ccsecurity.h>
25 kumaneko 115
26 kumaneko 1052 /* For compatibility with older kernels. */
27 kumaneko 111 #ifndef for_each_process
28     #define for_each_process for_each_task
29     #endif
30    
31 kumaneko 1052 /* Variables definitions.*/
32 kumaneko 111
33     /* The initial domain. */
34 kumaneko 2282 struct ccs_domain_info ccs_kernel_domain;
35 kumaneko 111
36 kumaneko 2282 /* The list for "struct ccs_domain_info". */
37 kumaneko 2540 LIST_HEAD(ccs_domain_list);
38 kumaneko 708
39 kumaneko 1052 /**
40     * ccs_get_last_name - Get last component of a domainname.
41     *
42 kumaneko 2282 * @domain: Pointer to "struct ccs_domain_info".
43 kumaneko 1052 *
44     * Returns the last component of the domainname.
45     */
46 kumaneko 2282 const char *ccs_get_last_name(const struct ccs_domain_info *domain)
47 kumaneko 111 {
48 kumaneko 1687 const char *cp0 = domain->domainname->name;
49     const char *cp1 = strrchr(cp0, ' ');
50 kumaneko 1052 if (cp1)
51     return cp1 + 1;
52 kumaneko 111 return cp0;
53     }
54    
55 kumaneko 1052 /**
56     * ccs_add_domain_acl - Add the given ACL to the given domain.
57     *
58 kumaneko 2282 * @domain: Pointer to "struct ccs_domain_info". May be NULL.
59 kumaneko 2002 * @acl: Pointer to "struct ccs_acl_info".
60 kumaneko 1052 *
61     * Returns 0.
62     */
63 kumaneko 2282 int ccs_add_domain_acl(struct ccs_domain_info *domain, struct ccs_acl_info *acl)
64 kumaneko 111 {
65 kumaneko 1695 if (domain) {
66 kumaneko 2553 if (acl->cond)
67     atomic_inc(&acl->cond->users);
68 kumaneko 2690 list_add_tail_rcu(&acl->list, &domain->acl_info_list);
69 kumaneko 1695 } else {
70 kumaneko 1052 acl->type &= ~ACL_DELETED;
71 kumaneko 1695 }
72 kumaneko 111 return 0;
73     }
74    
75 kumaneko 1052 /**
76     * ccs_del_domain_acl - Delete the given ACL from the domain.
77     *
78 kumaneko 2002 * @acl: Pointer to "struct ccs_acl_info". May be NULL.
79 kumaneko 1052 *
80     * Returns 0.
81     */
82 kumaneko 2002 int ccs_del_domain_acl(struct ccs_acl_info *acl)
83 kumaneko 111 {
84 kumaneko 1052 if (acl)
85     acl->type |= ACL_DELETED;
86 kumaneko 111 return 0;
87     }
88    
89 kumaneko 1052 /**
90 kumaneko 2002 * ccs_audit_execute_handler_log - Audit execute_handler log.
91 kumaneko 1052 *
92 kumaneko 2037 * @ee: Pointer to "struct ccs_execve_entry".
93 kumaneko 1064 * @is_default: True if it is "execute_handler" log.
94 kumaneko 1052 *
95     * Returns 0 on success, negative value otherwise.
96     */
97 kumaneko 2037 static int ccs_audit_execute_handler_log(struct ccs_execve_entry *ee,
98     const bool is_default)
99 kumaneko 1052 {
100 kumaneko 2037 struct ccs_request_info *r = &ee->r;
101     const char *handler = ee->handler->name;
102 kumaneko 2690 r->mode = ccs_check_flags(r->domain, CCS_MAC_FOR_FILE);
103 kumaneko 2037 return ccs_write_audit_log(true, r, "%s %s\n",
104 kumaneko 1657 is_default ? KEYWORD_EXECUTE_HANDLER :
105     KEYWORD_DENIED_EXECUTE_HANDLER, handler);
106 kumaneko 1052 }
107 kumaneko 111
108 kumaneko 1052 /**
109 kumaneko 2002 * ccs_audit_domain_creation_log - Audit domain creation log.
110 kumaneko 1052 *
111 kumaneko 2282 * @domain: Pointer to "struct ccs_domain_info".
112 kumaneko 1052 *
113     * Returns 0 on success, negative value otherwise.
114     */
115 kumaneko 2282 static int ccs_audit_domain_creation_log(struct ccs_domain_info *domain)
116 kumaneko 1052 {
117 kumaneko 2544 int error;
118 kumaneko 1657 struct ccs_request_info r;
119 kumaneko 2282 ccs_init_request_info(&r, domain, CCS_MAC_FOR_FILE);
120 kumaneko 2544 error = ccs_write_audit_log(false, &r, "use_profile %u\n", r.profile);
121     return error;
122 kumaneko 1052 }
123    
124 kumaneko 2002 /* The list for "struct ccs_domain_initializer_entry". */
125 kumaneko 2540 LIST_HEAD(ccs_domain_initializer_list);
126 kumaneko 111
127 kumaneko 1052 /**
128 kumaneko 2002 * ccs_update_domain_initializer_entry - Update "struct ccs_domain_initializer_entry" list.
129 kumaneko 1052 *
130     * @domainname: The name of domain. May be NULL.
131     * @program: The name of program.
132     * @is_not: True if it is "no_initialize_domain" entry.
133     * @is_delete: True if it is a delete request.
134     *
135     * Returns 0 on success, negative value otherwise.
136     */
137 kumaneko 2002 static int ccs_update_domain_initializer_entry(const char *domainname,
138     const char *program,
139     const bool is_not,
140     const bool is_delete)
141 kumaneko 111 {
142 kumaneko 2540 struct ccs_domain_initializer_entry *entry = NULL;
143 kumaneko 2002 struct ccs_domain_initializer_entry *ptr;
144     const struct ccs_path_info *saved_program;
145     const struct ccs_path_info *saved_domainname = NULL;
146 kumaneko 2540 int error = is_delete ? -ENOENT : -ENOMEM;
147 kumaneko 1016 bool is_last_name = false;
148 kumaneko 2577 if (!ccs_is_correct_path(program, 1, -1, -1))
149 kumaneko 1052 return -EINVAL; /* No patterns allowed. */
150 kumaneko 111 if (domainname) {
151 kumaneko 1052 if (!ccs_is_domain_def(domainname) &&
152 kumaneko 2577 ccs_is_correct_path(domainname, 1, -1, -1))
153 kumaneko 1016 is_last_name = true;
154 kumaneko 2577 else if (!ccs_is_correct_domain(domainname))
155 kumaneko 111 return -EINVAL;
156 kumaneko 2540 saved_domainname = ccs_get_name(domainname);
157 kumaneko 1052 if (!saved_domainname)
158     return -ENOMEM;
159 kumaneko 111 }
160 kumaneko 2540 saved_program = ccs_get_name(program);
161     if (!saved_program) {
162     ccs_put_name(saved_domainname);
163 kumaneko 1052 return -ENOMEM;
164 kumaneko 2540 }
165     if (!is_delete)
166     entry = kzalloc(sizeof(*entry), GFP_KERNEL);
167 kumaneko 2690 mutex_lock(&ccs_policy_lock);
168     list_for_each_entry_rcu(ptr, &ccs_domain_initializer_list, list) {
169 kumaneko 1052 if (ptr->is_not != is_not ||
170     ptr->domainname != saved_domainname ||
171     ptr->program != saved_program)
172     continue;
173     ptr->is_deleted = is_delete;
174     error = 0;
175 kumaneko 2540 break;
176 kumaneko 111 }
177 kumaneko 2718 if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {
178 kumaneko 2540 entry->domainname = saved_domainname;
179     saved_domainname = NULL;
180     entry->program = saved_program;
181     saved_program = NULL;
182     entry->is_not = is_not;
183     entry->is_last_name = is_last_name;
184 kumaneko 2690 list_add_tail_rcu(&entry->list, &ccs_domain_initializer_list);
185 kumaneko 2540 entry = NULL;
186     error = 0;
187 kumaneko 111 }
188 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
189 kumaneko 2540 ccs_put_name(saved_domainname);
190     ccs_put_name(saved_program);
191     kfree(entry);
192 kumaneko 111 return error;
193     }
194    
195 kumaneko 1052 /**
196 kumaneko 2002 * ccs_read_domain_initializer_policy - Read "struct ccs_domain_initializer_entry" list.
197 kumaneko 1052 *
198     * @head: Pointer to "struct ccs_io_buffer".
199     *
200     * Returns true on success, false otherwise.
201 kumaneko 2690 *
202 kumaneko 2828 * Caller holds ccs_read_lock().
203 kumaneko 1052 */
204     bool ccs_read_domain_initializer_policy(struct ccs_io_buffer *head)
205 kumaneko 111 {
206 kumaneko 2540 struct list_head *pos;
207     bool done = true;
208 kumaneko 2828 ccs_check_read_lock();
209 kumaneko 2690 list_for_each_cookie(pos, head->read_var2,
210     &ccs_domain_initializer_list) {
211 kumaneko 1064 const char *no;
212     const char *from = "";
213     const char *domain = "";
214 kumaneko 2002 struct ccs_domain_initializer_entry *ptr;
215 kumaneko 2540 ptr = list_entry(pos, struct ccs_domain_initializer_entry,
216 kumaneko 2002 list);
217 kumaneko 1052 if (ptr->is_deleted)
218     continue;
219 kumaneko 1064 no = ptr->is_not ? "no_" : "";
220 kumaneko 708 if (ptr->domainname) {
221 kumaneko 1064 from = " from ";
222     domain = ptr->domainname->name;
223     }
224 kumaneko 2540 done = ccs_io_printf(head,
225     "%s" KEYWORD_INITIALIZE_DOMAIN "%s%s%s\n",
226     no, ptr->program->name, from, domain);
227     if (!done)
228     break;
229 kumaneko 111 }
230 kumaneko 2540 return done;
231 kumaneko 111 }
232    
233 kumaneko 1052 /**
234 kumaneko 2002 * ccs_write_domain_initializer_policy - Write "struct ccs_domain_initializer_entry" list.
235 kumaneko 1052 *
236     * @data: String to parse.
237     * @is_not: True if it is "no_initialize_domain" entry.
238     * @is_delete: True if it is a delete request.
239     *
240     * Returns 0 on success, negative value otherwise.
241     */
242     int ccs_write_domain_initializer_policy(char *data, const bool is_not,
243     const bool is_delete)
244 kumaneko 111 {
245     char *cp = strstr(data, " from ");
246     if (cp) {
247     *cp = '\0';
248 kumaneko 2002 return ccs_update_domain_initializer_entry(cp + 6, data,
249     is_not, is_delete);
250 kumaneko 111 }
251 kumaneko 2002 return ccs_update_domain_initializer_entry(NULL, data, is_not,
252     is_delete);
253 kumaneko 111 }
254    
255 kumaneko 1052 /**
256 kumaneko 2002 * ccs_is_domain_initializer - Check whether the given program causes domainname reinitialization.
257 kumaneko 1052 *
258     * @domainname: The name of domain.
259     * @program: The name of program.
260     * @last_name: The last component of @domainname.
261     *
262     * Returns true if executing @program reinitializes domain transition,
263     * false otherwise.
264 kumaneko 2690 *
265 kumaneko 2828 * Caller holds ccs_read_lock().
266 kumaneko 1052 */
267 kumaneko 2002 static bool ccs_is_domain_initializer(const struct ccs_path_info *domainname,
268     const struct ccs_path_info *program,
269     const struct ccs_path_info *last_name)
270 kumaneko 111 {
271 kumaneko 2002 struct ccs_domain_initializer_entry *ptr;
272 kumaneko 1016 bool flag = false;
273 kumaneko 2828 ccs_check_read_lock();
274 kumaneko 2690 list_for_each_entry_rcu(ptr, &ccs_domain_initializer_list, list) {
275 kumaneko 1052 if (ptr->is_deleted)
276     continue;
277 kumaneko 111 if (ptr->domainname) {
278     if (!ptr->is_last_name) {
279 kumaneko 1052 if (ptr->domainname != domainname)
280     continue;
281 kumaneko 111 } else {
282 kumaneko 1052 if (ccs_pathcmp(ptr->domainname, last_name))
283     continue;
284 kumaneko 111 }
285     }
286 kumaneko 1052 if (ccs_pathcmp(ptr->program, program))
287     continue;
288 kumaneko 2540 if (ptr->is_not) {
289     flag = false;
290     break;
291     }
292 kumaneko 1016 flag = true;
293 kumaneko 111 }
294     return flag;
295     }
296    
297 kumaneko 2002 /* The list for "struct ccs_domain_keeper_entry". */
298 kumaneko 2540 LIST_HEAD(ccs_domain_keeper_list);
299 kumaneko 111
300 kumaneko 1052 /**
301 kumaneko 2002 * ccs_update_domain_keeper_entry - Update "struct ccs_domain_keeper_entry" list.
302 kumaneko 1052 *
303     * @domainname: The name of domain.
304     * @program: The name of program. May be NULL.
305     * @is_not: True if it is "no_keep_domain" entry.
306     * @is_delete: True if it is a delete request.
307     *
308     * Returns 0 on success, negative value otherwise.
309     */
310 kumaneko 2002 static int ccs_update_domain_keeper_entry(const char *domainname,
311     const char *program,
312     const bool is_not,
313     const bool is_delete)
314 kumaneko 111 {
315 kumaneko 2540 struct ccs_domain_keeper_entry *entry = NULL;
316 kumaneko 2002 struct ccs_domain_keeper_entry *ptr;
317     const struct ccs_path_info *saved_domainname;
318     const struct ccs_path_info *saved_program = NULL;
319 kumaneko 2540 int error = is_delete ? -ENOENT : -ENOMEM;
320 kumaneko 1016 bool is_last_name = false;
321 kumaneko 1052 if (!ccs_is_domain_def(domainname) &&
322 kumaneko 2577 ccs_is_correct_path(domainname, 1, -1, -1))
323 kumaneko 1016 is_last_name = true;
324 kumaneko 2577 else if (!ccs_is_correct_domain(domainname))
325 kumaneko 111 return -EINVAL;
326     if (program) {
327 kumaneko 2577 if (!ccs_is_correct_path(program, 1, -1, -1))
328 kumaneko 1052 return -EINVAL;
329 kumaneko 2540 saved_program = ccs_get_name(program);
330 kumaneko 1052 if (!saved_program)
331     return -ENOMEM;
332 kumaneko 111 }
333 kumaneko 2540 saved_domainname = ccs_get_name(domainname);
334     if (!saved_domainname) {
335     ccs_put_name(saved_program);
336 kumaneko 1052 return -ENOMEM;
337 kumaneko 2540 }
338     if (!is_delete)
339     entry = kzalloc(sizeof(*entry), GFP_KERNEL);
340 kumaneko 2690 mutex_lock(&ccs_policy_lock);
341     list_for_each_entry_rcu(ptr, &ccs_domain_keeper_list, list) {
342 kumaneko 1052 if (ptr->is_not != is_not ||
343     ptr->domainname != saved_domainname ||
344     ptr->program != saved_program)
345     continue;
346     ptr->is_deleted = is_delete;
347     error = 0;
348 kumaneko 2540 break;
349 kumaneko 111 }
350 kumaneko 2718 if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {
351 kumaneko 2540 entry->domainname = saved_domainname;
352     saved_domainname = NULL;
353     entry->program = saved_program;
354     saved_program = NULL;
355     entry->is_not = is_not;
356     entry->is_last_name = is_last_name;
357 kumaneko 2690 list_add_tail_rcu(&entry->list, &ccs_domain_keeper_list);
358 kumaneko 2540 entry = NULL;
359     error = 0;
360 kumaneko 111 }
361 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
362 kumaneko 2540 ccs_put_name(saved_domainname);
363     ccs_put_name(saved_program);
364     kfree(entry);
365 kumaneko 111 return error;
366     }
367    
368 kumaneko 1052 /**
369 kumaneko 2002 * ccs_write_domain_keeper_policy - Write "struct ccs_domain_keeper_entry" list.
370 kumaneko 1052 *
371     * @data: String to parse.
372     * @is_not: True if it is "no_keep_domain" entry.
373     * @is_delete: True if it is a delete request.
374     *
375     */
376     int ccs_write_domain_keeper_policy(char *data, const bool is_not,
377     const bool is_delete)
378 kumaneko 111 {
379     char *cp = strstr(data, " from ");
380     if (cp) {
381     *cp = '\0';
382 kumaneko 2002 return ccs_update_domain_keeper_entry(cp + 6, data,
383     is_not, is_delete);
384 kumaneko 111 }
385 kumaneko 2002 return ccs_update_domain_keeper_entry(data, NULL, is_not, is_delete);
386 kumaneko 111 }
387    
388 kumaneko 1052 /**
389 kumaneko 2002 * ccs_read_domain_keeper_policy - Read "struct ccs_domain_keeper_entry" list.
390 kumaneko 1052 *
391     * @head: Pointer to "struct ccs_io_buffer".
392     *
393     * Returns true on success, false otherwise.
394 kumaneko 2690 *
395 kumaneko 2828 * Caller holds ccs_read_lock().
396 kumaneko 1052 */
397     bool ccs_read_domain_keeper_policy(struct ccs_io_buffer *head)
398 kumaneko 111 {
399 kumaneko 2540 struct list_head *pos;
400     bool done = true;
401 kumaneko 2828 ccs_check_read_lock();
402 kumaneko 2690 list_for_each_cookie(pos, head->read_var2,
403     &ccs_domain_keeper_list) {
404 kumaneko 2002 struct ccs_domain_keeper_entry *ptr;
405 kumaneko 1064 const char *no;
406     const char *from = "";
407     const char *program = "";
408 kumaneko 2540 ptr = list_entry(pos, struct ccs_domain_keeper_entry, list);
409 kumaneko 1052 if (ptr->is_deleted)
410     continue;
411 kumaneko 1064 no = ptr->is_not ? "no_" : "";
412 kumaneko 708 if (ptr->program) {
413 kumaneko 1064 from = " from ";
414     program = ptr->program->name;
415     }
416 kumaneko 2540 done = ccs_io_printf(head,
417     "%s" KEYWORD_KEEP_DOMAIN "%s%s%s\n", no,
418     program, from, ptr->domainname->name);
419     if (!done)
420     break;
421 kumaneko 111 }
422 kumaneko 2540 return done;
423 kumaneko 111 }
424    
425 kumaneko 1052 /**
426 kumaneko 2002 * ccs_is_domain_keeper - Check whether the given program causes domain transition suppression.
427 kumaneko 1052 *
428     * @domainname: The name of domain.
429     * @program: The name of program.
430     * @last_name: The last component of @domainname.
431     *
432     * Returns true if executing @program supresses domain transition,
433     * false otherwise.
434 kumaneko 2690 *
435 kumaneko 2828 * Caller holds ccs_read_lock().
436 kumaneko 1052 */
437 kumaneko 2002 static bool ccs_is_domain_keeper(const struct ccs_path_info *domainname,
438     const struct ccs_path_info *program,
439     const struct ccs_path_info *last_name)
440 kumaneko 111 {
441 kumaneko 2002 struct ccs_domain_keeper_entry *ptr;
442 kumaneko 1016 bool flag = false;
443 kumaneko 2828 ccs_check_read_lock();
444 kumaneko 2690 list_for_each_entry_rcu(ptr, &ccs_domain_keeper_list, list) {
445 kumaneko 1052 if (ptr->is_deleted)
446     continue;
447 kumaneko 111 if (!ptr->is_last_name) {
448 kumaneko 1052 if (ptr->domainname != domainname)
449     continue;
450 kumaneko 111 } else {
451 kumaneko 1052 if (ccs_pathcmp(ptr->domainname, last_name))
452     continue;
453 kumaneko 111 }
454 kumaneko 1052 if (ptr->program && ccs_pathcmp(ptr->program, program))
455     continue;
456 kumaneko 2540 if (ptr->is_not) {
457     flag = false;
458     break;
459     }
460 kumaneko 1016 flag = true;
461 kumaneko 111 }
462     return flag;
463     }
464    
465 kumaneko 2002 /* The list for "struct ccs_aggregator_entry". */
466 kumaneko 2540 LIST_HEAD(ccs_aggregator_list);
467 kumaneko 111
468 kumaneko 1052 /**
469 kumaneko 2002 * ccs_update_aggregator_entry - Update "struct ccs_aggregator_entry" list.
470 kumaneko 1052 *
471     * @original_name: The original program's name.
472     * @aggregated_name: The aggregated program's name.
473     * @is_delete: True if it is a delete request.
474     *
475     * Returns 0 on success, negative value otherwise.
476     */
477 kumaneko 2002 static int ccs_update_aggregator_entry(const char *original_name,
478     const char *aggregated_name,
479     const bool is_delete)
480 kumaneko 111 {
481 kumaneko 2540 struct ccs_aggregator_entry *entry = NULL;
482 kumaneko 2002 struct ccs_aggregator_entry *ptr;
483     const struct ccs_path_info *saved_original_name;
484     const struct ccs_path_info *saved_aggregated_name;
485 kumaneko 2540 int error = is_delete ? -ENOENT : -ENOMEM;
486 kumaneko 2577 if (!ccs_is_correct_path(original_name, 1, 0, -1) ||
487     !ccs_is_correct_path(aggregated_name, 1, -1, -1))
488 kumaneko 1052 return -EINVAL;
489 kumaneko 2540 saved_original_name = ccs_get_name(original_name);
490     saved_aggregated_name = ccs_get_name(aggregated_name);
491     if (!saved_original_name || !saved_aggregated_name) {
492     ccs_put_name(saved_original_name);
493     ccs_put_name(saved_aggregated_name);
494 kumaneko 1052 return -ENOMEM;
495 kumaneko 2540 }
496     if (!is_delete)
497     entry = kzalloc(sizeof(*entry), GFP_KERNEL);
498 kumaneko 2690 mutex_lock(&ccs_policy_lock);
499     list_for_each_entry_rcu(ptr, &ccs_aggregator_list, list) {
500 kumaneko 1052 if (ptr->original_name != saved_original_name ||
501     ptr->aggregated_name != saved_aggregated_name)
502     continue;
503     ptr->is_deleted = is_delete;
504     error = 0;
505 kumaneko 2540 break;
506 kumaneko 111 }
507 kumaneko 2718 if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {
508 kumaneko 2540 entry->original_name = saved_original_name;
509     saved_original_name = NULL;
510     entry->aggregated_name = saved_aggregated_name;
511     saved_aggregated_name = NULL;
512 kumaneko 2690 list_add_tail_rcu(&entry->list, &ccs_aggregator_list);
513 kumaneko 2540 entry = NULL;
514     error = 0;
515 kumaneko 111 }
516 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
517 kumaneko 2540 ccs_put_name(saved_original_name);
518     ccs_put_name(saved_aggregated_name);
519     kfree(entry);
520 kumaneko 111 return error;
521     }
522    
523 kumaneko 1052 /**
524 kumaneko 2002 * ccs_read_aggregator_policy - Read "struct ccs_aggregator_entry" list.
525 kumaneko 1052 *
526     * @head: Pointer to "struct ccs_io_buffer".
527     *
528     * Returns true on success, false otherwise.
529 kumaneko 2690 *
530 kumaneko 2828 * Caller holds ccs_read_lock().
531 kumaneko 1052 */
532     bool ccs_read_aggregator_policy(struct ccs_io_buffer *head)
533 kumaneko 111 {
534 kumaneko 2540 struct list_head *pos;
535     bool done = true;
536 kumaneko 2828 ccs_check_read_lock();
537 kumaneko 2690 list_for_each_cookie(pos, head->read_var2, &ccs_aggregator_list) {
538 kumaneko 2002 struct ccs_aggregator_entry *ptr;
539 kumaneko 2540 ptr = list_entry(pos, struct ccs_aggregator_entry, list);
540 kumaneko 1052 if (ptr->is_deleted)
541     continue;
542 kumaneko 2540 done = ccs_io_printf(head, KEYWORD_AGGREGATOR "%s %s\n",
543     ptr->original_name->name,
544     ptr->aggregated_name->name);
545     if (!done)
546     break;
547 kumaneko 111 }
548 kumaneko 2540 return done;
549 kumaneko 111 }
550    
551 kumaneko 1052 /**
552 kumaneko 2002 * ccs_write_aggregator_policy - Write "struct ccs_aggregator_entry" list.
553 kumaneko 1052 *
554     * @data: String to parse.
555     * @is_delete: True if it is a delete request.
556     *
557     * Returns 0 on success, negative value otherwise.
558     */
559     int ccs_write_aggregator_policy(char *data, const bool is_delete)
560 kumaneko 111 {
561 kumaneko 2779 char *w[2];
562     if (!ccs_tokenize(data, w, sizeof(w)) || !w[1][0])
563     return -EINVAL;
564     return ccs_update_aggregator_entry(w[0], w[1], is_delete);
565 kumaneko 111 }
566    
567 kumaneko 2393 /* Domain create/delete handler. */
568 kumaneko 111
569 kumaneko 1052 /**
570     * ccs_delete_domain - Delete a domain.
571     *
572     * @domainname: The name of domain.
573     *
574     * Returns 0.
575     */
576     int ccs_delete_domain(char *domainname)
577 kumaneko 111 {
578 kumaneko 2282 struct ccs_domain_info *domain;
579 kumaneko 2002 struct ccs_path_info name;
580 kumaneko 1052 name.name = domainname;
581     ccs_fill_path_info(&name);
582 kumaneko 2690 mutex_lock(&ccs_policy_lock);
583 kumaneko 111 /* Is there an active domain? */
584 kumaneko 2690 list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
585 kumaneko 2282 /* Never delete ccs_kernel_domain */
586     if (domain == &ccs_kernel_domain)
587 kumaneko 1052 continue;
588     if (domain->is_deleted ||
589     ccs_pathcmp(domain->domainname, &name))
590     continue;
591 kumaneko 2393 domain->is_deleted = true;
592 kumaneko 708 break;
593 kumaneko 111 }
594 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
595 kumaneko 111 return 0;
596     }
597    
598 kumaneko 1052 /**
599     * ccs_find_or_assign_new_domain - Create a domain.
600     *
601     * @domainname: The name of domain.
602     * @profile: Profile number to assign if the domain was newly created.
603     *
604 kumaneko 2690 * Returns pointer to "struct ccs_domain_info" on success, NULL otherwise.
605 kumaneko 1052 */
606 kumaneko 2690 struct ccs_domain_info *ccs_find_or_assign_new_domain(const char *domainname,
607     const u8 profile)
608 kumaneko 111 {
609 kumaneko 2544 struct ccs_domain_info *entry;
610     struct ccs_domain_info *domain;
611     const struct ccs_path_info *saved_domainname;
612 kumaneko 2690 bool found = false;
613    
614 kumaneko 2577 if (!ccs_is_correct_domain(domainname))
615 kumaneko 2690 return NULL;
616 kumaneko 2544 saved_domainname = ccs_get_name(domainname);
617     if (!saved_domainname)
618 kumaneko 2690 return NULL;
619 kumaneko 2545 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
620 kumaneko 2690 mutex_lock(&ccs_policy_lock);
621     list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
622 kumaneko 2544 if (domain->is_deleted ||
623     ccs_pathcmp(saved_domainname, domain->domainname))
624     continue;
625 kumaneko 2690 found = true;
626 kumaneko 2544 break;
627 kumaneko 111 }
628 kumaneko 2718 if (!found && ccs_memory_ok(entry, sizeof(*entry))) {
629 kumaneko 2544 INIT_LIST_HEAD(&entry->acl_info_list);
630     entry->domainname = saved_domainname;
631     saved_domainname = NULL;
632     entry->profile = profile;
633 kumaneko 2690 list_add_tail_rcu(&entry->list, &ccs_domain_list);
634     domain = entry;
635 kumaneko 2544 entry = NULL;
636 kumaneko 2690 found = true;
637 kumaneko 2544 }
638 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
639 kumaneko 2540 ccs_put_name(saved_domainname);
640 kumaneko 2545 kfree(entry);
641 kumaneko 2690 return found ? domain : NULL;
642 kumaneko 111 }
643    
644 kumaneko 1052 /**
645 kumaneko 2002 * ccs_get_argv0 - Get argv[0].
646 kumaneko 1052 *
647 kumaneko 2037 * @ee: Pointer to "struct ccs_execve_entry".
648 kumaneko 1052 *
649     * Returns true on success, false otherwise.
650     */
651 kumaneko 2037 static bool ccs_get_argv0(struct ccs_execve_entry *ee)
652 kumaneko 111 {
653 kumaneko 2037 struct linux_binprm *bprm = ee->bprm;
654     char *arg_ptr = ee->tmp;
655 kumaneko 316 int arg_len = 0;
656     unsigned long pos = bprm->p;
657 kumaneko 1052 int offset = pos % PAGE_SIZE;
658 kumaneko 1031 bool done = false;
659 kumaneko 1052 if (!bprm->argc)
660     goto out;
661 kumaneko 316 while (1) {
662 kumaneko 2037 if (!ccs_dump_page(bprm, pos, &ee->dump))
663 kumaneko 1052 goto out;
664 kumaneko 1031 pos += PAGE_SIZE - offset;
665     /* Read. */
666     while (offset < PAGE_SIZE) {
667 kumaneko 2037 const char *kaddr = ee->dump.data;
668 kumaneko 1031 const unsigned char c = kaddr[offset++];
669     if (c && arg_len < CCS_MAX_PATHNAME_LEN - 10) {
670     if (c == '\\') {
671     arg_ptr[arg_len++] = '\\';
672     arg_ptr[arg_len++] = '\\';
673     } else if (c == '/') {
674     arg_len = 0;
675     } else if (c > ' ' && c < 127) {
676     arg_ptr[arg_len++] = c;
677     } else {
678     arg_ptr[arg_len++] = '\\';
679     arg_ptr[arg_len++] = (c >> 6) + '0';
680 kumaneko 1052 arg_ptr[arg_len++]
681     = ((c >> 3) & 7) + '0';
682 kumaneko 1031 arg_ptr[arg_len++] = (c & 7) + '0';
683     }
684     } else {
685     arg_ptr[arg_len] = '\0';
686     done = true;
687     break;
688 kumaneko 316 }
689 kumaneko 115 }
690 kumaneko 316 offset = 0;
691 kumaneko 1052 if (done)
692     break;
693 kumaneko 115 }
694 kumaneko 1031 return true;
695     out:
696     return false;
697 kumaneko 115 }
698 kumaneko 2318
699 kumaneko 1052 /**
700 kumaneko 2002 * ccs_find_next_domain - Find a domain.
701 kumaneko 1052 *
702 kumaneko 2075 * @ee: Pointer to "struct ccs_execve_entry".
703 kumaneko 1052 *
704     * Returns 0 on success, negative value otherwise.
705 kumaneko 2690 *
706 kumaneko 2828 * Caller holds ccs_read_lock().
707 kumaneko 1052 */
708 kumaneko 2037 static int ccs_find_next_domain(struct ccs_execve_entry *ee)
709 kumaneko 115 {
710 kumaneko 2037 struct ccs_request_info *r = &ee->r;
711     const struct ccs_path_info *handler = ee->handler;
712 kumaneko 2691 struct ccs_domain_info *domain = NULL;
713 kumaneko 2690 const char *old_domain_name = r->domain->domainname->name;
714 kumaneko 2037 struct linux_binprm *bprm = ee->bprm;
715 kumaneko 1657 const u8 mode = r->mode;
716     const bool is_enforce = (mode == 3);
717 kumaneko 2282 const u32 ccs_flags = current->ccs_flags;
718 kumaneko 111 char *new_domain_name = NULL;
719 kumaneko 2002 struct ccs_path_info rn; /* real name */
720     struct ccs_path_info ln; /* last name */
721 kumaneko 111 int retval;
722 kumaneko 2828 ccs_check_read_lock();
723 kumaneko 1561 retry:
724 kumaneko 2282 current->ccs_flags = ccs_flags;
725 kumaneko 2690 r->cond = NULL;
726 kumaneko 2738 /* Get symlink's pathname of program. */
727     retval = ccs_symlink_path(bprm->filename, ee);
728 kumaneko 2075 if (retval < 0)
729 kumaneko 1052 goto out;
730 kumaneko 111
731 kumaneko 2037 rn.name = ee->program_path;
732 kumaneko 1657 ccs_fill_path_info(&rn);
733 kumaneko 2690 ln.name = ccs_get_last_name(r->domain);
734 kumaneko 1657 ccs_fill_path_info(&ln);
735 kumaneko 111
736 kumaneko 1657 if (handler) {
737     if (ccs_pathcmp(&rn, handler)) {
738 kumaneko 1064 /* Failed to verify execute handler. */
739 kumaneko 1029 static u8 counter = 20;
740     if (counter) {
741     counter--;
742 kumaneko 1052 printk(KERN_WARNING "Failed to verify: %s\n",
743 kumaneko 1657 handler->name);
744 kumaneko 1029 }
745     goto out;
746     }
747 kumaneko 1052 goto calculate_domain;
748 kumaneko 1029 }
749 kumaneko 708
750 kumaneko 2037 /* Compare basename of program_path and argv[0] */
751 kumaneko 2690 r->mode = ccs_check_flags(r->domain, CCS_MAC_FOR_ARGV0);
752 kumaneko 1657 if (bprm->argc > 0 && r->mode) {
753 kumaneko 2037 char *base_argv0 = ee->tmp;
754 kumaneko 1031 const char *base_filename;
755 kumaneko 115 retval = -ENOMEM;
756 kumaneko 2037 if (!ccs_get_argv0(ee))
757 kumaneko 1052 goto out;
758 kumaneko 2037 base_filename = strrchr(ee->program_path, '/');
759 kumaneko 1052 if (!base_filename)
760 kumaneko 2037 base_filename = ee->program_path;
761 kumaneko 1052 else
762     base_filename++;
763 kumaneko 1031 if (strcmp(base_argv0, base_filename)) {
764 kumaneko 1657 retval = ccs_check_argv0_perm(r, &rn, base_argv0);
765 kumaneko 1781 if (retval == 1)
766 kumaneko 1561 goto retry;
767     if (retval < 0)
768 kumaneko 1052 goto out;
769 kumaneko 111 }
770     }
771 kumaneko 1032
772 kumaneko 183 /* Check 'aggregator' directive. */
773     {
774 kumaneko 2002 struct ccs_aggregator_entry *ptr;
775 kumaneko 183 /* Is this program allowed to be aggregated? */
776 kumaneko 2690 list_for_each_entry_rcu(ptr, &ccs_aggregator_list, list) {
777 kumaneko 1052 if (ptr->is_deleted ||
778 kumaneko 1657 !ccs_path_matches_pattern(&rn, ptr->original_name))
779 kumaneko 1052 continue;
780 kumaneko 2037 strncpy(ee->program_path, ptr->aggregated_name->name,
781 kumaneko 1052 CCS_MAX_PATHNAME_LEN - 1);
782 kumaneko 1657 ccs_fill_path_info(&rn);
783 kumaneko 183 break;
784     }
785     }
786    
787 kumaneko 111 /* Check execute permission. */
788 kumaneko 1657 r->mode = mode;
789     retval = ccs_check_exec_perm(r, &rn);
790 kumaneko 1781 if (retval == 1)
791 kumaneko 1561 goto retry;
792 kumaneko 1052 if (retval < 0)
793     goto out;
794 kumaneko 111
795 kumaneko 1052 calculate_domain:
796 kumaneko 2037 new_domain_name = ee->tmp;
797 kumaneko 2690 if (ccs_is_domain_initializer(r->domain->domainname, &rn, &ln)) {
798 kumaneko 2282 /* Transit to the child of ccs_kernel_domain domain. */
799 kumaneko 2037 snprintf(new_domain_name, CCS_EXEC_TMPSIZE - 1,
800     ROOT_NAME " " "%s", ee->program_path);
801 kumaneko 2690 } else if (r->domain == &ccs_kernel_domain && !ccs_policy_loaded) {
802 kumaneko 111 /*
803 kumaneko 1052 * Needn't to transit from kernel domain before starting
804 kumaneko 1064 * /sbin/init. But transit from kernel domain if executing
805     * initializers because they might start before /sbin/init.
806 kumaneko 111 */
807 kumaneko 2690 domain = r->domain;
808     } else if (ccs_is_domain_keeper(r->domain->domainname, &rn, &ln)) {
809 kumaneko 111 /* Keep current domain. */
810 kumaneko 2690 domain = r->domain;
811 kumaneko 111 } else {
812     /* Normal domain transition. */
813 kumaneko 2037 snprintf(new_domain_name, CCS_EXEC_TMPSIZE - 1,
814     "%s %s", old_domain_name, ee->program_path);
815 kumaneko 111 }
816 kumaneko 2690 if (domain || strlen(new_domain_name) >= CCS_MAX_PATHNAME_LEN)
817 kumaneko 1052 goto done;
818 kumaneko 2690 domain = ccs_find_domain(new_domain_name);
819     if (domain)
820 kumaneko 1052 goto done;
821 kumaneko 1561 if (is_enforce) {
822 kumaneko 1657 int error = ccs_check_supervisor(r,
823 kumaneko 1561 "# wants to create domain\n"
824     "%s\n", new_domain_name);
825 kumaneko 1781 if (error == 1)
826 kumaneko 1561 goto retry;
827     if (error < 0)
828 kumaneko 1052 goto done;
829 kumaneko 1561 }
830 kumaneko 2690 domain = ccs_find_or_assign_new_domain(new_domain_name, r->profile);
831     if (domain)
832     ccs_audit_domain_creation_log(r->domain);
833 kumaneko 1052 done:
834 kumaneko 2691 if (!domain) {
835     printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
836     new_domain_name);
837     if (is_enforce)
838     retval = -EPERM;
839     else {
840     retval = 0;
841     r->domain->domain_transition_failed = true;
842     }
843     } else {
844 kumaneko 111 retval = 0;
845     }
846 kumaneko 1052 out:
847 kumaneko 2691 if (domain)
848     r->domain = domain;
849 kumaneko 111 return retval;
850     }
851    
852 kumaneko 1052 /**
853 kumaneko 2002 * ccs_check_environ - Check permission for environment variable names.
854 kumaneko 1052 *
855 kumaneko 2037 * @ee: Pointer to "struct ccs_execve_entry".
856 kumaneko 1052 *
857     * Returns 0 on success, negative value otherwise.
858     */
859 kumaneko 2037 static int ccs_check_environ(struct ccs_execve_entry *ee)
860 kumaneko 581 {
861 kumaneko 2037 struct ccs_request_info *r = &ee->r;
862     struct linux_binprm *bprm = ee->bprm;
863     char *arg_ptr = ee->tmp;
864 kumaneko 581 int arg_len = 0;
865     unsigned long pos = bprm->p;
866 kumaneko 1064 int offset = pos % PAGE_SIZE;
867 kumaneko 581 int argv_count = bprm->argc;
868     int envp_count = bprm->envc;
869 kumaneko 1052 /* printk(KERN_DEBUG "start %d %d\n", argv_count, envp_count); */
870 kumaneko 581 int error = -ENOMEM;
871 kumaneko 1657 if (!r->mode || !envp_count)
872 kumaneko 1052 return 0;
873 kumaneko 581 while (error == -ENOMEM) {
874 kumaneko 2037 if (!ccs_dump_page(bprm, pos, &ee->dump))
875 kumaneko 1052 goto out;
876 kumaneko 986 pos += PAGE_SIZE - offset;
877 kumaneko 581 /* Read. */
878     while (argv_count && offset < PAGE_SIZE) {
879 kumaneko 2037 const char *kaddr = ee->dump.data;
880 kumaneko 1052 if (!kaddr[offset++])
881     argv_count--;
882 kumaneko 581 }
883 kumaneko 2037 if (argv_count) {
884     offset = 0;
885     continue;
886     }
887 kumaneko 581 while (offset < PAGE_SIZE) {
888 kumaneko 2037 const char *kaddr = ee->dump.data;
889 kumaneko 581 const unsigned char c = kaddr[offset++];
890 kumaneko 652 if (c && arg_len < CCS_MAX_PATHNAME_LEN - 10) {
891 kumaneko 581 if (c == '=') {
892     arg_ptr[arg_len++] = '\0';
893     } else if (c == '\\') {
894     arg_ptr[arg_len++] = '\\';
895     arg_ptr[arg_len++] = '\\';
896     } else if (c > ' ' && c < 127) {
897     arg_ptr[arg_len++] = c;
898     } else {
899     arg_ptr[arg_len++] = '\\';
900     arg_ptr[arg_len++] = (c >> 6) + '0';
901 kumaneko 1052 arg_ptr[arg_len++]
902     = ((c >> 3) & 7) + '0';
903 kumaneko 581 arg_ptr[arg_len++] = (c & 7) + '0';
904     }
905     } else {
906     arg_ptr[arg_len] = '\0';
907     }
908 kumaneko 1052 if (c)
909     continue;
910 kumaneko 1657 if (ccs_check_env_perm(r, arg_ptr)) {
911 kumaneko 581 error = -EPERM;
912     break;
913     }
914     if (!--envp_count) {
915     error = 0;
916     break;
917     }
918     arg_len = 0;
919     }
920     offset = 0;
921     }
922     out:
923 kumaneko 1657 if (r->mode != 3)
924 kumaneko 1052 error = 0;
925 kumaneko 581 return error;
926     }
927 kumaneko 111
928 kumaneko 1052 /**
929 kumaneko 2002 * ccs_unescape - Unescape escaped string.
930 kumaneko 1052 *
931 kumaneko 2075 * @dest: String to unescape.
932 kumaneko 1052 *
933     * Returns nothing.
934     */
935 kumaneko 2002 static void ccs_unescape(unsigned char *dest)
936 kumaneko 708 {
937     unsigned char *src = dest;
938 kumaneko 1064 unsigned char c;
939     unsigned char d;
940     unsigned char e;
941 kumaneko 1747 while (1) {
942     c = *src++;
943     if (!c)
944     break;
945 kumaneko 708 if (c != '\\') {
946     *dest++ = c;
947     continue;
948     }
949     c = *src++;
950     if (c == '\\') {
951     *dest++ = c;
952 kumaneko 1052 continue;
953     }
954     if (c < '0' || c > '3')
955 kumaneko 708 break;
956 kumaneko 1052 d = *src++;
957     if (d < '0' || d > '7')
958     break;
959     e = *src++;
960     if (e < '0' || e > '7')
961     break;
962     *dest++ = ((c - '0') << 6) + ((d - '0') << 3) + (e - '0');
963 kumaneko 708 }
964     *dest = '\0';
965     }
966    
967 kumaneko 1052 /**
968 kumaneko 2002 * ccs_root_depth - Get number of directories to strip.
969 kumaneko 1052 *
970     * @dentry: Pointer to "struct dentry".
971     * @vfsmnt: Pointer to "struct vfsmount".
972     *
973     * Returns number of directories to strip.
974 kumaneko 1029 */
975 kumaneko 2002 static inline int ccs_root_depth(struct dentry *dentry, struct vfsmount *vfsmnt)
976 kumaneko 708 {
977 kumaneko 1029 int depth = 0;
978     /***** CRITICAL SECTION START *****/
979 kumaneko 1474 ccs_realpath_lock();
980 kumaneko 1029 for (;;) {
981     if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
982     /* Global root? */
983 kumaneko 1052 if (vfsmnt->mnt_parent == vfsmnt)
984     break;
985 kumaneko 1029 dentry = vfsmnt->mnt_mountpoint;
986     vfsmnt = vfsmnt->mnt_parent;
987     continue;
988     }
989     dentry = dentry->d_parent;
990     depth++;
991     }
992 kumaneko 1474 ccs_realpath_unlock();
993 kumaneko 1029 /***** CRITICAL SECTION END *****/
994 kumaneko 1052 return depth;
995     }
996    
997     /**
998 kumaneko 2002 * ccs_get_root_depth - return the depth of root directory.
999 kumaneko 1052 *
1000     * Returns number of directories to strip.
1001     */
1002 kumaneko 2002 static int ccs_get_root_depth(void)
1003 kumaneko 1052 {
1004     int depth;
1005     struct dentry *dentry;
1006     struct vfsmount *vfsmnt;
1007     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1008     struct path root;
1009     #endif
1010     /***** CRITICAL SECTION START *****/
1011     read_lock(&current->fs->lock);
1012     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1013     root = current->fs->root;
1014     path_get(&current->fs->root);
1015     dentry = root.dentry;
1016     vfsmnt = root.mnt;
1017     #else
1018     dentry = dget(current->fs->root);
1019     vfsmnt = mntget(current->fs->rootmnt);
1020     #endif
1021     read_unlock(&current->fs->lock);
1022     /***** CRITICAL SECTION END *****/
1023 kumaneko 2002 depth = ccs_root_depth(dentry, vfsmnt);
1024 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1025 kumaneko 1029 path_put(&root);
1026     #else
1027 kumaneko 1052 dput(dentry);
1028     mntput(vfsmnt);
1029 kumaneko 1029 #endif
1030     return depth;
1031     }
1032    
1033 kumaneko 2037 static LIST_HEAD(ccs_execve_list);
1034     static DEFINE_SPINLOCK(ccs_execve_list_lock);
1035    
1036 kumaneko 1052 /**
1037 kumaneko 2037 * ccs_allocate_execve_entry - Allocate memory for execve().
1038     *
1039     * Returns pointer to "struct ccs_execve_entry" on success, NULL otherwise.
1040     */
1041     static struct ccs_execve_entry *ccs_allocate_execve_entry(void)
1042     {
1043 kumaneko 2711 struct ccs_execve_entry *ee = kzalloc(sizeof(*ee), GFP_KERNEL);
1044 kumaneko 2037 if (!ee)
1045     return NULL;
1046 kumaneko 2711 ee->program_path = kzalloc(CCS_MAX_PATHNAME_LEN, GFP_KERNEL);
1047 kumaneko 2727 ee->tmp = kzalloc(CCS_EXEC_TMPSIZE, GFP_KERNEL);
1048 kumaneko 2037 if (!ee->program_path || !ee->tmp) {
1049 kumaneko 2711 kfree(ee->program_path);
1050     kfree(ee->tmp);
1051     kfree(ee);
1052 kumaneko 2037 return NULL;
1053     }
1054 kumaneko 2828 ee->reader_idx = ccs_read_lock();
1055 kumaneko 2037 /* ee->dump->data is allocated by ccs_dump_page(). */
1056     ee->task = current;
1057     /***** CRITICAL SECTION START *****/
1058     spin_lock(&ccs_execve_list_lock);
1059     list_add(&ee->list, &ccs_execve_list);
1060     spin_unlock(&ccs_execve_list_lock);
1061     /***** CRITICAL SECTION END *****/
1062     return ee;
1063     }
1064    
1065     /**
1066     * ccs_find_execve_entry - Find ccs_execve_entry of current process.
1067     *
1068     * Returns pointer to "struct ccs_execve_entry" on success, NULL otherwise.
1069     */
1070     static struct ccs_execve_entry *ccs_find_execve_entry(void)
1071     {
1072     struct task_struct *task = current;
1073     struct ccs_execve_entry *ee = NULL;
1074     struct ccs_execve_entry *p;
1075     /***** CRITICAL SECTION START *****/
1076     spin_lock(&ccs_execve_list_lock);
1077     list_for_each_entry(p, &ccs_execve_list, list) {
1078     if (p->task != task)
1079     continue;
1080     ee = p;
1081     break;
1082     }
1083     spin_unlock(&ccs_execve_list_lock);
1084     /***** CRITICAL SECTION END *****/
1085     return ee;
1086     }
1087    
1088     /**
1089     * ccs_free_execve_entry - Free memory for execve().
1090     *
1091     * @ee: Pointer to "struct ccs_execve_entry".
1092     */
1093     static void ccs_free_execve_entry(struct ccs_execve_entry *ee)
1094     {
1095     if (!ee)
1096     return;
1097     /***** CRITICAL SECTION START *****/
1098     spin_lock(&ccs_execve_list_lock);
1099     list_del(&ee->list);
1100     spin_unlock(&ccs_execve_list_lock);
1101     /***** CRITICAL SECTION END *****/
1102 kumaneko 2711 kfree(ee->program_path);
1103     kfree(ee->tmp);
1104 kumaneko 2037 kfree(ee->dump.data);
1105 kumaneko 2828 ccs_read_unlock(ee->reader_idx);
1106 kumaneko 2711 kfree(ee);
1107 kumaneko 2037 }
1108    
1109     /**
1110 kumaneko 2002 * ccs_try_alt_exec - Try to start execute handler.
1111 kumaneko 1052 *
1112 kumaneko 2075 * @ee: Pointer to "struct ccs_execve_entry".
1113 kumaneko 1052 *
1114     * Returns 0 on success, negative value otherwise.
1115     */
1116 kumaneko 2037 static int ccs_try_alt_exec(struct ccs_execve_entry *ee)
1117 kumaneko 1029 {
1118 kumaneko 1005 /*
1119     * Contents of modified bprm.
1120     * The envp[] in original bprm is moved to argv[] so that
1121     * the alternatively executed program won't be affected by
1122 kumaneko 1064 * some dangerous environment variables like LD_PRELOAD.
1123 kumaneko 1005 *
1124     * modified bprm->argc
1125     * = original bprm->argc + original bprm->envc + 7
1126     * modified bprm->envc
1127     * = 0
1128     *
1129     * modified bprm->argv[0]
1130 kumaneko 1029 * = the program's name specified by execute_handler
1131 kumaneko 1005 * modified bprm->argv[1]
1132 kumaneko 2282 * = ccs_current_domain()->domainname->name
1133 kumaneko 1005 * modified bprm->argv[2]
1134     * = the current process's name
1135     * modified bprm->argv[3]
1136     * = the current process's information (e.g. uid/gid).
1137     * modified bprm->argv[4]
1138     * = original bprm->filename
1139     * modified bprm->argv[5]
1140     * = original bprm->argc in string expression
1141     * modified bprm->argv[6]
1142     * = original bprm->envc in string expression
1143     * modified bprm->argv[7]
1144     * = original bprm->argv[0]
1145     * ...
1146     * modified bprm->argv[bprm->argc + 6]
1147     * = original bprm->argv[bprm->argc - 1]
1148     * modified bprm->argv[bprm->argc + 7]
1149     * = original bprm->envp[0]
1150     * ...
1151     * modified bprm->argv[bprm->envc + bprm->argc + 6]
1152     * = original bprm->envp[bprm->envc - 1]
1153     */
1154 kumaneko 2037 struct linux_binprm *bprm = ee->bprm;
1155 kumaneko 708 struct file *filp;
1156     int retval;
1157 kumaneko 1005 const int original_argc = bprm->argc;
1158     const int original_envc = bprm->envc;
1159     struct task_struct *task = current;
1160 kumaneko 1032
1161 kumaneko 1029 /* Close the requested program's dentry. */
1162 kumaneko 708 allow_write_access(bprm->file);
1163     fput(bprm->file);
1164     bprm->file = NULL;
1165 kumaneko 1005
1166 kumaneko 2037 /* Invalidate page dump cache. */
1167     ee->dump.page = NULL;
1168 kumaneko 1029
1169 kumaneko 1005 /* Move envp[] to argv[] */
1170     bprm->argc += bprm->envc;
1171     bprm->envc = 0;
1172    
1173     /* Set argv[6] */
1174     {
1175 kumaneko 2037 char *cp = ee->tmp;
1176     snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%d", original_envc);
1177     retval = copy_strings_kernel(1, &cp, bprm);
1178 kumaneko 1052 if (retval < 0)
1179     goto out;
1180 kumaneko 1005 bprm->argc++;
1181     }
1182    
1183     /* Set argv[5] */
1184     {
1185 kumaneko 2037 char *cp = ee->tmp;
1186     snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%d", original_argc);
1187     retval = copy_strings_kernel(1, &cp, bprm);
1188 kumaneko 1052 if (retval < 0)
1189     goto out;
1190 kumaneko 1005 bprm->argc++;
1191     }
1192    
1193     /* Set argv[4] */
1194     {
1195 kumaneko 2075 retval = copy_strings_kernel(1, &bprm->filename, bprm);
1196 kumaneko 1052 if (retval < 0)
1197     goto out;
1198 kumaneko 1005 bprm->argc++;
1199     }
1200    
1201     /* Set argv[3] */
1202     {
1203 kumaneko 2037 char *cp = ee->tmp;
1204 kumaneko 2282 const u32 ccs_flags = task->ccs_flags;
1205 kumaneko 2037 snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1,
1206 kumaneko 1052 "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "
1207     "sgid=%d fsuid=%d fsgid=%d state[0]=%u "
1208     "state[1]=%u state[2]=%u",
1209 kumaneko 2016 (pid_t) sys_getpid(), current_uid(), current_gid(),
1210     current_euid(), current_egid(), current_suid(),
1211     current_sgid(), current_fsuid(), current_fsgid(),
1212 kumaneko 2282 (u8) (ccs_flags >> 24), (u8) (ccs_flags >> 16),
1213     (u8) (ccs_flags >> 8));
1214 kumaneko 2037 retval = copy_strings_kernel(1, &cp, bprm);
1215 kumaneko 1052 if (retval < 0)
1216     goto out;
1217 kumaneko 1005 bprm->argc++;
1218     }
1219    
1220     /* Set argv[2] */
1221     {
1222 kumaneko 1052 char *exe = (char *) ccs_get_exe();
1223 kumaneko 1005 if (exe) {
1224     retval = copy_strings_kernel(1, &exe, bprm);
1225 kumaneko 2711 kfree(exe);
1226 kumaneko 1005 } else {
1227 kumaneko 2037 exe = ee->tmp;
1228     strncpy(ee->tmp, "<unknown>", CCS_EXEC_TMPSIZE - 1);
1229     retval = copy_strings_kernel(1, &exe, bprm);
1230 kumaneko 1005 }
1231 kumaneko 1052 if (retval < 0)
1232     goto out;
1233 kumaneko 1005 bprm->argc++;
1234     }
1235    
1236     /* Set argv[1] */
1237     {
1238 kumaneko 2037 char *cp = ee->tmp;
1239 kumaneko 2282 strncpy(ee->tmp, ccs_current_domain()->domainname->name,
1240 kumaneko 2037 CCS_EXEC_TMPSIZE - 1);
1241     retval = copy_strings_kernel(1, &cp, bprm);
1242 kumaneko 1052 if (retval < 0)
1243     goto out;
1244 kumaneko 1005 bprm->argc++;
1245     }
1246    
1247     /* Set argv[0] */
1248     {
1249 kumaneko 2037 int depth = ccs_get_root_depth();
1250     char *cp = ee->program_path;
1251     strncpy(cp, ee->handler->name, CCS_MAX_PATHNAME_LEN - 1);
1252     ccs_unescape(cp);
1253     retval = -ENOENT;
1254     if (!*cp || *cp != '/')
1255     goto out;
1256     /* Adjust root directory for open_exec(). */
1257     while (depth) {
1258     cp = strchr(cp + 1, '/');
1259     if (!cp)
1260     goto out;
1261     depth--;
1262     }
1263     memmove(ee->program_path, cp, strlen(cp) + 1);
1264     cp = ee->program_path;
1265     retval = copy_strings_kernel(1, &cp, bprm);
1266 kumaneko 1052 if (retval < 0)
1267     goto out;
1268 kumaneko 1005 bprm->argc++;
1269     }
1270 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
1271     #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
1272 kumaneko 1007 bprm->argv_len = bprm->exec - bprm->p;
1273     #endif
1274 kumaneko 1052 #endif
1275 kumaneko 1005
1276 kumaneko 1029 /* OK, now restart the process with execute handler program's dentry. */
1277 kumaneko 2037 filp = open_exec(ee->program_path);
1278 kumaneko 1005 if (IS_ERR(filp)) {
1279     retval = PTR_ERR(filp);
1280     goto out;
1281     }
1282 kumaneko 1052 bprm->file = filp;
1283 kumaneko 2037 bprm->filename = ee->program_path;
1284 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
1285 kumaneko 2076 bprm->interp = bprm->filename;
1286 kumaneko 708 #endif
1287 kumaneko 1029 retval = prepare_binprm(bprm);
1288 kumaneko 1052 if (retval < 0)
1289     goto out;
1290 kumaneko 2075 {
1291 kumaneko 2076 /*
1292     * Backup ee->program_path because ccs_find_next_domain() will
1293     * overwrite ee->program_path and ee->tmp.
1294     */
1295 kumaneko 2075 const int len = strlen(ee->program_path) + 1;
1296 kumaneko 2711 char *cp = kzalloc(len, GFP_KERNEL);
1297 kumaneko 2075 if (!cp) {
1298     retval = -ENOMEM;
1299     goto out;
1300     }
1301     memmove(cp, ee->program_path, len);
1302 kumaneko 2076 bprm->filename = cp;
1303     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
1304     bprm->interp = bprm->filename;
1305     #endif
1306 kumaneko 2282 task->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1307 kumaneko 2075 retval = ccs_find_next_domain(ee);
1308 kumaneko 2282 task->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1309 kumaneko 2075 /* Restore ee->program_path for search_binary_handler(). */
1310     memmove(ee->program_path, cp, len);
1311 kumaneko 2076 bprm->filename = ee->program_path;
1312     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
1313     bprm->interp = bprm->filename;
1314     #endif
1315 kumaneko 2075 kfree(cp);
1316     }
1317 kumaneko 1005 out:
1318     return retval;
1319 kumaneko 708 }
1320 kumaneko 581
1321 kumaneko 1052 /**
1322 kumaneko 2002 * ccs_find_execute_handler - Find an execute handler.
1323 kumaneko 1052 *
1324 kumaneko 2037 * @ee: Pointer to "struct ccs_execve_entry".
1325 kumaneko 1052 * @type: Type of execute handler.
1326     *
1327 kumaneko 2075 * Returns true if found, false otherwise.
1328 kumaneko 2690 *
1329 kumaneko 2828 * Caller holds ccs_read_lock().
1330 kumaneko 1052 */
1331 kumaneko 2037 static bool ccs_find_execute_handler(struct ccs_execve_entry *ee,
1332     const u8 type)
1333 kumaneko 1029 {
1334 kumaneko 1064 struct task_struct *task = current;
1335 kumaneko 2282 const struct ccs_domain_info *domain = ccs_current_domain();
1336 kumaneko 2002 struct ccs_acl_info *ptr;
1337 kumaneko 2540 bool found = false;
1338 kumaneko 2828 ccs_check_read_lock();
1339 kumaneko 1064 /*
1340     * Don't use execute handler if the current process is
1341     * marked as execute handler to avoid infinite execute handler loop.
1342     */
1343 kumaneko 2282 if (task->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)
1344 kumaneko 2037 return false;
1345 kumaneko 2540 list_for_each_entry(ptr, &domain->acl_info_list, list) {
1346 kumaneko 2002 struct ccs_execute_handler_record *acl;
1347 kumaneko 1058 if (ptr->type != type)
1348 kumaneko 1052 continue;
1349 kumaneko 2002 acl = container_of(ptr, struct ccs_execute_handler_record,
1350     head);
1351 kumaneko 2037 ee->handler = acl->handler;
1352 kumaneko 2540 found = true;
1353     break;
1354 kumaneko 1029 }
1355 kumaneko 2540 return found;
1356 kumaneko 1029 }
1357    
1358 kumaneko 1052 /**
1359 kumaneko 2037 * ccs_dump_page - Dump a page to buffer.
1360 kumaneko 1657 *
1361 kumaneko 2037 * @bprm: Pointer to "struct linux_binprm".
1362     * @pos: Location to dump.
1363     * @dump: Poiner to "struct ccs_page_dump".
1364 kumaneko 1657 *
1365 kumaneko 2037 * Returns true on success, false otherwise.
1366 kumaneko 1657 */
1367 kumaneko 2037 bool ccs_dump_page(struct linux_binprm *bprm, unsigned long pos,
1368     struct ccs_page_dump *dump)
1369 kumaneko 1657 {
1370 kumaneko 2037 struct page *page;
1371     /* dump->data is released by ccs_free_execve_entry(). */
1372     if (!dump->data) {
1373 kumaneko 2711 dump->data = kzalloc(PAGE_SIZE, GFP_KERNEL);
1374 kumaneko 2037 if (!dump->data)
1375     return false;
1376     }
1377     /* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */
1378     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
1379     if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
1380     return false;
1381 kumaneko 2346 #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR == 3 && defined(CONFIG_MMU)
1382     if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
1383     return false;
1384 kumaneko 2037 #else
1385     page = bprm->page[pos / PAGE_SIZE];
1386     #endif
1387     if (page != dump->page) {
1388     const unsigned int offset = pos % PAGE_SIZE;
1389     /*
1390     * Maybe kmap()/kunmap() should be used here.
1391     * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic().
1392     * So do I.
1393     */
1394     char *kaddr = kmap_atomic(page, KM_USER0);
1395     dump->page = page;
1396     memcpy(dump->data + offset, kaddr + offset, PAGE_SIZE - offset);
1397     kunmap_atomic(kaddr, KM_USER0);
1398     }
1399     /* Same with put_arg_page(page) in fs/exec.c */
1400     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
1401     put_page(page);
1402 kumaneko 2346 #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR == 3 && defined(CONFIG_MMU)
1403     put_page(page);
1404 kumaneko 2037 #endif
1405     return true;
1406 kumaneko 1657 }
1407    
1408     /**
1409     * ccs_fetch_next_domain - Fetch next_domain from the list.
1410     *
1411 kumaneko 2282 * Returns pointer to "struct ccs_domain_info" which will be used if execve()
1412 kumaneko 1657 * succeeds. This function does not return NULL.
1413     */
1414 kumaneko 2282 struct ccs_domain_info *ccs_fetch_next_domain(void)
1415 kumaneko 1657 {
1416 kumaneko 2037 struct ccs_execve_entry *ee = ccs_find_execve_entry();
1417 kumaneko 2282 struct ccs_domain_info *next_domain = NULL;
1418 kumaneko 2037 if (ee)
1419 kumaneko 2690 next_domain = ee->r.domain;
1420 kumaneko 2037 if (!next_domain)
1421 kumaneko 2282 next_domain = ccs_current_domain();
1422 kumaneko 1657 return next_domain;
1423     }
1424    
1425     /**
1426 kumaneko 2037 * ccs_start_execve - Prepare for execve() operation.
1427 kumaneko 1052 *
1428     * @bprm: Pointer to "struct linux_binprm".
1429     *
1430 kumaneko 2037 * Returns 0 on success, negative value otherwise.
1431 kumaneko 1052 */
1432 kumaneko 2037 int ccs_start_execve(struct linux_binprm *bprm)
1433 kumaneko 115 {
1434 kumaneko 1657 int retval;
1435 kumaneko 1029 struct task_struct *task = current;
1436 kumaneko 2037 struct ccs_execve_entry *ee = ccs_allocate_execve_entry();
1437 kumaneko 2040 if (!ccs_policy_loaded)
1438 kumaneko 1657 ccs_load_policy(bprm->filename);
1439 kumaneko 2037 if (!ee)
1440 kumaneko 1052 return -ENOMEM;
1441 kumaneko 2282 ccs_init_request_info(&ee->r, NULL, CCS_MAC_FOR_FILE);
1442 kumaneko 2037 ee->r.ee = ee;
1443     ee->bprm = bprm;
1444     ee->r.obj = &ee->obj;
1445     ee->obj.path1_dentry = bprm->file->f_dentry;
1446     ee->obj.path1_vfsmnt = bprm->file->f_vfsmnt;
1447 kumaneko 1578 /* Clear manager flag. */
1448 kumaneko 2282 task->ccs_flags &= ~CCS_TASK_IS_POLICY_MANAGER;
1449 kumaneko 2037 if (ccs_find_execute_handler(ee, TYPE_EXECUTE_HANDLER)) {
1450     retval = ccs_try_alt_exec(ee);
1451 kumaneko 1052 if (!retval)
1452 kumaneko 2037 ccs_audit_execute_handler_log(ee, true);
1453 kumaneko 1052 goto ok;
1454 kumaneko 708 }
1455 kumaneko 2037 retval = ccs_find_next_domain(ee);
1456 kumaneko 1052 if (retval != -EPERM)
1457     goto ok;
1458 kumaneko 2037 if (ccs_find_execute_handler(ee, TYPE_DENIED_EXECUTE_HANDLER)) {
1459     retval = ccs_try_alt_exec(ee);
1460 kumaneko 1052 if (!retval)
1461 kumaneko 2037 ccs_audit_execute_handler_log(ee, false);
1462 kumaneko 1052 }
1463     ok:
1464 kumaneko 1561 if (retval < 0)
1465 kumaneko 1052 goto out;
1466 kumaneko 2690 ee->r.mode = ccs_check_flags(ee->r.domain, CCS_MAC_FOR_ENV);
1467 kumaneko 2037 retval = ccs_check_environ(ee);
1468 kumaneko 1561 if (retval < 0)
1469 kumaneko 1052 goto out;
1470 kumaneko 2282 task->ccs_flags |= CCS_CHECK_READ_FOR_OPEN_EXEC;
1471 kumaneko 2037 retval = 0;
1472     out:
1473 kumaneko 2048 if (retval)
1474     ccs_finish_execve(retval);
1475 kumaneko 2037 return retval;
1476     }
1477    
1478     /**
1479     * ccs_finish_execve - Clean up execve() operation.
1480 kumaneko 2076 *
1481     * @retval: Return code of an execve() operation.
1482 kumaneko 2690 *
1483 kumaneko 2828 * Caller holds ccs_read_lock().
1484 kumaneko 2037 */
1485     void ccs_finish_execve(int retval)
1486     {
1487     struct task_struct *task = current;
1488     struct ccs_execve_entry *ee = ccs_find_execve_entry();
1489 kumaneko 2828 ccs_check_read_lock();
1490 kumaneko 2282 task->ccs_flags &= ~CCS_CHECK_READ_FOR_OPEN_EXEC;
1491 kumaneko 2037 if (!ee)
1492     return;
1493 kumaneko 1052 if (retval < 0)
1494 kumaneko 1657 goto out;
1495     /* Proceed to next domain if execution suceeded. */
1496 kumaneko 2690 task->ccs_domain_info = ee->r.domain;
1497 kumaneko 1064 /* Mark the current process as execute handler. */
1498 kumaneko 2037 if (ee->handler)
1499 kumaneko 2282 task->ccs_flags |= CCS_TASK_IS_EXECUTE_HANDLER;
1500 kumaneko 1064 /* Mark the current process as normal process. */
1501     else
1502 kumaneko 2282 task->ccs_flags &= ~CCS_TASK_IS_EXECUTE_HANDLER;
1503 kumaneko 1657 out:
1504 kumaneko 2037 ccs_free_execve_entry(ee);
1505 kumaneko 115 }

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