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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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