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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2864 - (hide annotations) (download) (as text)
Fri Aug 7 06:40:37 2009 UTC (14 years, 9 months ago) by kumaneko
Original Path: branches/ccs-patch/security/ccsecurity/domain.c
File MIME type: text/x-csrc
File size: 39392 byte(s)


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

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