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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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