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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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