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

Subversion リポジトリの参照

Annotation of /branches/ccs-patch/security/ccsecurity/domain.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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