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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2932 - (hide annotations) (download) (as text)
Fri Aug 21 08:26:08 2009 UTC (14 years, 9 months ago) by kumaneko
Original Path: branches/ccs-patch/security/ccsecurity/domain.c
File MIME type: text/x-csrc
File size: 34576 byte(s)


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

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