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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3701 - (hide annotations) (download) (as text)
Fri May 28 12:44:01 2010 UTC (13 years, 11 months ago) by kumaneko
Original Path: branches/ccs-patch/security/ccsecurity/domain.c
File MIME type: text/x-csrc
File size: 35953 byte(s)


1 kumaneko 111 /*
2 kumaneko 2864 * security/ccsecurity/domain.c
3 kumaneko 111 *
4 kumaneko 3360 * Copyright (C) 2005-2010 NTT DATA CORPORATION
5 kumaneko 111 *
6 kumaneko 3701 * Version: 1.7.2+ 2010/05/27
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 /* Variables definitions.*/
26 kumaneko 111
27 kumaneko 3697 /* The global domain. */
28     struct ccs_domain_info ccs_global_domain;
29    
30 kumaneko 111 /* The initial domain. */
31 kumaneko 2282 struct ccs_domain_info ccs_kernel_domain;
32 kumaneko 111
33 kumaneko 2282 /* The list for "struct ccs_domain_info". */
34 kumaneko 2540 LIST_HEAD(ccs_domain_list);
35 kumaneko 708
36 kumaneko 3689 struct list_head ccs_policy_list[CCS_MAX_POLICY];
37     struct list_head ccs_group_list[CCS_MAX_GROUP];
38     struct list_head ccs_shared_list[CCS_MAX_LIST];
39    
40 kumaneko 1052 /**
41 kumaneko 2002 * ccs_audit_execute_handler_log - Audit execute_handler log.
42 kumaneko 1052 *
43 kumaneko 3693 * @ee: Pointer to "struct ccs_execve".
44 kumaneko 1052 *
45     * Returns 0 on success, negative value otherwise.
46     */
47 kumaneko 3693 static int ccs_audit_execute_handler_log(struct ccs_execve *ee)
48 kumaneko 1052 {
49 kumaneko 2037 struct ccs_request_info *r = &ee->r;
50     const char *handler = ee->handler->name;
51 kumaneko 3626 r->type = CCS_MAC_FILE_EXECUTE;
52 kumaneko 2943 r->mode = ccs_get_mode(r->profile, CCS_MAC_FILE_EXECUTE);
53 kumaneko 3701 r->granted = true;
54     return ccs_write_log(r, "%s %s\n", ee->handler_type ==
55 kumaneko 3694 CCS_TYPE_DENIED_EXECUTE_HANDLER ?
56     CCS_KEYWORD_DENIED_EXECUTE_HANDLER :
57     CCS_KEYWORD_EXECUTE_HANDLER, handler);
58 kumaneko 1052 }
59 kumaneko 111
60 kumaneko 1052 /**
61 kumaneko 2002 * ccs_audit_domain_creation_log - Audit domain creation log.
62 kumaneko 1052 *
63     * Returns 0 on success, negative value otherwise.
64     */
65 kumaneko 3627 static int ccs_audit_domain_creation_log(void)
66 kumaneko 1052 {
67 kumaneko 1657 struct ccs_request_info r;
68 kumaneko 3627 ccs_init_request_info(&r, CCS_MAC_FILE_EXECUTE);
69 kumaneko 3701 r.granted = false;
70     return ccs_write_log(&r, "use_profile %u\n", r.profile);
71 kumaneko 1052 }
72    
73 kumaneko 3689 int ccs_update_policy(struct ccs_acl_head *new_entry, const int size,
74     bool is_delete, const int idx, bool (*check_duplicate)
75     (const struct ccs_acl_head *,
76     const struct ccs_acl_head *))
77     {
78     int error = is_delete ? -ENOENT : -ENOMEM;
79     struct ccs_acl_head *entry;
80     if (mutex_lock_interruptible(&ccs_policy_lock))
81     return -ENOMEM;
82     list_for_each_entry_rcu(entry, &ccs_policy_list[idx], list) {
83     if (!check_duplicate(entry, new_entry))
84     continue;
85     entry->is_deleted = is_delete;
86     error = 0;
87     break;
88     }
89     if (error && !is_delete) {
90     entry = ccs_commit_ok(new_entry, size);
91     if (entry) {
92     list_add_tail_rcu(&entry->list, &ccs_policy_list[idx]);
93     error = 0;
94     }
95     }
96     mutex_unlock(&ccs_policy_lock);
97     return error;
98     }
99 kumaneko 111
100 kumaneko 3689 int ccs_update_group(struct ccs_acl_head *new_entry, const int size,
101     bool is_delete, struct ccs_group *group,
102     bool (*check_duplicate) (const struct ccs_acl_head *,
103     const struct ccs_acl_head *))
104     {
105     int error = is_delete ? -ENOENT : -ENOMEM;
106     struct ccs_acl_head *entry;
107     if (mutex_lock_interruptible(&ccs_policy_lock))
108     return -ENOMEM;
109     list_for_each_entry_rcu(entry, &group->member_list, list) {
110     if (!check_duplicate(entry, new_entry))
111     continue;
112     entry->is_deleted = is_delete;
113     error = 0;
114     break;
115     }
116     if (!is_delete && error) {
117     entry = ccs_commit_ok(new_entry, size);
118     if (entry) {
119     list_add_tail_rcu(&entry->list, &group->member_list);
120     error = 0;
121     }
122     }
123     mutex_unlock(&ccs_policy_lock);
124     return error;
125     }
126    
127 kumaneko 3697 static void ccs_delete_type(struct ccs_domain_info *domain, u8 type)
128     {
129     struct ccs_acl_info *ptr;
130     list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
131     if (ptr->type == type)
132     ptr->is_deleted = true;
133     }
134     }
135    
136 kumaneko 3693 int ccs_update_domain(struct ccs_acl_info *new_entry, const int size,
137     bool is_delete, struct ccs_domain_info *domain,
138     bool (*check_duplicate) (const struct ccs_acl_info *,
139     const struct ccs_acl_info *),
140     bool (*merge_duplicate) (struct ccs_acl_info *,
141     struct ccs_acl_info *,
142     const bool))
143 kumaneko 3689 {
144     int error = is_delete ? -ENOENT : -ENOMEM;
145     struct ccs_acl_info *entry;
146 kumaneko 3697 /*
147     * Only one "execute_handler" and "denied_execute_handler" can exist
148     * in a domain.
149     */
150     const u8 type = new_entry->type;
151     const bool exclusive = !is_delete &&
152     (type == CCS_TYPE_EXECUTE_HANDLER ||
153     type == CCS_TYPE_DENIED_EXECUTE_HANDLER);
154 kumaneko 3689 if (mutex_lock_interruptible(&ccs_policy_lock))
155     return error;
156     list_for_each_entry_rcu(entry, &domain->acl_info_list, list) {
157     if (!check_duplicate(entry, new_entry))
158     continue;
159 kumaneko 3697 if (exclusive)
160     ccs_delete_type(domain, type);
161 kumaneko 3689 if (merge_duplicate)
162     entry->is_deleted = merge_duplicate(entry, new_entry,
163     is_delete);
164     else
165     entry->is_deleted = is_delete;
166     error = 0;
167     break;
168     }
169     if (error && !is_delete) {
170     entry = ccs_commit_ok(new_entry, size);
171     if (entry) {
172 kumaneko 3697 if (exclusive)
173     ccs_delete_type(domain, type);
174 kumaneko 3689 ccs_add_domain_acl(domain, entry);
175     error = 0;
176     }
177     }
178     mutex_unlock(&ccs_policy_lock);
179     return error;
180     }
181    
182 kumaneko 3701 void ccs_check_acl(struct ccs_request_info *r,
183     bool (*check_entry) (const struct ccs_request_info *,
184     const struct ccs_acl_info *))
185     {
186     const struct ccs_domain_info *domain = ccs_current_domain();
187     struct ccs_acl_info *ptr;
188     retry:
189     list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
190     if (ptr->is_deleted || ptr->type != r->param_type)
191     continue;
192     if (check_entry(r, ptr) && ccs_condition(r, ptr->cond)) {
193     r->cond = ptr->cond;
194     r->granted = true;
195     return;
196     }
197     }
198     if (domain != &ccs_global_domain && !domain->ignore_global &&
199     (r->param_type != CCS_TYPE_PATH_ACL ||
200     r->param.path.operation != CCS_TYPE_READ ||
201     !domain->ignore_global_allow_read) &&
202     (r->param_type != CCS_TYPE_ENV_ACL ||
203     !domain->ignore_global_allow_env)) {
204     domain = &ccs_global_domain;
205     goto retry;
206     }
207     r->granted = false;
208     }
209    
210 kumaneko 3693 static bool ccs_same_domain_initializer_entry(const struct ccs_acl_head *a,
211 kumaneko 3695 const struct ccs_acl_head *b)
212 kumaneko 3689 {
213 kumaneko 3695 const struct ccs_domain_initializer *p1 = container_of(a, typeof(*p1),
214     head);
215     const struct ccs_domain_initializer *p2 = container_of(b, typeof(*p2),
216     head);
217 kumaneko 3689 return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
218     && p1->domainname == p2->domainname
219     && p1->program == p2->program;
220     }
221    
222 kumaneko 1052 /**
223 kumaneko 3693 * ccs_update_domain_initializer_entry - Update "struct ccs_domain_initializer" list.
224 kumaneko 1052 *
225     * @domainname: The name of domain. May be NULL.
226     * @program: The name of program.
227     * @is_not: True if it is "no_initialize_domain" entry.
228     * @is_delete: True if it is a delete request.
229     *
230     * Returns 0 on success, negative value otherwise.
231     */
232 kumaneko 2002 static int ccs_update_domain_initializer_entry(const char *domainname,
233     const char *program,
234     const bool is_not,
235     const bool is_delete)
236 kumaneko 111 {
237 kumaneko 3693 struct ccs_domain_initializer e = { .is_not = is_not };
238 kumaneko 2540 int error = is_delete ? -ENOENT : -ENOMEM;
239 kumaneko 3693 if (!ccs_correct_path(program, 1, -1, -1))
240 kumaneko 1052 return -EINVAL; /* No patterns allowed. */
241 kumaneko 111 if (domainname) {
242 kumaneko 3693 if (!ccs_domain_def(domainname) &&
243     ccs_correct_path(domainname, 1, -1, -1))
244 kumaneko 2900 e.is_last_name = true;
245 kumaneko 3693 else if (!ccs_correct_domain(domainname))
246 kumaneko 111 return -EINVAL;
247 kumaneko 2900 e.domainname = ccs_get_name(domainname);
248     if (!e.domainname)
249     goto out;
250 kumaneko 111 }
251 kumaneko 2900 e.program = ccs_get_name(program);
252     if (!e.program)
253     goto out;
254 kumaneko 3689 error = ccs_update_policy(&e.head, sizeof(e), is_delete,
255     CCS_ID_DOMAIN_INITIALIZER,
256 kumaneko 3693 ccs_same_domain_initializer_entry);
257 kumaneko 2900 out:
258     ccs_put_name(e.domainname);
259     ccs_put_name(e.program);
260 kumaneko 111 return error;
261     }
262    
263 kumaneko 1052 /**
264 kumaneko 3693 * ccs_write_domain_initializer - Write "struct ccs_domain_initializer" list.
265 kumaneko 1052 *
266     * @data: String to parse.
267     * @is_delete: True if it is a delete request.
268     *
269     * Returns 0 on success, negative value otherwise.
270     */
271 kumaneko 3693 int ccs_write_domain_initializer(char *data, const bool is_delete, const u8 flags)
272 kumaneko 111 {
273 kumaneko 3691 char *domainname = strstr(data, " from ");
274     if (domainname) {
275     *domainname = '\0';
276     domainname += 6;
277 kumaneko 111 }
278 kumaneko 3691 return ccs_update_domain_initializer_entry(domainname, data, flags,
279 kumaneko 2002 is_delete);
280 kumaneko 111 }
281    
282 kumaneko 1052 /**
283 kumaneko 3693 * ccs_domain_initializer - Check whether the given program causes domainname reinitialization.
284 kumaneko 1052 *
285     * @domainname: The name of domain.
286     * @program: The name of program.
287     * @last_name: The last component of @domainname.
288     *
289     * Returns true if executing @program reinitializes domain transition,
290     * false otherwise.
291 kumaneko 2690 *
292 kumaneko 2828 * Caller holds ccs_read_lock().
293 kumaneko 1052 */
294 kumaneko 3693 static bool ccs_domain_initializer(const struct ccs_path_info *domainname,
295 kumaneko 2002 const struct ccs_path_info *program,
296     const struct ccs_path_info *last_name)
297 kumaneko 111 {
298 kumaneko 3693 struct ccs_domain_initializer *ptr;
299 kumaneko 1016 bool flag = false;
300 kumaneko 3689 list_for_each_entry_rcu(ptr, &ccs_policy_list
301     [CCS_ID_DOMAIN_INITIALIZER], head.list) {
302     if (ptr->head.is_deleted)
303 kumaneko 1052 continue;
304 kumaneko 111 if (ptr->domainname) {
305     if (!ptr->is_last_name) {
306 kumaneko 1052 if (ptr->domainname != domainname)
307     continue;
308 kumaneko 111 } else {
309 kumaneko 1052 if (ccs_pathcmp(ptr->domainname, last_name))
310     continue;
311 kumaneko 111 }
312     }
313 kumaneko 1052 if (ccs_pathcmp(ptr->program, program))
314     continue;
315 kumaneko 2540 if (ptr->is_not) {
316     flag = false;
317     break;
318     }
319 kumaneko 1016 flag = true;
320 kumaneko 111 }
321     return flag;
322     }
323    
324 kumaneko 3693 static bool ccs_same_domain_keeper_entry(const struct ccs_acl_head *a,
325 kumaneko 3695 const struct ccs_acl_head *b)
326 kumaneko 3689 {
327 kumaneko 3695 const struct ccs_domain_keeper *p1 = container_of(a, typeof(*p1),
328     head);
329     const struct ccs_domain_keeper *p2 = container_of(b, typeof(*p2),
330     head);
331 kumaneko 3689 return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
332     && p1->domainname == p2->domainname
333     && p1->program == p2->program;
334     }
335 kumaneko 111
336 kumaneko 1052 /**
337 kumaneko 3693 * ccs_update_domain_keeper_entry - Update "struct ccs_domain_keeper" list.
338 kumaneko 1052 *
339     * @domainname: The name of domain.
340     * @program: The name of program. May be NULL.
341     * @is_not: True if it is "no_keep_domain" entry.
342     * @is_delete: True if it is a delete request.
343     *
344     * Returns 0 on success, negative value otherwise.
345     */
346 kumaneko 2002 static int ccs_update_domain_keeper_entry(const char *domainname,
347     const char *program,
348     const bool is_not,
349     const bool is_delete)
350 kumaneko 111 {
351 kumaneko 3693 struct ccs_domain_keeper e = { .is_not = is_not };
352 kumaneko 2540 int error = is_delete ? -ENOENT : -ENOMEM;
353 kumaneko 3693 if (!ccs_domain_def(domainname) &&
354     ccs_correct_path(domainname, 1, -1, -1))
355 kumaneko 2900 e.is_last_name = true;
356 kumaneko 3693 else if (!ccs_correct_domain(domainname))
357 kumaneko 111 return -EINVAL;
358     if (program) {
359 kumaneko 3693 if (!ccs_correct_path(program, 1, -1, -1))
360 kumaneko 1052 return -EINVAL;
361 kumaneko 2900 e.program = ccs_get_name(program);
362     if (!e.program)
363     goto out;
364 kumaneko 111 }
365 kumaneko 2900 e.domainname = ccs_get_name(domainname);
366     if (!e.domainname)
367     goto out;
368 kumaneko 3689 error = ccs_update_policy(&e.head, sizeof(e), is_delete,
369     CCS_ID_DOMAIN_KEEPER,
370 kumaneko 3693 ccs_same_domain_keeper_entry);
371 kumaneko 2900 out:
372     ccs_put_name(e.domainname);
373     ccs_put_name(e.program);
374 kumaneko 111 return error;
375     }
376    
377 kumaneko 1052 /**
378 kumaneko 3693 * ccs_write_domain_keeper - Write "struct ccs_domain_keeper" list.
379 kumaneko 1052 *
380     * @data: String to parse.
381     * @is_delete: True if it is a delete request.
382     *
383 kumaneko 3691 * Returns 0 on success, negative value otherwise.
384 kumaneko 1052 */
385 kumaneko 3693 int ccs_write_domain_keeper(char *data, const bool is_delete, const u8 flags)
386 kumaneko 111 {
387 kumaneko 3691 char *domainname = strstr(data, " from ");
388     if (domainname) {
389     *domainname = '\0';
390     domainname += 6;
391     } else {
392     domainname = data;
393     data = NULL;
394 kumaneko 111 }
395 kumaneko 3691 return ccs_update_domain_keeper_entry(domainname, data, flags,
396     is_delete);
397 kumaneko 111 }
398    
399 kumaneko 1052 /**
400 kumaneko 3693 * ccs_domain_keeper - Check whether the given program causes domain transition suppression.
401 kumaneko 1052 *
402     * @domainname: The name of domain.
403     * @program: The name of program.
404     * @last_name: The last component of @domainname.
405     *
406     * Returns true if executing @program supresses domain transition,
407     * false otherwise.
408 kumaneko 2690 *
409 kumaneko 2828 * Caller holds ccs_read_lock().
410 kumaneko 1052 */
411 kumaneko 3693 static bool ccs_domain_keeper(const struct ccs_path_info *domainname,
412 kumaneko 2002 const struct ccs_path_info *program,
413     const struct ccs_path_info *last_name)
414 kumaneko 111 {
415 kumaneko 3693 struct ccs_domain_keeper *ptr;
416 kumaneko 1016 bool flag = false;
417 kumaneko 3689 list_for_each_entry_rcu(ptr, &ccs_policy_list[CCS_ID_DOMAIN_KEEPER],
418     head.list) {
419     if (ptr->head.is_deleted)
420 kumaneko 1052 continue;
421 kumaneko 111 if (!ptr->is_last_name) {
422 kumaneko 1052 if (ptr->domainname != domainname)
423     continue;
424 kumaneko 111 } else {
425 kumaneko 1052 if (ccs_pathcmp(ptr->domainname, last_name))
426     continue;
427 kumaneko 111 }
428 kumaneko 1052 if (ptr->program && ccs_pathcmp(ptr->program, program))
429     continue;
430 kumaneko 2540 if (ptr->is_not) {
431     flag = false;
432     break;
433     }
434 kumaneko 1016 flag = true;
435 kumaneko 111 }
436     return flag;
437     }
438    
439 kumaneko 3693 static bool ccs_same_aggregator_entry(const struct ccs_acl_head *a,
440 kumaneko 3695 const struct ccs_acl_head *b)
441 kumaneko 3689 {
442 kumaneko 3695 const struct ccs_aggregator *p1 = container_of(a, typeof(*p1), head);
443     const struct ccs_aggregator *p2 = container_of(b, typeof(*p2), head);
444 kumaneko 3689 return p1->original_name == p2->original_name &&
445     p1->aggregated_name == p2->aggregated_name;
446     }
447 kumaneko 111
448 kumaneko 1052 /**
449 kumaneko 3693 * ccs_update_aggregator_entry - Update "struct ccs_aggregator" list.
450 kumaneko 1052 *
451     * @original_name: The original program's name.
452     * @aggregated_name: The aggregated program's name.
453     * @is_delete: True if it is a delete request.
454     *
455     * Returns 0 on success, negative value otherwise.
456     */
457 kumaneko 2002 static int ccs_update_aggregator_entry(const char *original_name,
458     const char *aggregated_name,
459     const bool is_delete)
460 kumaneko 111 {
461 kumaneko 3693 struct ccs_aggregator e = { };
462 kumaneko 2540 int error = is_delete ? -ENOENT : -ENOMEM;
463 kumaneko 3693 if (!ccs_correct_path(original_name, 1, 0, -1) ||
464     !ccs_correct_path(aggregated_name, 1, -1, -1))
465 kumaneko 1052 return -EINVAL;
466 kumaneko 2900 e.original_name = ccs_get_name(original_name);
467     e.aggregated_name = ccs_get_name(aggregated_name);
468     if (!e.original_name || !e.aggregated_name)
469     goto out;
470 kumaneko 3689 error = ccs_update_policy(&e.head, sizeof(e), is_delete,
471     CCS_ID_AGGREGATOR,
472 kumaneko 3693 ccs_same_aggregator_entry);
473 kumaneko 2900 out:
474     ccs_put_name(e.original_name);
475     ccs_put_name(e.aggregated_name);
476 kumaneko 111 return error;
477     }
478    
479 kumaneko 1052 /**
480 kumaneko 3693 * ccs_write_aggregator - Write "struct ccs_aggregator" list.
481 kumaneko 1052 *
482     * @data: String to parse.
483     * @is_delete: True if it is a delete request.
484     *
485     * Returns 0 on success, negative value otherwise.
486     */
487 kumaneko 3693 int ccs_write_aggregator(char *data, const bool is_delete, const u8 flags)
488 kumaneko 111 {
489 kumaneko 2779 char *w[2];
490     if (!ccs_tokenize(data, w, sizeof(w)) || !w[1][0])
491 kumaneko 2870 return -EINVAL;
492 kumaneko 2779 return ccs_update_aggregator_entry(w[0], w[1], is_delete);
493 kumaneko 111 }
494    
495 kumaneko 2393 /* Domain create/delete handler. */
496 kumaneko 111
497 kumaneko 1052 /**
498     * ccs_delete_domain - Delete a domain.
499     *
500     * @domainname: The name of domain.
501     *
502     * Returns 0.
503     */
504     int ccs_delete_domain(char *domainname)
505 kumaneko 111 {
506 kumaneko 2282 struct ccs_domain_info *domain;
507 kumaneko 2002 struct ccs_path_info name;
508 kumaneko 1052 name.name = domainname;
509     ccs_fill_path_info(&name);
510 kumaneko 3534 if (mutex_lock_interruptible(&ccs_policy_lock))
511     return 0;
512 kumaneko 111 /* Is there an active domain? */
513 kumaneko 2690 list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
514 kumaneko 2282 /* Never delete ccs_kernel_domain */
515     if (domain == &ccs_kernel_domain)
516 kumaneko 1052 continue;
517     if (domain->is_deleted ||
518     ccs_pathcmp(domain->domainname, &name))
519     continue;
520 kumaneko 2393 domain->is_deleted = true;
521 kumaneko 708 break;
522 kumaneko 111 }
523 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
524 kumaneko 111 return 0;
525     }
526    
527 kumaneko 1052 /**
528 kumaneko 3694 * ccs_assign_domain - Create a domain.
529 kumaneko 1052 *
530     * @domainname: The name of domain.
531     * @profile: Profile number to assign if the domain was newly created.
532     *
533 kumaneko 2690 * Returns pointer to "struct ccs_domain_info" on success, NULL otherwise.
534 kumaneko 1052 */
535 kumaneko 3694 struct ccs_domain_info *ccs_assign_domain(const char *domainname,
536     const u8 profile)
537 kumaneko 111 {
538 kumaneko 3697 struct ccs_domain_info e = { };
539     struct ccs_domain_info *entry = NULL;
540 kumaneko 2690 bool found = false;
541 kumaneko 2870
542 kumaneko 3693 if (!ccs_correct_domain(domainname))
543 kumaneko 2690 return NULL;
544 kumaneko 3697 e.profile = profile;
545     e.domainname = ccs_get_name(domainname);
546     if (!e.domainname)
547 kumaneko 2690 return NULL;
548 kumaneko 3534 if (mutex_lock_interruptible(&ccs_policy_lock))
549     goto out;
550 kumaneko 3697 list_for_each_entry_rcu(entry, &ccs_domain_list, list) {
551     if (entry->is_deleted ||
552     ccs_pathcmp(e.domainname, entry->domainname))
553 kumaneko 2544 continue;
554 kumaneko 2690 found = true;
555 kumaneko 2544 break;
556 kumaneko 111 }
557 kumaneko 3697 if (!found) {
558     entry = ccs_commit_ok(&e, sizeof(e));
559     if (entry) {
560     INIT_LIST_HEAD(&entry->acl_info_list);
561     list_add_tail_rcu(&entry->list, &ccs_domain_list);
562     found = true;
563     }
564 kumaneko 2544 }
565 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
566 kumaneko 3534 out:
567 kumaneko 3697 ccs_put_name(e.domainname);
568     return found ? entry : NULL;
569 kumaneko 111 }
570    
571 kumaneko 1052 /**
572 kumaneko 2002 * ccs_find_next_domain - Find a domain.
573 kumaneko 1052 *
574 kumaneko 3693 * @ee: Pointer to "struct ccs_execve".
575 kumaneko 1052 *
576     * Returns 0 on success, negative value otherwise.
577 kumaneko 2690 *
578 kumaneko 2828 * Caller holds ccs_read_lock().
579 kumaneko 1052 */
580 kumaneko 3693 static int ccs_find_next_domain(struct ccs_execve *ee)
581 kumaneko 115 {
582 kumaneko 2037 struct ccs_request_info *r = &ee->r;
583     const struct ccs_path_info *handler = ee->handler;
584 kumaneko 2691 struct ccs_domain_info *domain = NULL;
585 kumaneko 3627 struct ccs_domain_info * const old_domain = ccs_current_domain();
586     const char *old_domain_name = old_domain->domainname->name;
587 kumaneko 2037 struct linux_binprm *bprm = ee->bprm;
588 kumaneko 3627 struct task_struct *task = current;
589     const u32 ccs_flags = task->ccs_flags;
590 kumaneko 2932 struct ccs_path_info rn = { }; /* real name */
591 kumaneko 2002 struct ccs_path_info ln; /* last name */
592 kumaneko 111 int retval;
593 kumaneko 2932 bool need_kfree = false;
594 kumaneko 3627 bool domain_created = false;
595 kumaneko 2943 ln.name = ccs_last_word(old_domain_name);
596     ccs_fill_path_info(&ln);
597 kumaneko 1561 retry:
598 kumaneko 2282 current->ccs_flags = ccs_flags;
599 kumaneko 2690 r->cond = NULL;
600 kumaneko 2943 if (need_kfree) {
601     kfree(rn.name);
602     need_kfree = false;
603     }
604    
605 kumaneko 2738 /* Get symlink's pathname of program. */
606 kumaneko 2932 retval = ccs_symlink_path(bprm->filename, &rn);
607 kumaneko 2075 if (retval < 0)
608 kumaneko 1052 goto out;
609 kumaneko 2932 need_kfree = true;
610 kumaneko 111
611 kumaneko 1657 if (handler) {
612     if (ccs_pathcmp(&rn, handler)) {
613 kumaneko 1064 /* Failed to verify execute handler. */
614 kumaneko 1029 static u8 counter = 20;
615     if (counter) {
616     counter--;
617 kumaneko 1052 printk(KERN_WARNING "Failed to verify: %s\n",
618 kumaneko 1657 handler->name);
619 kumaneko 1029 }
620     goto out;
621     }
622 kumaneko 2943 } else {
623 kumaneko 3693 struct ccs_aggregator *ptr;
624 kumaneko 2943 /* Check 'aggregator' directive. */
625 kumaneko 3689 list_for_each_entry_rcu(ptr,
626     &ccs_policy_list[CCS_ID_AGGREGATOR],
627     head.list) {
628     if (ptr->head.is_deleted ||
629 kumaneko 1657 !ccs_path_matches_pattern(&rn, ptr->original_name))
630 kumaneko 1052 continue;
631 kumaneko 2932 kfree(rn.name);
632     need_kfree = false;
633 kumaneko 2943 /* This is OK because it is read only. */
634 kumaneko 2932 rn = *ptr->aggregated_name;
635 kumaneko 183 break;
636     }
637 kumaneko 2943
638     /* Check execute permission. */
639 kumaneko 3701 retval = ccs_path_permission(r, CCS_TYPE_EXECUTE, &rn);
640 kumaneko 3494 if (retval == CCS_RETRY_REQUEST)
641 kumaneko 2943 goto retry;
642     if (retval < 0)
643     goto out;
644 kumaneko 183 }
645    
646 kumaneko 2943 /* Calculate domain to transit to. */
647 kumaneko 3693 if (ccs_domain_initializer(old_domain->domainname, &rn, &ln)) {
648 kumaneko 2282 /* Transit to the child of ccs_kernel_domain domain. */
649 kumaneko 2932 snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, ROOT_NAME " " "%s",
650     rn.name);
651 kumaneko 3627 } else if (old_domain == &ccs_kernel_domain && !ccs_policy_loaded) {
652 kumaneko 111 /*
653 kumaneko 1052 * Needn't to transit from kernel domain before starting
654 kumaneko 1064 * /sbin/init. But transit from kernel domain if executing
655     * initializers because they might start before /sbin/init.
656 kumaneko 111 */
657 kumaneko 3627 domain = old_domain;
658 kumaneko 3693 } else if (ccs_domain_keeper(old_domain->domainname, &rn, &ln)) {
659 kumaneko 111 /* Keep current domain. */
660 kumaneko 3627 domain = old_domain;
661 kumaneko 111 } else {
662     /* Normal domain transition. */
663 kumaneko 2932 snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s %s",
664     old_domain_name, rn.name);
665 kumaneko 111 }
666 kumaneko 2932 if (domain || strlen(ee->tmp) >= CCS_EXEC_TMPSIZE - 10)
667 kumaneko 1052 goto done;
668 kumaneko 2932 domain = ccs_find_domain(ee->tmp);
669 kumaneko 2690 if (domain)
670 kumaneko 1052 goto done;
671 kumaneko 2958 if (r->mode == CCS_CONFIG_ENFORCING) {
672 kumaneko 2932 int error = ccs_supervisor(r, "# wants to create domain\n"
673     "%s\n", ee->tmp);
674 kumaneko 3494 if (error == CCS_RETRY_REQUEST)
675 kumaneko 1561 goto retry;
676     if (error < 0)
677 kumaneko 1052 goto done;
678 kumaneko 1561 }
679 kumaneko 3694 domain = ccs_assign_domain(ee->tmp, r->profile);
680 kumaneko 2690 if (domain)
681 kumaneko 3627 domain_created = true;
682 kumaneko 1052 done:
683 kumaneko 2691 if (!domain) {
684 kumaneko 3258 retval = (r->mode == CCS_CONFIG_ENFORCING) ? -EPERM : 0;
685 kumaneko 3627 if (!old_domain->domain_transition_failed) {
686     old_domain->domain_transition_failed = true;
687 kumaneko 3701 r->granted = false;
688     ccs_write_log(r, CCS_KEYWORD_TRANSITION_FAILED "\n");
689 kumaneko 3694 printk(KERN_WARNING
690     "ERROR: Domain '%s' not defined.\n", ee->tmp);
691 kumaneko 2691 }
692     } else {
693 kumaneko 111 retval = 0;
694     }
695 kumaneko 3627 if (!retval && handler)
696     ccs_audit_execute_handler_log(ee);
697     /*
698     * Tell GC that I started execve().
699     * Also, tell open_exec() to check read permission.
700     */
701     task->ccs_flags |= CCS_TASK_IS_IN_EXECVE;
702     /*
703     * Make task->ccs_flags visible to GC before changing
704     * task->ccs_domain_info .
705     */
706     smp_mb();
707     /*
708     * Proceed to the next domain in order to allow reaching via PID.
709     * It will be reverted if execve() failed. Reverting is not good.
710     * But it is better than being unable to reach via PID in interactive
711     * enforcing mode.
712     */
713     if (domain)
714     task->ccs_domain_info = domain;
715     if (domain_created)
716     ccs_audit_domain_creation_log();
717 kumaneko 1052 out:
718 kumaneko 2932 if (need_kfree)
719     kfree(rn.name);
720 kumaneko 111 return retval;
721     }
722    
723 kumaneko 1052 /**
724 kumaneko 2922 * ccs_environ - Check permission for environment variable names.
725 kumaneko 1052 *
726 kumaneko 3693 * @ee: Pointer to "struct ccs_execve".
727 kumaneko 1052 *
728     * Returns 0 on success, negative value otherwise.
729     */
730 kumaneko 3693 static int ccs_environ(struct ccs_execve *ee)
731 kumaneko 581 {
732 kumaneko 2037 struct ccs_request_info *r = &ee->r;
733     struct linux_binprm *bprm = ee->bprm;
734 kumaneko 3128 /* env_page->data is allocated by ccs_dump_page(). */
735     struct ccs_page_dump env_page = { };
736     char *arg_ptr; /* Size is CCS_EXEC_TMPSIZE bytes */
737 kumaneko 581 int arg_len = 0;
738     unsigned long pos = bprm->p;
739 kumaneko 1064 int offset = pos % PAGE_SIZE;
740 kumaneko 581 int argv_count = bprm->argc;
741     int envp_count = bprm->envc;
742 kumaneko 1052 /* printk(KERN_DEBUG "start %d %d\n", argv_count, envp_count); */
743 kumaneko 581 int error = -ENOMEM;
744 kumaneko 3627 ee->r.type = CCS_MAC_ENVIRON;
745     ee->r.mode = ccs_get_mode(ccs_current_domain()->profile,
746     CCS_MAC_ENVIRON);
747 kumaneko 1657 if (!r->mode || !envp_count)
748 kumaneko 1052 return 0;
749 kumaneko 3512 arg_ptr = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
750 kumaneko 3128 if (!arg_ptr)
751     goto out;
752 kumaneko 581 while (error == -ENOMEM) {
753 kumaneko 3128 if (!ccs_dump_page(bprm, pos, &env_page))
754 kumaneko 1052 goto out;
755 kumaneko 986 pos += PAGE_SIZE - offset;
756 kumaneko 581 /* Read. */
757     while (argv_count && offset < PAGE_SIZE) {
758 kumaneko 3128 if (!env_page.data[offset++])
759 kumaneko 1052 argv_count--;
760 kumaneko 581 }
761 kumaneko 2037 if (argv_count) {
762     offset = 0;
763     continue;
764     }
765 kumaneko 581 while (offset < PAGE_SIZE) {
766 kumaneko 3128 const unsigned char c = env_page.data[offset++];
767 kumaneko 2932 if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {
768 kumaneko 581 if (c == '=') {
769     arg_ptr[arg_len++] = '\0';
770     } else if (c == '\\') {
771     arg_ptr[arg_len++] = '\\';
772     arg_ptr[arg_len++] = '\\';
773     } else if (c > ' ' && c < 127) {
774     arg_ptr[arg_len++] = c;
775     } else {
776     arg_ptr[arg_len++] = '\\';
777     arg_ptr[arg_len++] = (c >> 6) + '0';
778 kumaneko 1052 arg_ptr[arg_len++]
779     = ((c >> 3) & 7) + '0';
780 kumaneko 581 arg_ptr[arg_len++] = (c & 7) + '0';
781     }
782     } else {
783     arg_ptr[arg_len] = '\0';
784     }
785 kumaneko 1052 if (c)
786     continue;
787 kumaneko 2922 if (ccs_env_perm(r, arg_ptr)) {
788 kumaneko 581 error = -EPERM;
789     break;
790     }
791     if (!--envp_count) {
792     error = 0;
793     break;
794     }
795     arg_len = 0;
796     }
797     offset = 0;
798     }
799     out:
800 kumaneko 1657 if (r->mode != 3)
801 kumaneko 1052 error = 0;
802 kumaneko 3128 kfree(env_page.data);
803 kumaneko 3272 kfree(arg_ptr);
804 kumaneko 581 return error;
805     }
806 kumaneko 111
807 kumaneko 1052 /**
808 kumaneko 2002 * ccs_unescape - Unescape escaped string.
809 kumaneko 1052 *
810 kumaneko 2075 * @dest: String to unescape.
811 kumaneko 1052 *
812     * Returns nothing.
813     */
814 kumaneko 2002 static void ccs_unescape(unsigned char *dest)
815 kumaneko 708 {
816     unsigned char *src = dest;
817 kumaneko 1064 unsigned char c;
818     unsigned char d;
819     unsigned char e;
820 kumaneko 1747 while (1) {
821     c = *src++;
822     if (!c)
823     break;
824 kumaneko 708 if (c != '\\') {
825     *dest++ = c;
826     continue;
827     }
828     c = *src++;
829     if (c == '\\') {
830     *dest++ = c;
831 kumaneko 1052 continue;
832     }
833     if (c < '0' || c > '3')
834 kumaneko 708 break;
835 kumaneko 1052 d = *src++;
836     if (d < '0' || d > '7')
837     break;
838     e = *src++;
839     if (e < '0' || e > '7')
840     break;
841     *dest++ = ((c - '0') << 6) + ((d - '0') << 3) + (e - '0');
842 kumaneko 708 }
843     *dest = '\0';
844     }
845    
846 kumaneko 1052 /**
847 kumaneko 2002 * ccs_root_depth - Get number of directories to strip.
848 kumaneko 1052 *
849     * @dentry: Pointer to "struct dentry".
850     * @vfsmnt: Pointer to "struct vfsmount".
851     *
852     * Returns number of directories to strip.
853 kumaneko 1029 */
854 kumaneko 3625 static int ccs_root_depth(struct dentry *dentry, struct vfsmount *vfsmnt)
855 kumaneko 708 {
856 kumaneko 1029 int depth = 0;
857 kumaneko 1474 ccs_realpath_lock();
858 kumaneko 1029 for (;;) {
859     if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
860     /* Global root? */
861 kumaneko 1052 if (vfsmnt->mnt_parent == vfsmnt)
862     break;
863 kumaneko 1029 dentry = vfsmnt->mnt_mountpoint;
864     vfsmnt = vfsmnt->mnt_parent;
865     continue;
866     }
867     dentry = dentry->d_parent;
868     depth++;
869     }
870 kumaneko 1474 ccs_realpath_unlock();
871 kumaneko 1052 return depth;
872     }
873    
874     /**
875 kumaneko 2002 * ccs_get_root_depth - return the depth of root directory.
876 kumaneko 1052 *
877     * Returns number of directories to strip.
878     */
879 kumaneko 2002 static int ccs_get_root_depth(void)
880 kumaneko 1052 {
881     int depth;
882     struct dentry *dentry;
883     struct vfsmount *vfsmnt;
884     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
885     struct path root;
886     #endif
887     read_lock(&current->fs->lock);
888     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
889     root = current->fs->root;
890     path_get(&current->fs->root);
891     dentry = root.dentry;
892     vfsmnt = root.mnt;
893     #else
894     dentry = dget(current->fs->root);
895     vfsmnt = mntget(current->fs->rootmnt);
896     #endif
897     read_unlock(&current->fs->lock);
898 kumaneko 2002 depth = ccs_root_depth(dentry, vfsmnt);
899 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
900 kumaneko 1029 path_put(&root);
901     #else
902 kumaneko 1052 dput(dentry);
903     mntput(vfsmnt);
904 kumaneko 1029 #endif
905     return depth;
906     }
907    
908 kumaneko 1052 /**
909 kumaneko 2002 * ccs_try_alt_exec - Try to start execute handler.
910 kumaneko 1052 *
911 kumaneko 3693 * @ee: Pointer to "struct ccs_execve".
912 kumaneko 1052 *
913     * Returns 0 on success, negative value otherwise.
914     */
915 kumaneko 3693 static int ccs_try_alt_exec(struct ccs_execve *ee)
916 kumaneko 1029 {
917 kumaneko 1005 /*
918     * Contents of modified bprm.
919     * The envp[] in original bprm is moved to argv[] so that
920     * the alternatively executed program won't be affected by
921 kumaneko 1064 * some dangerous environment variables like LD_PRELOAD.
922 kumaneko 1005 *
923     * modified bprm->argc
924     * = original bprm->argc + original bprm->envc + 7
925     * modified bprm->envc
926     * = 0
927     *
928     * modified bprm->argv[0]
929 kumaneko 1029 * = the program's name specified by execute_handler
930 kumaneko 1005 * modified bprm->argv[1]
931 kumaneko 2282 * = ccs_current_domain()->domainname->name
932 kumaneko 1005 * modified bprm->argv[2]
933     * = the current process's name
934     * modified bprm->argv[3]
935     * = the current process's information (e.g. uid/gid).
936     * modified bprm->argv[4]
937     * = original bprm->filename
938     * modified bprm->argv[5]
939     * = original bprm->argc in string expression
940     * modified bprm->argv[6]
941     * = original bprm->envc in string expression
942     * modified bprm->argv[7]
943     * = original bprm->argv[0]
944     * ...
945     * modified bprm->argv[bprm->argc + 6]
946     * = original bprm->argv[bprm->argc - 1]
947     * modified bprm->argv[bprm->argc + 7]
948     * = original bprm->envp[0]
949     * ...
950     * modified bprm->argv[bprm->envc + bprm->argc + 6]
951     * = original bprm->envp[bprm->envc - 1]
952     */
953 kumaneko 2037 struct linux_binprm *bprm = ee->bprm;
954 kumaneko 708 struct file *filp;
955     int retval;
956 kumaneko 1005 const int original_argc = bprm->argc;
957     const int original_envc = bprm->envc;
958     struct task_struct *task = current;
959 kumaneko 1032
960 kumaneko 1029 /* Close the requested program's dentry. */
961 kumaneko 3064 ee->obj.path1.dentry = NULL;
962     ee->obj.path1.mnt = NULL;
963     ee->obj.validate_done = false;
964 kumaneko 708 allow_write_access(bprm->file);
965     fput(bprm->file);
966     bprm->file = NULL;
967 kumaneko 1005
968 kumaneko 2037 /* Invalidate page dump cache. */
969     ee->dump.page = NULL;
970 kumaneko 1029
971 kumaneko 1005 /* Move envp[] to argv[] */
972     bprm->argc += bprm->envc;
973     bprm->envc = 0;
974    
975     /* Set argv[6] */
976     {
977 kumaneko 2037 char *cp = ee->tmp;
978     snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%d", original_envc);
979     retval = copy_strings_kernel(1, &cp, bprm);
980 kumaneko 1052 if (retval < 0)
981     goto out;
982 kumaneko 1005 bprm->argc++;
983     }
984    
985     /* Set argv[5] */
986     {
987 kumaneko 2037 char *cp = ee->tmp;
988     snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%d", original_argc);
989     retval = copy_strings_kernel(1, &cp, bprm);
990 kumaneko 1052 if (retval < 0)
991     goto out;
992 kumaneko 1005 bprm->argc++;
993     }
994    
995     /* Set argv[4] */
996     {
997 kumaneko 2075 retval = copy_strings_kernel(1, &bprm->filename, bprm);
998 kumaneko 1052 if (retval < 0)
999     goto out;
1000 kumaneko 1005 bprm->argc++;
1001     }
1002    
1003     /* Set argv[3] */
1004     {
1005 kumaneko 2037 char *cp = ee->tmp;
1006 kumaneko 2282 const u32 ccs_flags = task->ccs_flags;
1007 kumaneko 2037 snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1,
1008 kumaneko 1052 "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "
1009     "sgid=%d fsuid=%d fsgid=%d state[0]=%u "
1010     "state[1]=%u state[2]=%u",
1011 kumaneko 3502 (pid_t) ccsecurity_exports.sys_getpid(),
1012     current_uid(), current_gid(), current_euid(),
1013     current_egid(), current_suid(), current_sgid(),
1014     current_fsuid(), current_fsgid(),
1015 kumaneko 2282 (u8) (ccs_flags >> 24), (u8) (ccs_flags >> 16),
1016     (u8) (ccs_flags >> 8));
1017 kumaneko 2037 retval = copy_strings_kernel(1, &cp, bprm);
1018 kumaneko 1052 if (retval < 0)
1019     goto out;
1020 kumaneko 1005 bprm->argc++;
1021     }
1022    
1023     /* Set argv[2] */
1024     {
1025 kumaneko 1052 char *exe = (char *) ccs_get_exe();
1026 kumaneko 1005 if (exe) {
1027     retval = copy_strings_kernel(1, &exe, bprm);
1028 kumaneko 2711 kfree(exe);
1029 kumaneko 1005 } else {
1030 kumaneko 2037 exe = ee->tmp;
1031 kumaneko 2932 snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "<unknown>");
1032 kumaneko 2037 retval = copy_strings_kernel(1, &exe, bprm);
1033 kumaneko 1005 }
1034 kumaneko 1052 if (retval < 0)
1035     goto out;
1036 kumaneko 1005 bprm->argc++;
1037     }
1038    
1039     /* Set argv[1] */
1040     {
1041 kumaneko 2037 char *cp = ee->tmp;
1042 kumaneko 2932 snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s",
1043     ccs_current_domain()->domainname->name);
1044 kumaneko 2037 retval = copy_strings_kernel(1, &cp, bprm);
1045 kumaneko 1052 if (retval < 0)
1046     goto out;
1047 kumaneko 1005 bprm->argc++;
1048     }
1049    
1050     /* Set argv[0] */
1051     {
1052 kumaneko 2037 int depth = ccs_get_root_depth();
1053 kumaneko 2932 int len = ee->handler->total_len + 1;
1054 kumaneko 3512 char *cp = kmalloc(len, CCS_GFP_FLAGS);
1055 kumaneko 2932 if (!cp) {
1056 kumaneko 2998 retval = -ENOMEM;
1057 kumaneko 2932 goto out;
1058     }
1059     ee->handler_path = cp;
1060     memmove(cp, ee->handler->name, len);
1061 kumaneko 2037 ccs_unescape(cp);
1062     retval = -ENOENT;
1063     if (!*cp || *cp != '/')
1064     goto out;
1065     /* Adjust root directory for open_exec(). */
1066     while (depth) {
1067     cp = strchr(cp + 1, '/');
1068     if (!cp)
1069     goto out;
1070     depth--;
1071     }
1072 kumaneko 2932 memmove(ee->handler_path, cp, strlen(cp) + 1);
1073     cp = ee->handler_path;
1074 kumaneko 2037 retval = copy_strings_kernel(1, &cp, bprm);
1075 kumaneko 1052 if (retval < 0)
1076     goto out;
1077 kumaneko 1005 bprm->argc++;
1078     }
1079 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
1080     #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
1081 kumaneko 1007 bprm->argv_len = bprm->exec - bprm->p;
1082     #endif
1083 kumaneko 1052 #endif
1084 kumaneko 1005
1085 kumaneko 3625 /*
1086     * OK, now restart the process with execute handler program's dentry.
1087     */
1088 kumaneko 2932 filp = open_exec(ee->handler_path);
1089 kumaneko 1005 if (IS_ERR(filp)) {
1090     retval = PTR_ERR(filp);
1091     goto out;
1092     }
1093 kumaneko 3064 ee->obj.path1.dentry = filp->f_dentry;
1094     ee->obj.path1.mnt = filp->f_vfsmnt;
1095 kumaneko 1052 bprm->file = filp;
1096 kumaneko 2932 bprm->filename = ee->handler_path;
1097 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
1098 kumaneko 2076 bprm->interp = bprm->filename;
1099 kumaneko 708 #endif
1100 kumaneko 1029 retval = prepare_binprm(bprm);
1101 kumaneko 1052 if (retval < 0)
1102     goto out;
1103 kumaneko 2932 task->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1104     retval = ccs_find_next_domain(ee);
1105     task->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1106 kumaneko 1005 out:
1107     return retval;
1108 kumaneko 708 }
1109 kumaneko 581
1110 kumaneko 1052 /**
1111 kumaneko 2002 * ccs_find_execute_handler - Find an execute handler.
1112 kumaneko 1052 *
1113 kumaneko 3693 * @ee: Pointer to "struct ccs_execve".
1114 kumaneko 1052 * @type: Type of execute handler.
1115     *
1116 kumaneko 2075 * Returns true if found, false otherwise.
1117 kumaneko 2690 *
1118 kumaneko 2828 * Caller holds ccs_read_lock().
1119 kumaneko 1052 */
1120 kumaneko 3697 static bool ccs_find_execute_handler(struct ccs_execve *ee, const u8 type)
1121 kumaneko 1029 {
1122 kumaneko 1064 struct task_struct *task = current;
1123 kumaneko 3627 const struct ccs_domain_info * const domain = ccs_current_domain();
1124 kumaneko 2002 struct ccs_acl_info *ptr;
1125 kumaneko 2540 bool found = false;
1126 kumaneko 1064 /*
1127     * Don't use execute handler if the current process is
1128     * marked as execute handler to avoid infinite execute handler loop.
1129     */
1130 kumaneko 2282 if (task->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)
1131 kumaneko 2037 return false;
1132 kumaneko 3697 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
1133     struct ccs_execute_handler *acl;
1134 kumaneko 1058 if (ptr->type != type)
1135 kumaneko 1052 continue;
1136 kumaneko 3697 acl = container_of(ptr, struct ccs_execute_handler, head);
1137 kumaneko 2037 ee->handler = acl->handler;
1138 kumaneko 3627 ee->handler_type = type;
1139 kumaneko 2540 found = true;
1140     break;
1141 kumaneko 1029 }
1142 kumaneko 2540 return found;
1143 kumaneko 1029 }
1144    
1145 kumaneko 1052 /**
1146 kumaneko 2037 * ccs_dump_page - Dump a page to buffer.
1147 kumaneko 1657 *
1148 kumaneko 2037 * @bprm: Pointer to "struct linux_binprm".
1149     * @pos: Location to dump.
1150     * @dump: Poiner to "struct ccs_page_dump".
1151 kumaneko 1657 *
1152 kumaneko 2037 * Returns true on success, false otherwise.
1153 kumaneko 1657 */
1154 kumaneko 2037 bool ccs_dump_page(struct linux_binprm *bprm, unsigned long pos,
1155     struct ccs_page_dump *dump)
1156 kumaneko 1657 {
1157 kumaneko 2037 struct page *page;
1158 kumaneko 3056 /* dump->data is released by ccs_finish_execve(). */
1159 kumaneko 2037 if (!dump->data) {
1160 kumaneko 3512 dump->data = kzalloc(PAGE_SIZE, CCS_GFP_FLAGS);
1161 kumaneko 2037 if (!dump->data)
1162     return false;
1163     }
1164     /* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */
1165     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
1166     if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
1167     return false;
1168 kumaneko 2996 #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 3 && defined(CONFIG_MMU)
1169 kumaneko 2346 if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
1170     return false;
1171 kumaneko 3018 #elif defined(AX_MAJOR) && AX_MAJOR == 3 && defined(AX_MINOR) && AX_MINOR >= 2 && defined(CONFIG_MMU)
1172     if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
1173     return false;
1174 kumaneko 2037 #else
1175     page = bprm->page[pos / PAGE_SIZE];
1176     #endif
1177     if (page != dump->page) {
1178     const unsigned int offset = pos % PAGE_SIZE;
1179     /*
1180     * Maybe kmap()/kunmap() should be used here.
1181     * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic().
1182     * So do I.
1183     */
1184     char *kaddr = kmap_atomic(page, KM_USER0);
1185     dump->page = page;
1186 kumaneko 3625 memcpy(dump->data + offset, kaddr + offset,
1187     PAGE_SIZE - offset);
1188 kumaneko 2037 kunmap_atomic(kaddr, KM_USER0);
1189     }
1190     /* Same with put_arg_page(page) in fs/exec.c */
1191     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
1192     put_page(page);
1193 kumaneko 2996 #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 3 && defined(CONFIG_MMU)
1194 kumaneko 2346 put_page(page);
1195 kumaneko 3018 #elif defined(AX_MAJOR) && AX_MAJOR == 3 && defined(AX_MINOR) && AX_MINOR >= 2 && defined(CONFIG_MMU)
1196     put_page(page);
1197 kumaneko 2037 #endif
1198     return true;
1199 kumaneko 1657 }
1200    
1201     /**
1202 kumaneko 2037 * ccs_start_execve - Prepare for execve() operation.
1203 kumaneko 1052 *
1204     * @bprm: Pointer to "struct linux_binprm".
1205 kumaneko 3693 * @eep: Pointer to "struct ccs_execve *".
1206 kumaneko 1052 *
1207 kumaneko 2037 * Returns 0 on success, negative value otherwise.
1208 kumaneko 1052 */
1209 kumaneko 3502 static int ccs_start_execve(struct linux_binprm *bprm,
1210 kumaneko 3693 struct ccs_execve **eep)
1211 kumaneko 115 {
1212 kumaneko 1657 int retval;
1213 kumaneko 1029 struct task_struct *task = current;
1214 kumaneko 3693 struct ccs_execve *ee;
1215 kumaneko 3056 *eep = NULL;
1216 kumaneko 3512 ee = kzalloc(sizeof(*ee), CCS_GFP_FLAGS);
1217 kumaneko 2037 if (!ee)
1218 kumaneko 1052 return -ENOMEM;
1219 kumaneko 3512 ee->tmp = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
1220 kumaneko 3056 if (!ee->tmp) {
1221     kfree(ee);
1222     return -ENOMEM;
1223     }
1224     ee->reader_idx = ccs_read_lock();
1225     /* ee->dump->data is allocated by ccs_dump_page(). */
1226     ee->previous_domain = task->ccs_domain_info;
1227     /* Clear manager flag. */
1228 kumaneko 3693 task->ccs_flags &= ~CCS_TASK_IS_MANAGER;
1229 kumaneko 3056 *eep = ee;
1230 kumaneko 3627 ccs_init_request_info(&ee->r, CCS_MAC_FILE_EXECUTE);
1231 kumaneko 2037 ee->r.ee = ee;
1232     ee->bprm = bprm;
1233     ee->r.obj = &ee->obj;
1234 kumaneko 2915 ee->obj.path1.dentry = bprm->file->f_dentry;
1235     ee->obj.path1.mnt = bprm->file->f_vfsmnt;
1236 kumaneko 3627 /*
1237     * No need to call ccs_environ() for execute handler because envp[] is
1238     * moved to argv[].
1239     */
1240     if (ccs_find_execute_handler(ee, CCS_TYPE_EXECUTE_HANDLER))
1241     return ccs_try_alt_exec(ee);
1242 kumaneko 2037 retval = ccs_find_next_domain(ee);
1243 kumaneko 3627 if (retval == -EPERM) {
1244     if (ccs_find_execute_handler(ee,
1245     CCS_TYPE_DENIED_EXECUTE_HANDLER))
1246     return ccs_try_alt_exec(ee);
1247 kumaneko 1052 }
1248 kumaneko 3627 if (!retval)
1249     retval = ccs_environ(ee);
1250 kumaneko 2037 return retval;
1251     }
1252    
1253     /**
1254     * ccs_finish_execve - Clean up execve() operation.
1255 kumaneko 2076 *
1256     * @retval: Return code of an execve() operation.
1257 kumaneko 3693 * @ee: Pointer to "struct ccs_execve".
1258 kumaneko 2690 *
1259 kumaneko 2828 * Caller holds ccs_read_lock().
1260 kumaneko 2037 */
1261 kumaneko 3693 static void ccs_finish_execve(int retval, struct ccs_execve *ee)
1262 kumaneko 2037 {
1263     struct task_struct *task = current;
1264     if (!ee)
1265     return;
1266 kumaneko 2968 if (retval < 0) {
1267     task->ccs_domain_info = ee->previous_domain;
1268 kumaneko 3056 /*
1269     * Make task->ccs_domain_info visible to GC before changing
1270     * task->ccs_flags .
1271     */
1272     smp_mb();
1273     } else {
1274     /* Mark the current process as execute handler. */
1275     if (ee->handler)
1276     task->ccs_flags |= CCS_TASK_IS_EXECUTE_HANDLER;
1277     /* Mark the current process as normal process. */
1278     else
1279     task->ccs_flags &= ~CCS_TASK_IS_EXECUTE_HANDLER;
1280 kumaneko 2968 }
1281 kumaneko 3056 /* Tell GC that I finished execve(). */
1282     task->ccs_flags &= ~CCS_TASK_IS_IN_EXECVE;
1283     ccs_read_unlock(ee->reader_idx);
1284     kfree(ee->handler_path);
1285     kfree(ee->tmp);
1286     kfree(ee->dump.data);
1287     kfree(ee);
1288 kumaneko 115 }
1289 kumaneko 3484
1290     /**
1291     * ccs_may_transit - Check permission and do domain transition without execve().
1292     *
1293     * @domainname: Domainname to transit to.
1294     * @pathname: Pathname to check.
1295     *
1296     * Returns 0 on success, negative value otherwise.
1297     *
1298     * Caller holds ccs_read_lock().
1299     */
1300 kumaneko 3512 int ccs_may_transit(const char *domainname, const char *pathname)
1301     {
1302 kumaneko 3484 struct ccs_path_info name;
1303     struct ccs_request_info r;
1304     struct ccs_domain_info *domain;
1305     int error;
1306 kumaneko 3627 bool domain_created = false;
1307 kumaneko 3484 name.name = pathname;
1308     ccs_fill_path_info(&name);
1309     /* Check allow_transit permission. */
1310 kumaneko 3627 ccs_init_request_info(&r, CCS_MAC_FILE_TRANSIT);
1311 kumaneko 3484 error = ccs_path_permission(&r, CCS_TYPE_TRANSIT, &name);
1312     if (error)
1313     return error;
1314     /* Check destination domain. */
1315     domain = ccs_find_domain(domainname);
1316     if (!domain && r.mode != CCS_CONFIG_ENFORCING &&
1317     strlen(domainname) < CCS_EXEC_TMPSIZE - 10) {
1318 kumaneko 3694 domain = ccs_assign_domain(domainname, r.profile);
1319 kumaneko 3484 if (domain)
1320 kumaneko 3627 domain_created = true;
1321 kumaneko 3484 }
1322     if (domain) {
1323     error = 0;
1324     current->ccs_domain_info = domain;
1325 kumaneko 3627 if (domain_created)
1326     ccs_audit_domain_creation_log();
1327 kumaneko 3484 } else {
1328     error = -ENOENT;
1329     }
1330     return error;
1331     }
1332 kumaneko 3502
1333     static int __ccs_search_binary_handler(struct linux_binprm *bprm,
1334     struct pt_regs *regs)
1335     {
1336 kumaneko 3693 struct ccs_execve *ee;
1337 kumaneko 3502 int retval;
1338     if (!ccs_policy_loaded)
1339     ccsecurity_exports.load_policy(bprm->filename);
1340     retval = ccs_start_execve(bprm, &ee);
1341     if (!retval)
1342     retval = search_binary_handler(bprm, regs);
1343     ccs_finish_execve(retval, ee);
1344     return retval;
1345     }
1346    
1347     void __init ccs_domain_init(void)
1348     {
1349     ccsecurity_ops.search_binary_handler = __ccs_search_binary_handler;
1350     }

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