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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2893 - (hide annotations) (download) (as text)
Tue Aug 11 04:11:19 2009 UTC (14 years, 9 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 59203 byte(s)


1 kumaneko 2863 /*
2 kumaneko 2864 * security/ccsecurity/policy_io.c
3 kumaneko 2863 *
4     * Copyright (C) 2005-2009 NTT DATA CORPORATION
5     *
6 kumaneko 2869 * Version: 1.7.0-pre 2009/08/08
7 kumaneko 2863 *
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     #include "internal.h"
14    
15     /* Lock for protecting ccs_profile->comment */
16     static DEFINE_SPINLOCK(ccs_profile_comment_lock);
17    
18     static bool ccs_profile_entry_used[CCS_MAX_CONTROL_INDEX +
19     CCS_MAX_CAPABILITY_INDEX + 1];
20    
21     /* String table for functionality that takes 4 modes. */
22     static const char *ccs_mode_4[4] = {
23     "disabled", "learning", "permissive", "enforcing"
24     };
25     /* String table for functionality that takes 2 modes. */
26     static const char *ccs_mode_2[4] = {
27     "disabled", "enabled", "enabled", "enabled"
28     };
29    
30     /* Table for profile. */
31     static struct {
32     const char *keyword;
33     unsigned int current_value;
34     const unsigned int max_value;
35     } ccs_control_array[CCS_MAX_CONTROL_INDEX] = {
36     [CCS_MAC_FOR_FILE] = { "MAC_FOR_FILE", 0, 3 },
37 kumaneko 2893 [CCS_AUTOLEARN_EXEC_REALPATH] = { "AUTOLEARN_EXEC_REALPATH", 0, 1 },
38     [CCS_AUTOLEARN_EXEC_ARGV0] = { "AUTOLEARN_EXEC_ARGV0", 0, 1 },
39 kumaneko 2863 [CCS_MAC_FOR_IOCTL] = { "MAC_FOR_IOCTL", 0, 3 },
40 kumaneko 2871 [CCS_MAC_FOR_FILEATTR] = { "MAC_FOR_FILEATTR", 0, 3 },
41 kumaneko 2863 [CCS_MAC_FOR_ENV] = { "MAC_FOR_ENV", 0, 3 },
42     [CCS_MAC_FOR_NETWORK] = { "MAC_FOR_NETWORK", 0, 3 },
43     [CCS_MAC_FOR_SIGNAL] = { "MAC_FOR_SIGNAL", 0, 3 },
44     [CCS_MAC_FOR_NAMESPACE] = { "MAC_FOR_NAMESPACE", 0, 3 },
45     [CCS_RESTRICT_AUTOBIND] = { "RESTRICT_AUTOBIND", 0, 1 },
46     [CCS_MAX_ACCEPT_ENTRY]
47     = { "MAX_ACCEPT_ENTRY", CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY, INT_MAX },
48     #ifdef CONFIG_CCSECURITY_AUDIT
49     [CCS_MAX_GRANT_LOG]
50     = { "MAX_GRANT_LOG", CONFIG_CCSECURITY_MAX_GRANT_LOG, INT_MAX },
51     [CCS_MAX_REJECT_LOG]
52     = { "MAX_REJECT_LOG", CONFIG_CCSECURITY_MAX_REJECT_LOG, INT_MAX },
53     #endif
54     [CCS_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 },
55     [CCS_SLEEP_PERIOD]
56     = { "SLEEP_PERIOD", 0, 3000 }, /* in 0.1 second */
57     };
58    
59     /* Permit policy management by non-root user? */
60     static bool ccs_manage_by_non_root;
61    
62     /**
63     * ccs_quiet_setup - Set CCS_VERBOSE=0 by default.
64     *
65     * @str: Unused.
66     *
67     * Returns 0.
68     */
69     static int __init ccs_quiet_setup(char *str)
70     {
71     ccs_control_array[CCS_VERBOSE].current_value = 0;
72     return 0;
73     }
74    
75     __setup("CCS_QUIET", ccs_quiet_setup);
76    
77     /**
78     * ccs_io_printf - Transactional printf() to "struct ccs_io_buffer" structure.
79     *
80     * @head: Pointer to "struct ccs_io_buffer".
81     * @fmt: The printf()'s format string, followed by parameters.
82     *
83     * Returns true on success, false otherwise.
84     *
85     * The snprintf() will truncate, but ccs_io_printf() won't.
86     */
87     bool ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
88     {
89     va_list args;
90     int len;
91     int pos = head->read_avail;
92     int size = head->readbuf_size - pos;
93     if (size <= 0)
94     return false;
95     va_start(args, fmt);
96     len = vsnprintf(head->read_buf + pos, size, fmt, args);
97     va_end(args);
98     if (pos + len >= head->readbuf_size)
99     return false;
100     head->read_avail += len;
101     return true;
102     }
103    
104     /**
105     * ccs_find_or_assign_new_profile - Create a new profile.
106     *
107     * @profile: Profile number to create.
108     *
109     * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
110     */
111 kumaneko 2892 static struct ccs_profile *ccs_find_or_assign_new_profile(const unsigned int
112     profile)
113 kumaneko 2863 {
114     struct ccs_profile *ptr;
115     struct ccs_profile *entry;
116     int i;
117 kumaneko 2892 if (profile >= CCS_MAX_PROFILES)
118 kumaneko 2863 return NULL;
119     ptr = ccs_profile_ptr[profile];
120     if (ptr)
121     return ptr;
122     entry = kzalloc(sizeof(*entry), GFP_KERNEL);
123     mutex_lock(&ccs_policy_lock);
124     ptr = ccs_profile_ptr[profile];
125     if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
126     ptr = entry;
127     for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++)
128     ptr->value[i] = ccs_control_array[i].current_value;
129     /*
130     * Needn't to initialize "ptr->capability_value"
131     * because they are always 0.
132     */
133     mb(); /* Avoid out-of-order execution. */
134     ccs_profile_ptr[profile] = ptr;
135     entry = NULL;
136     }
137     mutex_unlock(&ccs_policy_lock);
138     kfree(entry);
139     return ptr;
140     }
141    
142     /**
143     * ccs_write_profile - Write profile table.
144     *
145     * @head: Pointer to "struct ccs_io_buffer".
146     *
147     * Returns 0 on success, negative value otherwise.
148     */
149     static int ccs_write_profile(struct ccs_io_buffer *head)
150     {
151     char *data = head->write_buf;
152     unsigned int i;
153     unsigned int value;
154     char *cp;
155     struct ccs_profile *ccs_profile;
156     i = simple_strtoul(data, &cp, 10);
157     if (data != cp) {
158     if (*cp != '-')
159     return -EINVAL;
160     data = cp + 1;
161     }
162     ccs_profile = ccs_find_or_assign_new_profile(i);
163     if (!ccs_profile)
164     return -EINVAL;
165     cp = strchr(data, '=');
166     if (!cp)
167     return -EINVAL;
168     *cp = '\0';
169     if (!strcmp(data, "COMMENT")) {
170     const struct ccs_path_info *new_comment
171     = ccs_get_name(cp + 1);
172     const struct ccs_path_info *old_comment;
173     /* Protect reader from ccs_put_name(). */
174     /***** CRITICAL SECTION START *****/
175     spin_lock(&ccs_profile_comment_lock);
176     old_comment = ccs_profile->comment;
177     ccs_profile->comment = new_comment;
178     spin_unlock(&ccs_profile_comment_lock);
179     /***** CRITICAL SECTION END *****/
180     ccs_put_name(old_comment);
181     ccs_profile_entry_used[0] = true;
182     return 0;
183     }
184 kumaneko 2892 if (ccs_str_starts(&data, CCS_KEYWORD_MAC_FOR_CAPABILITY)) {
185 kumaneko 2863 if (sscanf(cp + 1, "%u", &value) != 1) {
186     for (i = 0; i < 4; i++) {
187     if (strcmp(cp + 1, ccs_mode_4[i]))
188     continue;
189     value = i;
190     break;
191     }
192     if (i == 4)
193     return -EINVAL;
194     }
195     if (value > 3)
196     value = 3;
197     for (i = 0; i < CCS_MAX_CAPABILITY_INDEX; i++) {
198     if (strcmp(data, ccs_capability_control_keyword[i]))
199     continue;
200     ccs_profile->capability_value[i] = value;
201     ccs_profile_entry_used[i + 1 + CCS_MAX_CONTROL_INDEX]
202     = true;
203     return 0;
204     }
205     return -EINVAL;
206     }
207     for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++) {
208     if (strcmp(data, ccs_control_array[i].keyword))
209     continue;
210     if (sscanf(cp + 1, "%u", &value) != 1) {
211     int j;
212     const char **modes;
213     switch (i) {
214 kumaneko 2893 case CCS_AUTOLEARN_EXEC_REALPATH:
215     case CCS_AUTOLEARN_EXEC_ARGV0:
216 kumaneko 2863 case CCS_RESTRICT_AUTOBIND:
217     case CCS_VERBOSE:
218     modes = ccs_mode_2;
219     break;
220     default:
221     modes = ccs_mode_4;
222     break;
223     }
224     for (j = 0; j < 4; j++) {
225     if (strcmp(cp + 1, modes[j]))
226     continue;
227     value = j;
228     break;
229     }
230     if (j == 4)
231     return -EINVAL;
232     } else if (value > ccs_control_array[i].max_value) {
233     value = ccs_control_array[i].max_value;
234     }
235     ccs_profile->value[i] = value;
236     ccs_profile_entry_used[i + 1] = true;
237     return 0;
238     }
239     return -EINVAL;
240     }
241    
242     /**
243     * ccs_read_profile - Read profile table.
244     *
245     * @head: Pointer to "struct ccs_io_buffer".
246     *
247     * Returns 0.
248     */
249     static int ccs_read_profile(struct ccs_io_buffer *head)
250     {
251     static const int ccs_total
252     = CCS_MAX_CONTROL_INDEX + CCS_MAX_CAPABILITY_INDEX + 1;
253     int step;
254     if (head->read_eof)
255     return 0;
256 kumaneko 2892 for (step = head->read_step; step < CCS_MAX_PROFILES * ccs_total;
257     step++) {
258 kumaneko 2863 const u8 index = step / ccs_total;
259     u8 type = step % ccs_total;
260     const struct ccs_profile *ccs_profile = ccs_profile_ptr[index];
261     head->read_step = step;
262     if (!ccs_profile)
263     continue;
264     if (!ccs_profile_entry_used[type])
265     continue;
266     if (!type) { /* Print profile' comment tag. */
267     bool done;
268     /***** CRITICAL SECTION START *****/
269     spin_lock(&ccs_profile_comment_lock);
270     done = ccs_io_printf(head, "%u-COMMENT=%s\n",
271     index, ccs_profile->comment ?
272     ccs_profile->comment->name : "");
273     spin_unlock(&ccs_profile_comment_lock);
274     /***** CRITICAL SECTION END *****/
275     if (!done)
276     break;
277     continue;
278     }
279     type--;
280     if (type >= CCS_MAX_CONTROL_INDEX) {
281     const int i = type - CCS_MAX_CONTROL_INDEX;
282     const u8 value = ccs_profile->capability_value[i];
283     if (!ccs_io_printf(head,
284 kumaneko 2892 "%u-" CCS_KEYWORD_MAC_FOR_CAPABILITY
285 kumaneko 2863 "%s=%s\n", index,
286     ccs_capability_control_keyword[i],
287     ccs_mode_4[value]))
288     break;
289     } else {
290     const unsigned int value = ccs_profile->value[type];
291     const char **modes = NULL;
292     const char *keyword = ccs_control_array[type].keyword;
293     switch (ccs_control_array[type].max_value) {
294     case 3:
295     modes = ccs_mode_4;
296     break;
297     case 1:
298     modes = ccs_mode_2;
299     break;
300     }
301     if (modes) {
302     if (!ccs_io_printf(head, "%u-%s=%s\n", index,
303     keyword, modes[value]))
304     break;
305     } else {
306     if (!ccs_io_printf(head, "%u-%s=%u\n", index,
307     keyword, value))
308     break;
309     }
310     }
311     }
312 kumaneko 2892 if (step == CCS_MAX_PROFILES * ccs_total)
313 kumaneko 2863 head->read_eof = true;
314     return 0;
315     }
316    
317     /* The list for "struct ccs_policy_manager_entry". */
318     LIST_HEAD(ccs_policy_manager_list);
319    
320     /**
321     * ccs_update_manager_entry - Add a manager entry.
322     *
323     * @manager: The path to manager or the domainnamme.
324     * @is_delete: True if it is a delete request.
325     *
326     * Returns 0 on success, negative value otherwise.
327     */
328     static int ccs_update_manager_entry(const char *manager, const bool is_delete)
329     {
330     struct ccs_policy_manager_entry *entry = NULL;
331     struct ccs_policy_manager_entry *ptr;
332     const struct ccs_path_info *saved_manager;
333     int error = is_delete ? -ENOENT : -ENOMEM;
334     bool is_domain = false;
335     if (ccs_is_domain_def(manager)) {
336     if (!ccs_is_correct_domain(manager))
337     return -EINVAL;
338     is_domain = true;
339     } else {
340     if (!ccs_is_correct_path(manager, 1, -1, -1))
341     return -EINVAL;
342     }
343     saved_manager = ccs_get_name(manager);
344     if (!saved_manager)
345     return -ENOMEM;
346     if (!is_delete)
347     entry = kzalloc(sizeof(*entry), GFP_KERNEL);
348     mutex_lock(&ccs_policy_lock);
349     list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
350     if (ptr->manager != saved_manager)
351     continue;
352     ptr->is_deleted = is_delete;
353     error = 0;
354     break;
355     }
356     if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {
357     entry->manager = saved_manager;
358     saved_manager = NULL;
359     entry->is_domain = is_domain;
360     list_add_tail_rcu(&entry->list, &ccs_policy_manager_list);
361     entry = NULL;
362     error = 0;
363     }
364     mutex_unlock(&ccs_policy_lock);
365     ccs_put_name(saved_manager);
366     kfree(entry);
367     return error;
368     }
369    
370     /**
371     * ccs_write_manager_policy - Write manager policy.
372     *
373     * @head: Pointer to "struct ccs_io_buffer".
374     *
375     * Returns 0 on success, negative value otherwise.
376     */
377     static int ccs_write_manager_policy(struct ccs_io_buffer *head)
378     {
379     char *data = head->write_buf;
380 kumaneko 2892 bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);
381 kumaneko 2863 if (!strcmp(data, "manage_by_non_root")) {
382     ccs_manage_by_non_root = !is_delete;
383     return 0;
384     }
385     return ccs_update_manager_entry(data, is_delete);
386     }
387    
388     /**
389     * ccs_read_manager_policy - Read manager policy.
390     *
391     * @head: Pointer to "struct ccs_io_buffer".
392     *
393     * Returns 0.
394     *
395     * Caller holds ccs_read_lock().
396     */
397     static int ccs_read_manager_policy(struct ccs_io_buffer *head)
398     {
399     struct list_head *pos;
400     ccs_check_read_lock();
401     if (head->read_eof)
402     return 0;
403     list_for_each_cookie(pos, head->read_var2, &ccs_policy_manager_list) {
404     struct ccs_policy_manager_entry *ptr;
405     ptr = list_entry(pos, struct ccs_policy_manager_entry, list);
406     if (ptr->is_deleted)
407     continue;
408     if (!ccs_io_printf(head, "%s\n", ptr->manager->name))
409     return 0;
410     }
411     head->read_eof = true;
412     return 0;
413     }
414    
415     /**
416     * ccs_is_policy_manager - Check whether the current process is a policy manager.
417     *
418     * Returns true if the current process is permitted to modify policy
419     * via /proc/ccs/ interface.
420     *
421     * Caller holds ccs_read_lock().
422     */
423     static bool ccs_is_policy_manager(void)
424     {
425     struct ccs_policy_manager_entry *ptr;
426     const char *exe;
427     struct task_struct *task = current;
428     const struct ccs_path_info *domainname
429     = ccs_current_domain()->domainname;
430     bool found = false;
431     ccs_check_read_lock();
432     if (!ccs_policy_loaded)
433     return true;
434     if (task->ccs_flags & CCS_TASK_IS_POLICY_MANAGER)
435     return true;
436     if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
437     return false;
438     list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
439     if (!ptr->is_deleted && ptr->is_domain
440     && !ccs_pathcmp(domainname, ptr->manager)) {
441     /* Set manager flag. */
442     task->ccs_flags |= CCS_TASK_IS_POLICY_MANAGER;
443     return true;
444     }
445     }
446     exe = ccs_get_exe();
447     if (!exe)
448     return false;
449     list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
450     if (!ptr->is_deleted && !ptr->is_domain
451     && !strcmp(exe, ptr->manager->name)) {
452     found = true;
453     /* Set manager flag. */
454     task->ccs_flags |= CCS_TASK_IS_POLICY_MANAGER;
455     break;
456     }
457     }
458     if (!found) { /* Reduce error messages. */
459     static pid_t ccs_last_pid;
460     const pid_t pid = current->pid;
461     if (ccs_last_pid != pid) {
462     printk(KERN_WARNING "%s ( %s ) is not permitted to "
463     "update policies.\n", domainname->name, exe);
464     ccs_last_pid = pid;
465     }
466     }
467     kfree(exe);
468     return found;
469     }
470    
471     /**
472     * ccs_find_condition_part - Find condition part from the statement.
473     *
474     * @data: String to parse.
475     *
476     * Returns pointer to the condition part if it was found in the statement,
477     * NULL otherwise.
478     */
479     static char *ccs_find_condition_part(char *data)
480     {
481     char *cp = strstr(data, " if ");
482     if (cp) {
483     while (1) {
484     char *cp2 = strstr(cp + 3, " if ");
485     if (!cp2)
486     break;
487     cp = cp2;
488     }
489     *cp++ = '\0';
490     } else {
491     cp = strstr(data, " ; set ");
492     if (cp)
493     *cp++ = '\0';
494     }
495     return cp;
496     }
497    
498     /**
499     * ccs_is_select_one - Parse select command.
500     *
501     * @head: Pointer to "struct ccs_io_buffer".
502     * @data: String to parse.
503     *
504     * Returns true on success, false otherwise.
505     *
506     * Caller holds ccs_read_lock().
507     */
508     static bool ccs_is_select_one(struct ccs_io_buffer *head, const char *data)
509     {
510     unsigned int pid;
511     struct ccs_domain_info *domain = NULL;
512     ccs_check_read_lock();
513     if (!strcmp(data, "allow_execute")) {
514     head->read_execute_only = true;
515     return true;
516     }
517     if (sscanf(data, "pid=%u", &pid) == 1) {
518     struct task_struct *p;
519     /***** CRITICAL SECTION START *****/
520     read_lock(&tasklist_lock);
521     p = find_task_by_pid(pid);
522     if (p)
523     domain = ccs_task_domain(p);
524     read_unlock(&tasklist_lock);
525     /***** CRITICAL SECTION END *****/
526     } else if (!strncmp(data, "domain=", 7)) {
527     if (ccs_is_domain_def(data + 7))
528     domain = ccs_find_domain(data + 7);
529     } else
530     return false;
531     head->write_var1 = domain;
532     /* Accessing read_buf is safe because head->io_sem is held. */
533     if (!head->read_buf)
534     return true; /* Do nothing if open(O_WRONLY). */
535     head->read_avail = 0;
536     ccs_io_printf(head, "# select %s\n", data);
537     head->read_single_domain = true;
538     head->read_eof = !domain;
539     if (domain) {
540     struct ccs_domain_info *d;
541     head->read_var1 = NULL;
542     list_for_each_entry_rcu(d, &ccs_domain_list, list) {
543     if (d == domain)
544     break;
545     head->read_var1 = &d->list;
546     }
547     head->read_var2 = NULL;
548     head->read_bit = 0;
549     head->read_step = 0;
550     if (domain->is_deleted)
551     ccs_io_printf(head, "# This is a deleted domain.\n");
552     }
553     return true;
554     }
555    
556     /**
557     * ccs_write_domain_policy - Write domain policy.
558     *
559     * @head: Pointer to "struct ccs_io_buffer".
560     *
561     * Returns 0 on success, negative value otherwise.
562     */
563     static int ccs_write_domain_policy(struct ccs_io_buffer *head)
564     {
565     char *data = head->write_buf;
566     struct ccs_domain_info *domain = head->write_var1;
567     bool is_delete = false;
568     bool is_select = false;
569     unsigned int profile;
570     struct ccs_condition *cond = NULL;
571     char *cp;
572     int error;
573 kumaneko 2892 if (ccs_str_starts(&data, CCS_KEYWORD_DELETE))
574 kumaneko 2863 is_delete = true;
575 kumaneko 2892 else if (ccs_str_starts(&data, CCS_KEYWORD_SELECT))
576 kumaneko 2863 is_select = true;
577     if (is_select && ccs_is_select_one(head, data))
578     return 0;
579     /* Don't allow updating policies by non manager programs. */
580     if (!ccs_is_policy_manager())
581     return -EPERM;
582     if (ccs_is_domain_def(data)) {
583     domain = NULL;
584     if (is_delete)
585     ccs_delete_domain(data);
586     else if (is_select)
587     domain = ccs_find_domain(data);
588     else
589     domain = ccs_find_or_assign_new_domain(data, 0);
590     head->write_var1 = domain;
591     return 0;
592     }
593     if (!domain)
594     return -EINVAL;
595    
596 kumaneko 2892 if (sscanf(data, CCS_KEYWORD_USE_PROFILE "%u", &profile) == 1
597     && profile < CCS_MAX_PROFILES) {
598 kumaneko 2863 if (ccs_profile_ptr[profile] || !ccs_policy_loaded)
599     domain->profile = (u8) profile;
600     return 0;
601     }
602 kumaneko 2892 if (!strcmp(data, CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
603 kumaneko 2863 domain->ignore_global_allow_read = !is_delete;
604     return 0;
605     }
606 kumaneko 2892 if (!strcmp(data, CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV)) {
607 kumaneko 2863 domain->ignore_global_allow_env = !is_delete;
608     return 0;
609     }
610     cp = ccs_find_condition_part(data);
611     if (cp) {
612     cond = ccs_get_condition(cp);
613     if (!cond)
614     return -EINVAL;
615     }
616 kumaneko 2892 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CAPABILITY))
617 kumaneko 2863 error = ccs_write_capability_policy(data, domain, cond,
618     is_delete);
619 kumaneko 2892 else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_NETWORK))
620 kumaneko 2863 error = ccs_write_network_policy(data, domain, cond, is_delete);
621 kumaneko 2892 else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_SIGNAL))
622 kumaneko 2863 error = ccs_write_signal_policy(data, domain, cond, is_delete);
623 kumaneko 2892 else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV))
624 kumaneko 2863 error = ccs_write_env_policy(data, domain, cond, is_delete);
625 kumaneko 2892 else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_MOUNT))
626 kumaneko 2863 error = ccs_write_mount_policy(data, domain, cond, is_delete);
627 kumaneko 2892 else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_UNMOUNT))
628 kumaneko 2863 error = ccs_write_umount_policy(data, domain, cond, is_delete);
629 kumaneko 2892 else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CHROOT))
630 kumaneko 2863 error = ccs_write_chroot_policy(data, domain, cond, is_delete);
631 kumaneko 2892 else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_PIVOT_ROOT))
632 kumaneko 2863 error = ccs_write_pivot_root_policy(data, domain, cond,
633     is_delete);
634     else
635     error = ccs_write_file_policy(data, domain, cond, is_delete);
636     if (cond)
637     ccs_put_condition(cond);
638     return error;
639     }
640    
641 kumaneko 2888 static bool ccs_print_name_union(struct ccs_io_buffer *head,
642     struct ccs_name_union *ptr)
643 kumaneko 2863 {
644     const int pos = head->read_avail;
645     if (pos && head->read_buf[pos - 1] == ' ')
646     head->read_avail--;
647 kumaneko 2888 if (ptr->is_group)
648 kumaneko 2870 return ccs_io_printf(head, " @%s",
649 kumaneko 2888 ptr->group->group_name->name);
650     return ccs_io_printf(head, " %s", ptr->filename->name);
651 kumaneko 2863 }
652    
653 kumaneko 2888 static bool ccs_print_number_union(struct ccs_io_buffer *head,
654     struct ccs_number_union *ptr)
655 kumaneko 2863 {
656 kumaneko 2888 unsigned long min;
657     unsigned long max;
658 kumaneko 2890 u8 min_type;
659     u8 max_type;
660 kumaneko 2888 if (ptr->is_group)
661 kumaneko 2870 return ccs_io_printf(head, " @%s",
662 kumaneko 2888 ptr->group->group_name->name);
663 kumaneko 2890 min_type = ptr->min_type;
664     max_type = ptr->max_type;
665 kumaneko 2888 min = ptr->values[0];
666     max = ptr->values[1];
667 kumaneko 2890 switch (min_type) {
668 kumaneko 2892 case CCS_VALUE_TYPE_HEXADECIMAL:
669 kumaneko 2890 if (!ccs_io_printf(head, " 0x%lX", min))
670     return false;
671     break;
672 kumaneko 2892 case CCS_VALUE_TYPE_OCTAL:
673 kumaneko 2890 if (!ccs_io_printf(head, " 0%lo", min))
674     return false;
675     break;
676     default:
677     if (!ccs_io_printf(head, " %lu", min))
678     return false;
679     break;
680     }
681     if (min == max && min_type == max_type)
682     return true;
683     switch (max_type) {
684 kumaneko 2892 case CCS_VALUE_TYPE_HEXADECIMAL:
685 kumaneko 2890 return ccs_io_printf(head, "-0x%lX", max);
686 kumaneko 2892 case CCS_VALUE_TYPE_OCTAL:
687 kumaneko 2890 return ccs_io_printf(head, "-0%lo", max);
688     default:
689     return ccs_io_printf(head, "-%lu", max);
690     }
691 kumaneko 2863 }
692    
693     /**
694     * ccs_print_single_path_acl - Print a single path ACL entry.
695     *
696     * @head: Pointer to "struct ccs_io_buffer".
697     * @ptr: Pointer to "struct ccs_single_path_acl_record".
698     * @cond: Pointer to "struct ccs_condition". May be NULL.
699     *
700     * Returns true on success, false otherwise.
701     */
702     static bool ccs_print_single_path_acl(struct ccs_io_buffer *head,
703     struct ccs_single_path_acl_record *ptr,
704     const struct ccs_condition *cond)
705     {
706     int pos;
707     u8 bit;
708     const u16 perm = ptr->perm;
709 kumaneko 2892 for (bit = head->read_bit; bit < CCS_MAX_SINGLE_PATH_OPERATION; bit++) {
710 kumaneko 2863 const char *msg;
711     if (!(perm & (1 << bit)))
712     continue;
713 kumaneko 2892 if (head->read_execute_only && bit != CCS_TYPE_EXECUTE_ACL)
714 kumaneko 2863 continue;
715     /* Print "read/write" instead of "read" and "write". */
716 kumaneko 2892 if ((bit == CCS_TYPE_READ_ACL || bit == CCS_TYPE_WRITE_ACL)
717     && (perm & (1 << CCS_TYPE_READ_WRITE_ACL)))
718 kumaneko 2863 continue;
719     msg = ccs_sp2keyword(bit);
720     pos = head->read_avail;
721     if (!ccs_io_printf(head, "allow_%s", msg) ||
722 kumaneko 2888 !ccs_print_name_union(head, &ptr->name) ||
723 kumaneko 2863 !ccs_print_condition(head, cond))
724     goto out;
725     }
726     head->read_bit = 0;
727     return true;
728     out:
729     head->read_bit = bit;
730     head->read_avail = pos;
731     return false;
732     }
733    
734     /**
735     * ccs_print_mkdev_acl - Print a mkdev ACL entry.
736     *
737     * @head: Pointer to "struct ccs_io_buffer".
738     * @ptr: Pointer to "struct ccs_mkdev_acl_record".
739     * @cond: Pointer to "struct ccs_condition". May be NULL.
740     *
741     * Returns true on success, false otherwise.
742     */
743     static bool ccs_print_mkdev_acl(struct ccs_io_buffer *head,
744     struct ccs_mkdev_acl_record *ptr,
745     const struct ccs_condition *cond)
746     {
747     int pos;
748     u8 bit;
749     const u16 perm = ptr->perm;
750 kumaneko 2892 for (bit = head->read_bit; bit < CCS_MAX_MKDEV_OPERATION; bit++) {
751 kumaneko 2863 const char *msg;
752     if (!(perm & (1 << bit)))
753     continue;
754     msg = ccs_mkdev2keyword(bit);
755     pos = head->read_avail;
756     if (!ccs_io_printf(head, "allow_%s", msg) ||
757 kumaneko 2888 !ccs_print_name_union(head, &ptr->name) ||
758     !ccs_print_number_union(head, &ptr->major) ||
759     !ccs_print_number_union(head, &ptr->minor) ||
760 kumaneko 2863 !ccs_print_condition(head, cond))
761     goto out;
762     }
763     head->read_bit = 0;
764     return true;
765     out:
766     head->read_bit = bit;
767     head->read_avail = pos;
768     return false;
769     }
770    
771     /**
772     * ccs_print_double_path_acl - Print a double path ACL entry.
773     *
774     * @head: Pointer to "struct ccs_io_buffer".
775     * @ptr: Pointer to "struct ccs_double_path_acl_record".
776     * @cond: Pointer to "struct ccs_condition". May be NULL.
777     *
778     * Returns true on success, false otherwise.
779     */
780     static bool ccs_print_double_path_acl(struct ccs_io_buffer *head,
781     struct ccs_double_path_acl_record *ptr,
782     const struct ccs_condition *cond)
783     {
784     int pos;
785     u8 bit;
786     const u8 perm = ptr->perm;
787 kumaneko 2892 for (bit = head->read_bit; bit < CCS_MAX_DOUBLE_PATH_OPERATION; bit++) {
788 kumaneko 2863 const char *msg;
789     if (!(perm & (1 << bit)))
790     continue;
791     msg = ccs_dp2keyword(bit);
792     pos = head->read_avail;
793     if (!ccs_io_printf(head, "allow_%s", msg) ||
794 kumaneko 2888 !ccs_print_name_union(head, &ptr->name1) ||
795     !ccs_print_name_union(head, &ptr->name2) ||
796 kumaneko 2863 !ccs_print_condition(head, cond))
797     goto out;
798     }
799     head->read_bit = 0;
800     return true;
801     out:
802     head->read_bit = bit;
803     head->read_avail = pos;
804     return false;
805     }
806    
807     /**
808 kumaneko 2871 * ccs_print_path_number_acl - Print an ioctl/chmod/chown/chgrp ACL entry.
809 kumaneko 2863 *
810     * @head: Pointer to "struct ccs_io_buffer".
811 kumaneko 2871 * @ptr: Pointer to "struct ccs_path_number_acl_record".
812 kumaneko 2863 * @cond: Pointer to "struct ccs_condition". May be NULL.
813     *
814     * Returns true on success, false otherwise.
815     */
816 kumaneko 2871 static bool ccs_print_path_number_acl(struct ccs_io_buffer *head,
817     struct ccs_path_number_acl_record *ptr,
818     const struct ccs_condition *cond)
819 kumaneko 2863 {
820 kumaneko 2871 int pos;
821     u8 bit;
822     const u8 perm = ptr->perm;
823 kumaneko 2892 for (bit = head->read_bit; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) {
824 kumaneko 2871 const char *msg;
825     if (!(perm & (1 << bit)))
826     continue;
827     msg = ccs_path_number2keyword(bit);
828     pos = head->read_avail;
829     if (!ccs_io_printf(head, "allow_%s", msg) ||
830 kumaneko 2888 !ccs_print_name_union(head, &ptr->name) ||
831     !ccs_print_number_union(head, &ptr->number) ||
832 kumaneko 2871 !ccs_print_condition(head, cond))
833     goto out;
834     }
835     head->read_bit = 0;
836 kumaneko 2863 return true;
837     out:
838 kumaneko 2871 head->read_bit = bit;
839 kumaneko 2863 head->read_avail = pos;
840     return false;
841     }
842    
843     /**
844     * ccs_print_env_acl - Print an evironment variable name's ACL entry.
845     *
846     * @head: Pointer to "struct ccs_io_buffer".
847     * @ptr: Pointer to "struct ccs_env_acl_record".
848     * @cond: Pointer to "struct ccs_condition". May be NULL.
849     *
850     * Returns true on success, false otherwise.
851     */
852     static bool ccs_print_env_acl(struct ccs_io_buffer *head,
853     struct ccs_env_acl_record *ptr,
854     const struct ccs_condition *cond)
855     {
856     int pos = head->read_avail;
857 kumaneko 2892 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_ENV "%s", ptr->env->name))
858 kumaneko 2863 goto out;
859     if (!ccs_print_condition(head, cond))
860     goto out;
861     return true;
862     out:
863     head->read_avail = pos;
864     return false;
865     }
866    
867     /**
868     * ccs_print_capability_acl - Print a capability ACL entry.
869     *
870     * @head: Pointer to "struct ccs_io_buffer".
871     * @ptr: Pointer to "struct ccs_capability_acl_record".
872     * @cond: Pointer to "struct ccs_condition". May be NULL.
873     *
874     * Returns true on success, false otherwise.
875     */
876     static bool ccs_print_capability_acl(struct ccs_io_buffer *head,
877     struct ccs_capability_acl_record *ptr,
878     const struct ccs_condition *cond)
879     {
880     int pos = head->read_avail;
881 kumaneko 2892 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CAPABILITY "%s",
882 kumaneko 2863 ccs_cap2keyword(ptr->operation)))
883     goto out;
884     if (!ccs_print_condition(head, cond))
885     goto out;
886     return true;
887     out:
888     head->read_avail = pos;
889     return false;
890     }
891    
892     /**
893     * ccs_print_ipv4_entry - Print IPv4 address of a network ACL entry.
894     *
895     * @head: Pointer to "struct ccs_io_buffer".
896     * @ptr: Pointer to "struct ccs_ip_network_acl_record".
897     *
898     * Returns true on success, false otherwise.
899     */
900     static bool ccs_print_ipv4_entry(struct ccs_io_buffer *head,
901     struct ccs_ip_network_acl_record *ptr)
902     {
903     const u32 min_address = ptr->address.ipv4.min;
904     const u32 max_address = ptr->address.ipv4.max;
905     if (!ccs_io_printf(head, "%u.%u.%u.%u", HIPQUAD(min_address)))
906     return false;
907     if (min_address != max_address
908     && !ccs_io_printf(head, "-%u.%u.%u.%u", HIPQUAD(max_address)))
909     return false;
910     return true;
911     }
912    
913     /**
914     * ccs_print_ipv6_entry - Print IPv6 address of a network ACL entry.
915     *
916     * @head: Pointer to "struct ccs_io_buffer".
917     * @ptr: Pointer to "struct ccs_ip_network_acl_record".
918     *
919     * Returns true on success, false otherwise.
920     */
921     static bool ccs_print_ipv6_entry(struct ccs_io_buffer *head,
922     struct ccs_ip_network_acl_record *ptr)
923     {
924     char buf[64];
925     const struct in6_addr *min_address = ptr->address.ipv6.min;
926     const struct in6_addr *max_address = ptr->address.ipv6.max;
927     ccs_print_ipv6(buf, sizeof(buf), min_address);
928     if (!ccs_io_printf(head, "%s", buf))
929     return false;
930     if (min_address != max_address) {
931     ccs_print_ipv6(buf, sizeof(buf), max_address);
932     if (!ccs_io_printf(head, "-%s", buf))
933     return false;
934     }
935     return true;
936     }
937    
938     /**
939     * ccs_print_network_acl - Print a network ACL entry.
940     *
941     * @head: Pointer to "struct ccs_io_buffer".
942     * @ptr: Pointer to "struct ccs_ip_network_acl_record".
943     * @cond: Pointer to "struct ccs_condition". May be NULL.
944     *
945     * Returns true on success, false otherwise.
946     */
947     static bool ccs_print_network_acl(struct ccs_io_buffer *head,
948     struct ccs_ip_network_acl_record *ptr,
949     const struct ccs_condition *cond)
950     {
951     int pos = head->read_avail;
952 kumaneko 2892 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s ",
953 kumaneko 2863 ccs_net2keyword(ptr->operation_type)))
954     goto out;
955     switch (ptr->record_type) {
956 kumaneko 2892 case CCS_IP_RECORD_TYPE_ADDRESS_GROUP:
957 kumaneko 2863 if (!ccs_io_printf(head, "@%s",
958     ptr->address.group->group_name->name))
959     goto out;
960     break;
961 kumaneko 2892 case CCS_IP_RECORD_TYPE_IPv4:
962 kumaneko 2863 if (!ccs_print_ipv4_entry(head, ptr))
963     goto out;
964     break;
965 kumaneko 2892 case CCS_IP_RECORD_TYPE_IPv6:
966 kumaneko 2863 if (!ccs_print_ipv6_entry(head, ptr))
967     goto out;
968     break;
969     }
970 kumaneko 2888 if (!ccs_print_number_union(head, &ptr->port) ||
971 kumaneko 2863 !ccs_print_condition(head, cond))
972     goto out;
973     return true;
974     out:
975     head->read_avail = pos;
976     return false;
977     }
978    
979     /**
980     * ccs_print_signal_acl - Print a signal ACL entry.
981     *
982     * @head: Pointer to "struct ccs_io_buffer".
983     * @ptr: Pointer to "struct signale_acl_record".
984     * @cond: Pointer to "struct ccs_condition". May be NULL.
985     *
986     * Returns true on success, false otherwise.
987     */
988     static bool ccs_print_signal_acl(struct ccs_io_buffer *head,
989     struct ccs_signal_acl_record *ptr,
990     const struct ccs_condition *cond)
991     {
992     int pos = head->read_avail;
993 kumaneko 2892 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u %s",
994 kumaneko 2863 ptr->sig, ptr->domainname->name))
995     goto out;
996     if (!ccs_print_condition(head, cond))
997     goto out;
998     return true;
999     out:
1000     head->read_avail = pos;
1001     return false;
1002     }
1003    
1004     /**
1005     * ccs_print_execute_handler_record - Print an execute handler ACL entry.
1006     *
1007     * @head: Pointer to "struct ccs_io_buffer".
1008     * @keyword: Name of the keyword.
1009     * @ptr: Pointer to "struct ccs_execute_handler_record".
1010     *
1011     * Returns true on success, false otherwise.
1012     */
1013     static bool ccs_print_execute_handler_record(struct ccs_io_buffer *head,
1014     const char *keyword,
1015     struct ccs_execute_handler_record *
1016     ptr)
1017     {
1018     return ccs_io_printf(head, "%s %s\n", keyword, ptr->handler->name);
1019     }
1020    
1021     /**
1022     * ccs_print_mount_acl - Print a mount ACL entry.
1023     *
1024     * @head: Pointer to "struct ccs_io_buffer".
1025     * @ptr: Pointer to "struct ccs_mount_acl_record".
1026     * @cond: Pointer to "struct ccs_condition". May be NULL.
1027     *
1028     * Returns true on success, false otherwise.
1029     */
1030     static bool ccs_print_mount_acl(struct ccs_io_buffer *head,
1031     struct ccs_mount_acl_record *ptr,
1032     const struct ccs_condition *cond)
1033     {
1034     int pos = head->read_avail;
1035 kumaneko 2892 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n",
1036 kumaneko 2863 ptr->dev_name->name, ptr->dir_name->name,
1037     ptr->fs_type->name, ptr->flags))
1038     goto out;
1039     if (!ccs_print_condition(head, cond))
1040     goto out;
1041     return true;
1042     out:
1043     head->read_avail = pos;
1044     return false;
1045     }
1046    
1047     /**
1048     * ccs_print_umount_acl - Print a mount ACL entry.
1049     *
1050     * @head: Pointer to "struct ccs_io_buffer".
1051     * @ptr: Pointer to "struct ccs_umount_acl_record".
1052     * @cond: Pointer to "struct ccs_condition". May be NULL.
1053     *
1054     * Returns true on success, false otherwise.
1055     */
1056     static bool ccs_print_umount_acl(struct ccs_io_buffer *head,
1057     struct ccs_umount_acl_record *ptr,
1058     const struct ccs_condition *cond)
1059     {
1060     int pos = head->read_avail;
1061 kumaneko 2892 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_UNMOUNT "%s\n",
1062 kumaneko 2863 ptr->dir->name))
1063     goto out;
1064     if (!ccs_print_condition(head, cond))
1065     goto out;
1066     return true;
1067     out:
1068     head->read_avail = pos;
1069     return false;
1070     }
1071    
1072     /**
1073     * ccs_print_chroot_acl - Print a chroot ACL entry.
1074     *
1075     * @head: Pointer to "struct ccs_io_buffer".
1076     * @ptr: Pointer to "struct ccs_chroot_acl_record".
1077     * @cond: Pointer to "struct ccs_condition". May be NULL.
1078     *
1079     * Returns true on success, false otherwise.
1080     */
1081     static bool ccs_print_chroot_acl(struct ccs_io_buffer *head,
1082     struct ccs_chroot_acl_record *ptr,
1083     const struct ccs_condition *cond)
1084     {
1085     int pos = head->read_avail;
1086 kumaneko 2892 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CHROOT "%s\n",
1087 kumaneko 2863 ptr->dir->name))
1088     goto out;
1089     if (!ccs_print_condition(head, cond))
1090     goto out;
1091     return true;
1092     out:
1093     head->read_avail = pos;
1094     return false;
1095     }
1096    
1097     /**
1098     * ccs_print_pivot_root_acl - Print a pivot_root ACL entry.
1099     *
1100     * @head: Pointer to "struct ccs_io_buffer".
1101     * @ptr: Pointer to "struct ccs_pivot_root_acl_record".
1102     * @cond: Pointer to "struct ccs_condition". May be NULL.
1103     *
1104     * Returns true on success, false otherwise.
1105     */
1106     static bool ccs_print_pivot_root_acl(struct ccs_io_buffer *head,
1107     struct ccs_pivot_root_acl_record *ptr,
1108     const struct ccs_condition *cond)
1109     {
1110     int pos = head->read_avail;
1111 kumaneko 2892 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_PIVOT_ROOT "%s %s\n",
1112 kumaneko 2863 ptr->new_root->name, ptr->old_root->name))
1113     goto out;
1114     if (!ccs_print_condition(head, cond))
1115     goto out;
1116     return true;
1117     out:
1118     head->read_avail = pos;
1119     return false;
1120     }
1121    
1122     /**
1123     * ccs_print_entry - Print an ACL entry.
1124     *
1125     * @head: Pointer to "struct ccs_io_buffer".
1126     * @ptr: Pointer to an ACL entry.
1127     *
1128     * Returns true on success, false otherwise.
1129     */
1130     static bool ccs_print_entry(struct ccs_io_buffer *head,
1131     struct ccs_acl_info *ptr)
1132     {
1133     const struct ccs_condition *cond = ptr->cond;
1134     const u8 acl_type = ccs_acl_type2(ptr);
1135 kumaneko 2892 if (acl_type & CCS_ACL_DELETED)
1136 kumaneko 2863 return true;
1137 kumaneko 2892 if (acl_type == CCS_TYPE_SINGLE_PATH_ACL) {
1138 kumaneko 2863 struct ccs_single_path_acl_record *acl
1139     = container_of(ptr, struct ccs_single_path_acl_record,
1140     head);
1141     return ccs_print_single_path_acl(head, acl, cond);
1142     }
1143 kumaneko 2892 if (acl_type == CCS_TYPE_EXECUTE_HANDLER) {
1144 kumaneko 2863 struct ccs_execute_handler_record *acl
1145     = container_of(ptr, struct ccs_execute_handler_record,
1146     head);
1147 kumaneko 2892 const char *keyword = CCS_KEYWORD_EXECUTE_HANDLER;
1148 kumaneko 2863 return ccs_print_execute_handler_record(head, keyword, acl);
1149     }
1150 kumaneko 2892 if (acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
1151 kumaneko 2863 struct ccs_execute_handler_record *acl
1152     = container_of(ptr, struct ccs_execute_handler_record,
1153     head);
1154 kumaneko 2892 const char *keyword = CCS_KEYWORD_DENIED_EXECUTE_HANDLER;
1155 kumaneko 2863 return ccs_print_execute_handler_record(head, keyword, acl);
1156     }
1157     if (head->read_execute_only)
1158     return true;
1159 kumaneko 2892 if (acl_type == CCS_TYPE_MKDEV_ACL) {
1160 kumaneko 2863 struct ccs_mkdev_acl_record *acl
1161     = container_of(ptr, struct ccs_mkdev_acl_record, head);
1162     return ccs_print_mkdev_acl(head, acl, cond);
1163     }
1164 kumaneko 2892 if (acl_type == CCS_TYPE_DOUBLE_PATH_ACL) {
1165 kumaneko 2863 struct ccs_double_path_acl_record *acl
1166     = container_of(ptr, struct ccs_double_path_acl_record,
1167     head);
1168     return ccs_print_double_path_acl(head, acl, cond);
1169     }
1170 kumaneko 2892 if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
1171 kumaneko 2871 struct ccs_path_number_acl_record *acl
1172     = container_of(ptr, struct ccs_path_number_acl_record,
1173     head);
1174     return ccs_print_path_number_acl(head, acl, cond);
1175 kumaneko 2863 }
1176 kumaneko 2892 if (acl_type == CCS_TYPE_ENV_ACL) {
1177 kumaneko 2863 struct ccs_env_acl_record *acl
1178     = container_of(ptr, struct ccs_env_acl_record, head);
1179     return ccs_print_env_acl(head, acl, cond);
1180     }
1181 kumaneko 2892 if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
1182 kumaneko 2863 struct ccs_capability_acl_record *acl
1183     = container_of(ptr, struct ccs_capability_acl_record,
1184     head);
1185     return ccs_print_capability_acl(head, acl, cond);
1186     }
1187 kumaneko 2892 if (acl_type == CCS_TYPE_IP_NETWORK_ACL) {
1188 kumaneko 2863 struct ccs_ip_network_acl_record *acl
1189     = container_of(ptr, struct ccs_ip_network_acl_record,
1190     head);
1191     return ccs_print_network_acl(head, acl, cond);
1192     }
1193 kumaneko 2892 if (acl_type == CCS_TYPE_SIGNAL_ACL) {
1194 kumaneko 2863 struct ccs_signal_acl_record *acl
1195     = container_of(ptr, struct ccs_signal_acl_record, head);
1196     return ccs_print_signal_acl(head, acl, cond);
1197     }
1198 kumaneko 2892 if (acl_type == CCS_TYPE_MOUNT_ACL) {
1199 kumaneko 2863 struct ccs_mount_acl_record *acl
1200     = container_of(ptr, struct ccs_mount_acl_record, head);
1201     return ccs_print_mount_acl(head, acl, cond);
1202     }
1203 kumaneko 2892 if (acl_type == CCS_TYPE_UMOUNT_ACL) {
1204 kumaneko 2863 struct ccs_umount_acl_record *acl
1205     = container_of(ptr, struct ccs_umount_acl_record, head);
1206     return ccs_print_umount_acl(head, acl, cond);
1207     }
1208 kumaneko 2892 if (acl_type == CCS_TYPE_CHROOT_ACL) {
1209 kumaneko 2863 struct ccs_chroot_acl_record *acl
1210     = container_of(ptr, struct ccs_chroot_acl_record, head);
1211     return ccs_print_chroot_acl(head, acl, cond);
1212     }
1213 kumaneko 2892 if (acl_type == CCS_TYPE_PIVOT_ROOT_ACL) {
1214 kumaneko 2863 struct ccs_pivot_root_acl_record *acl
1215     = container_of(ptr, struct ccs_pivot_root_acl_record,
1216     head);
1217     return ccs_print_pivot_root_acl(head, acl, cond);
1218     }
1219     /* Workaround for gcc 3.2.2's inline bug. */
1220 kumaneko 2892 if (acl_type & CCS_ACL_DELETED)
1221 kumaneko 2863 return true;
1222     BUG(); /* This must not happen. */
1223     return false;
1224     }
1225    
1226     /**
1227     * ccs_read_domain_policy - Read domain policy.
1228     *
1229     * @head: Pointer to "struct ccs_io_buffer".
1230     *
1231     * Returns 0.
1232     *
1233     * Caller holds ccs_read_lock().
1234     */
1235     static int ccs_read_domain_policy(struct ccs_io_buffer *head)
1236     {
1237     struct list_head *dpos;
1238     struct list_head *apos;
1239     ccs_check_read_lock();
1240     if (head->read_eof)
1241     return 0;
1242     if (head->read_step == 0)
1243     head->read_step = 1;
1244     list_for_each_cookie(dpos, head->read_var1, &ccs_domain_list) {
1245     struct ccs_domain_info *domain;
1246     const char *quota_exceeded = "";
1247     const char *transition_failed = "";
1248     const char *ignore_global_allow_read = "";
1249     const char *ignore_global_allow_env = "";
1250     domain = list_entry(dpos, struct ccs_domain_info, list);
1251     if (head->read_step != 1)
1252     goto acl_loop;
1253     if (domain->is_deleted && !head->read_single_domain)
1254     continue;
1255     /* Print domainname and flags. */
1256     if (domain->quota_warned)
1257     quota_exceeded = "quota_exceeded\n";
1258     if (domain->domain_transition_failed)
1259     transition_failed = "transition_failed\n";
1260     if (domain->ignore_global_allow_read)
1261     ignore_global_allow_read
1262 kumaneko 2892 = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
1263 kumaneko 2863 if (domain->ignore_global_allow_env)
1264     ignore_global_allow_env
1265 kumaneko 2892 = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n";
1266     if (!ccs_io_printf(head, "%s\n" CCS_KEYWORD_USE_PROFILE "%u\n"
1267 kumaneko 2863 "%s%s%s%s\n", domain->domainname->name,
1268     domain->profile, quota_exceeded,
1269     transition_failed,
1270     ignore_global_allow_read,
1271     ignore_global_allow_env))
1272     return 0;
1273     head->read_step = 2;
1274     acl_loop:
1275     if (head->read_step == 3)
1276     goto tail_mark;
1277     /* Print ACL entries in the domain. */
1278     list_for_each_cookie(apos, head->read_var2,
1279     &domain->acl_info_list) {
1280     struct ccs_acl_info *ptr
1281     = list_entry(apos, struct ccs_acl_info, list);
1282     if (!ccs_print_entry(head, ptr))
1283     return 0;
1284     }
1285     head->read_step = 3;
1286     tail_mark:
1287     if (!ccs_io_printf(head, "\n"))
1288     return 0;
1289     head->read_step = 1;
1290     if (head->read_single_domain)
1291     break;
1292     }
1293     head->read_eof = true;
1294     return 0;
1295     }
1296    
1297     /**
1298     * ccs_write_domain_profile - Assign profile for specified domain.
1299     *
1300     * @head: Pointer to "struct ccs_io_buffer".
1301     *
1302     * Returns 0 on success, -EINVAL otherwise.
1303     *
1304     * This is equivalent to doing
1305     *
1306     * ( echo "select " $domainname; echo "use_profile " $profile ) |
1307     * /usr/lib/ccs/loadpolicy -d
1308     *
1309     * Caller holds ccs_read_lock().
1310     */
1311     static int ccs_write_domain_profile(struct ccs_io_buffer *head)
1312     {
1313     char *data = head->write_buf;
1314     char *cp = strchr(data, ' ');
1315     struct ccs_domain_info *domain;
1316     unsigned int profile;
1317     ccs_check_read_lock();
1318     if (!cp)
1319     return -EINVAL;
1320     *cp = '\0';
1321     profile = simple_strtoul(data, NULL, 10);
1322 kumaneko 2892 if (profile >= CCS_MAX_PROFILES)
1323 kumaneko 2863 return -EINVAL;
1324     domain = ccs_find_domain(cp + 1);
1325     if (domain && (ccs_profile_ptr[profile] || !ccs_policy_loaded))
1326     domain->profile = (u8) profile;
1327     return 0;
1328     }
1329    
1330     /**
1331     * ccs_read_domain_profile - Read only domainname and profile.
1332     *
1333     * @head: Pointer to "struct ccs_io_buffer".
1334     *
1335     * Returns list of profile number and domainname pairs.
1336     *
1337     * This is equivalent to doing
1338     *
1339     * grep -A 1 '^<kernel>' /proc/ccs/domain_policy |
1340     * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
1341     * domainname = $0; } else if ( $1 == "use_profile" ) {
1342     * print $2 " " domainname; domainname = ""; } } ; '
1343     *
1344     * Caller holds ccs_read_lock().
1345     */
1346     static int ccs_read_domain_profile(struct ccs_io_buffer *head)
1347     {
1348     struct list_head *pos;
1349     ccs_check_read_lock();
1350     if (head->read_eof)
1351     return 0;
1352     list_for_each_cookie(pos, head->read_var1, &ccs_domain_list) {
1353     struct ccs_domain_info *domain;
1354     domain = list_entry(pos, struct ccs_domain_info, list);
1355     if (domain->is_deleted)
1356     continue;
1357     if (!ccs_io_printf(head, "%u %s\n", domain->profile,
1358     domain->domainname->name))
1359     return 0;
1360     }
1361     head->read_eof = true;
1362     return 0;
1363     }
1364    
1365     /**
1366     * ccs_write_pid: Specify PID to obtain domainname.
1367     *
1368     * @head: Pointer to "struct ccs_io_buffer".
1369     *
1370     * Returns 0.
1371     */
1372     static int ccs_write_pid(struct ccs_io_buffer *head)
1373     {
1374     head->read_eof = false;
1375     return 0;
1376     }
1377    
1378     /**
1379     * ccs_read_pid - Read information of a process.
1380     *
1381     * @head: Pointer to "struct ccs_io_buffer".
1382     *
1383     * Returns the domainname which the specified PID is in or
1384     * process information of the specified PID on success,
1385     * empty string otherwise.
1386     *
1387     * Caller holds ccs_read_lock().
1388     */
1389     static int ccs_read_pid(struct ccs_io_buffer *head)
1390     {
1391     char *buf = head->write_buf;
1392     bool task_info = false;
1393     unsigned int pid;
1394     struct task_struct *p;
1395     struct ccs_domain_info *domain = NULL;
1396     u32 ccs_flags = 0;
1397     ccs_check_read_lock();
1398     /* Accessing write_buf is safe because head->io_sem is held. */
1399     if (!buf)
1400     goto done; /* Do nothing if open(O_RDONLY). */
1401     if (head->read_avail || head->read_eof)
1402     goto done;
1403     head->read_eof = true;
1404     if (ccs_str_starts(&buf, "info "))
1405     task_info = true;
1406     pid = (unsigned int) simple_strtoul(buf, NULL, 10);
1407     /***** CRITICAL SECTION START *****/
1408     read_lock(&tasklist_lock);
1409     p = find_task_by_pid(pid);
1410     if (p) {
1411     domain = ccs_task_domain(p);
1412     ccs_flags = p->ccs_flags;
1413     }
1414     read_unlock(&tasklist_lock);
1415     /***** CRITICAL SECTION END *****/
1416     if (!domain)
1417     goto done;
1418     if (!task_info)
1419     ccs_io_printf(head, "%u %u %s", pid, domain->profile,
1420     domain->domainname->name);
1421     else
1422     ccs_io_printf(head, "%u manager=%s execute_handler=%s "
1423     "state[0]=%u state[1]=%u state[2]=%u", pid,
1424     ccs_flags & CCS_TASK_IS_POLICY_MANAGER ?
1425     "yes" : "no",
1426     ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER ?
1427     "yes" : "no",
1428     (u8) (ccs_flags >> 24),
1429     (u8) (ccs_flags >> 16),
1430     (u8) (ccs_flags >> 8));
1431     done:
1432     return 0;
1433     }
1434    
1435     /**
1436     * ccs_write_exception_policy - Write exception policy.
1437     *
1438     * @head: Pointer to "struct ccs_io_buffer".
1439     *
1440     * Returns 0 on success, negative value otherwise.
1441     */
1442     static int ccs_write_exception_policy(struct ccs_io_buffer *head)
1443     {
1444     char *data = head->write_buf;
1445 kumaneko 2892 bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);
1446     if (ccs_str_starts(&data, CCS_KEYWORD_KEEP_DOMAIN))
1447 kumaneko 2863 return ccs_write_domain_keeper_policy(data, false, is_delete);
1448 kumaneko 2892 if (ccs_str_starts(&data, CCS_KEYWORD_NO_KEEP_DOMAIN))
1449 kumaneko 2863 return ccs_write_domain_keeper_policy(data, true, is_delete);
1450 kumaneko 2892 if (ccs_str_starts(&data, CCS_KEYWORD_INITIALIZE_DOMAIN))
1451 kumaneko 2863 return ccs_write_domain_initializer_policy(data, false,
1452     is_delete);
1453 kumaneko 2892 if (ccs_str_starts(&data, CCS_KEYWORD_NO_INITIALIZE_DOMAIN))
1454 kumaneko 2863 return ccs_write_domain_initializer_policy(data, true,
1455     is_delete);
1456 kumaneko 2892 if (ccs_str_starts(&data, CCS_KEYWORD_AGGREGATOR))
1457 kumaneko 2863 return ccs_write_aggregator_policy(data, is_delete);
1458 kumaneko 2892 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_READ))
1459 kumaneko 2863 return ccs_write_globally_readable_policy(data, is_delete);
1460 kumaneko 2892 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV))
1461 kumaneko 2863 return ccs_write_globally_usable_env_policy(data, is_delete);
1462 kumaneko 2892 if (ccs_str_starts(&data, CCS_KEYWORD_FILE_PATTERN))
1463 kumaneko 2863 return ccs_write_pattern_policy(data, is_delete);
1464 kumaneko 2892 if (ccs_str_starts(&data, CCS_KEYWORD_PATH_GROUP))
1465 kumaneko 2863 return ccs_write_path_group_policy(data, is_delete);
1466 kumaneko 2892 if (ccs_str_starts(&data, CCS_KEYWORD_NUMBER_GROUP))
1467 kumaneko 2863 return ccs_write_number_group_policy(data, is_delete);
1468 kumaneko 2892 if (ccs_str_starts(&data, CCS_KEYWORD_DENY_REWRITE))
1469 kumaneko 2863 return ccs_write_no_rewrite_policy(data, is_delete);
1470 kumaneko 2892 if (ccs_str_starts(&data, CCS_KEYWORD_ADDRESS_GROUP))
1471 kumaneko 2863 return ccs_write_address_group_policy(data, is_delete);
1472 kumaneko 2892 if (ccs_str_starts(&data, CCS_KEYWORD_DENY_AUTOBIND))
1473 kumaneko 2863 return ccs_write_reserved_port_policy(data, is_delete);
1474     return -EINVAL;
1475     }
1476    
1477     /**
1478     * ccs_read_exception_policy - Read exception policy.
1479     *
1480     * @head: Pointer to "struct ccs_io_buffer".
1481     *
1482     * Returns 0 on success, -EINVAL otherwise.
1483     *
1484     * Caller holds ccs_read_lock().
1485     */
1486     static int ccs_read_exception_policy(struct ccs_io_buffer *head)
1487     {
1488     ccs_check_read_lock();
1489     if (!head->read_eof) {
1490     switch (head->read_step) {
1491     case 0:
1492     head->read_var2 = NULL;
1493     head->read_step = 1;
1494     case 1:
1495     if (!ccs_read_domain_keeper_policy(head))
1496     break;
1497     head->read_var2 = NULL;
1498     head->read_step = 2;
1499     case 2:
1500     if (!ccs_read_globally_readable_policy(head))
1501     break;
1502     head->read_var2 = NULL;
1503     head->read_step = 3;
1504     case 3:
1505     if (!ccs_read_globally_usable_env_policy(head))
1506     break;
1507     head->read_var2 = NULL;
1508     head->read_step = 4;
1509     case 4:
1510     if (!ccs_read_domain_initializer_policy(head))
1511     break;
1512     head->read_var2 = NULL;
1513     head->read_step = 6;
1514     case 6:
1515     if (!ccs_read_aggregator_policy(head))
1516     break;
1517     head->read_var2 = NULL;
1518     head->read_step = 7;
1519     case 7:
1520     if (!ccs_read_file_pattern(head))
1521     break;
1522     head->read_var2 = NULL;
1523     head->read_step = 8;
1524     case 8:
1525     if (!ccs_read_no_rewrite_policy(head))
1526     break;
1527     head->read_var2 = NULL;
1528     head->read_step = 9;
1529     case 9:
1530     if (!ccs_read_path_group_policy(head))
1531     break;
1532     head->read_var1 = NULL;
1533     head->read_var2 = NULL;
1534     head->read_step = 10;
1535     case 10:
1536     if (!ccs_read_number_group_policy(head))
1537     break;
1538     head->read_var1 = NULL;
1539     head->read_var2 = NULL;
1540     head->read_step = 11;
1541     case 11:
1542     if (!ccs_read_address_group_policy(head))
1543     break;
1544     head->read_var2 = NULL;
1545     head->read_step = 12;
1546     case 12:
1547     if (!ccs_read_reserved_port_policy(head))
1548     break;
1549     head->read_eof = true;
1550     break;
1551     default:
1552     return -EINVAL;
1553     }
1554     }
1555     return 0;
1556     }
1557    
1558     /* Wait queue for ccs_query_list. */
1559     static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
1560    
1561     /* Lock for manipulating ccs_query_list. */
1562     static DEFINE_SPINLOCK(ccs_query_list_lock);
1563    
1564     /* Structure for query. */
1565     struct ccs_query_entry {
1566     struct list_head list;
1567     char *query;
1568     int query_len;
1569     unsigned int serial;
1570     int timer;
1571     int answer;
1572     };
1573    
1574     /* The list for "struct ccs_query_entry". */
1575     static LIST_HEAD(ccs_query_list);
1576    
1577     /* Number of "struct file" referring /proc/ccs/query interface. */
1578     static atomic_t ccs_query_observers = ATOMIC_INIT(0);
1579    
1580     /**
1581     * ccs_check_supervisor - Ask for the supervisor's decision.
1582     *
1583     * @r: Pointer to "struct ccs_request_info".
1584     * @fmt: The printf()'s format string, followed by parameters.
1585     *
1586     * Returns 0 if the supervisor decided to permit the access request which
1587     * violated the policy in enforcing mode, 1 if the supervisor decided to
1588     * retry the access request which violated the policy in enforcing mode,
1589     * -EPERM otherwise.
1590     */
1591     int ccs_check_supervisor(struct ccs_request_info *r, const char *fmt, ...)
1592     {
1593     va_list args;
1594     int error = -EPERM;
1595     int pos;
1596     int len;
1597     static unsigned int ccs_serial;
1598     struct ccs_query_entry *ccs_query_entry = NULL;
1599     bool quota_exceeded = false;
1600     char *header;
1601     if (!r->domain)
1602     r->domain = ccs_current_domain();
1603     if (!atomic_read(&ccs_query_observers)) {
1604     int i;
1605     if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)
1606     return -EPERM;
1607     for (i = 0; i < ccs_check_flags(r->domain, CCS_SLEEP_PERIOD);
1608     i++) {
1609     set_current_state(TASK_INTERRUPTIBLE);
1610     schedule_timeout(HZ / 10);
1611     }
1612     return -EPERM;
1613     }
1614     va_start(args, fmt);
1615     len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;
1616     va_end(args);
1617     header = ccs_init_audit_log(&len, r);
1618     if (!header)
1619     goto out;
1620     ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), GFP_KERNEL);
1621     if (!ccs_query_entry)
1622     goto out;
1623     ccs_query_entry->query = kzalloc(len, GFP_KERNEL);
1624     if (!ccs_query_entry->query)
1625     goto out;
1626     INIT_LIST_HEAD(&ccs_query_entry->list);
1627     /***** CRITICAL SECTION START *****/
1628     spin_lock(&ccs_query_list_lock);
1629     if (ccs_quota_for_query && ccs_query_memory_size + len +
1630     sizeof(*ccs_query_entry) >= ccs_quota_for_query) {
1631     quota_exceeded = true;
1632     } else {
1633     ccs_query_memory_size += len + sizeof(*ccs_query_entry);
1634     ccs_query_entry->serial = ccs_serial++;
1635     }
1636     spin_unlock(&ccs_query_list_lock);
1637     /***** CRITICAL SECTION END *****/
1638     if (quota_exceeded)
1639     goto out;
1640     pos = snprintf(ccs_query_entry->query, len - 1, "Q%u-%hu\n%s",
1641     ccs_query_entry->serial, r->retry, header);
1642     kfree(header);
1643     header = NULL;
1644     va_start(args, fmt);
1645     vsnprintf(ccs_query_entry->query + pos, len - 1 - pos, fmt, args);
1646     ccs_query_entry->query_len = strlen(ccs_query_entry->query) + 1;
1647     va_end(args);
1648     /***** CRITICAL SECTION START *****/
1649     spin_lock(&ccs_query_list_lock);
1650     list_add_tail(&ccs_query_entry->list, &ccs_query_list);
1651     spin_unlock(&ccs_query_list_lock);
1652     /***** CRITICAL SECTION END *****/
1653     /* Give 10 seconds for supervisor's opinion. */
1654     for (ccs_query_entry->timer = 0;
1655     atomic_read(&ccs_query_observers) && ccs_query_entry->timer < 100;
1656     ccs_query_entry->timer++) {
1657     wake_up(&ccs_query_wait);
1658     set_current_state(TASK_INTERRUPTIBLE);
1659     schedule_timeout(HZ / 10);
1660     if (ccs_query_entry->answer)
1661     break;
1662     }
1663     /***** CRITICAL SECTION START *****/
1664     spin_lock(&ccs_query_list_lock);
1665     list_del(&ccs_query_entry->list);
1666     ccs_query_memory_size -= len + sizeof(*ccs_query_entry);
1667     spin_unlock(&ccs_query_list_lock);
1668     /***** CRITICAL SECTION END *****/
1669     switch (ccs_query_entry->answer) {
1670     case 3: /* Asked to retry by administrator. */
1671     error = 1;
1672     r->retry++;
1673     break;
1674     case 1:
1675     /* Granted by administrator. */
1676     error = 0;
1677     break;
1678     case 0:
1679     /* Timed out. */
1680     break;
1681     default:
1682     /* Rejected by administrator. */
1683     break;
1684     }
1685     out:
1686     if (ccs_query_entry)
1687     kfree(ccs_query_entry->query);
1688     kfree(ccs_query_entry);
1689     kfree(header);
1690     return error;
1691     }
1692    
1693     /**
1694     * ccs_poll_query - poll() for /proc/ccs/query.
1695     *
1696     * @file: Pointer to "struct file".
1697     * @wait: Pointer to "poll_table".
1698     *
1699     * Returns POLLIN | POLLRDNORM when ready to read, 0 otherwise.
1700     *
1701     * Waits for access requests which violated policy in enforcing mode.
1702     */
1703     static int ccs_poll_query(struct file *file, poll_table *wait)
1704     {
1705     struct list_head *tmp;
1706     bool found = false;
1707     u8 i;
1708     for (i = 0; i < 2; i++) {
1709     /***** CRITICAL SECTION START *****/
1710     spin_lock(&ccs_query_list_lock);
1711     list_for_each(tmp, &ccs_query_list) {
1712     struct ccs_query_entry *ptr
1713     = list_entry(tmp, struct ccs_query_entry, list);
1714     if (ptr->answer)
1715     continue;
1716     found = true;
1717     break;
1718     }
1719     spin_unlock(&ccs_query_list_lock);
1720     /***** CRITICAL SECTION END *****/
1721     if (found)
1722     return POLLIN | POLLRDNORM;
1723     if (i)
1724     break;
1725     poll_wait(file, &ccs_query_wait, wait);
1726     }
1727     return 0;
1728     }
1729    
1730     /**
1731     * ccs_read_query - Read access requests which violated policy in enforcing mode.
1732     *
1733     * @head: Pointer to "struct ccs_io_buffer".
1734     *
1735     * Returns 0.
1736     */
1737     static int ccs_read_query(struct ccs_io_buffer *head)
1738     {
1739     struct list_head *tmp;
1740     int pos = 0;
1741     int len = 0;
1742     char *buf;
1743     if (head->read_avail)
1744     return 0;
1745     if (head->read_buf) {
1746     kfree(head->read_buf);
1747     head->read_buf = NULL;
1748     head->readbuf_size = 0;
1749     }
1750     /***** CRITICAL SECTION START *****/
1751     spin_lock(&ccs_query_list_lock);
1752     list_for_each(tmp, &ccs_query_list) {
1753     struct ccs_query_entry *ptr
1754     = list_entry(tmp, struct ccs_query_entry, list);
1755     if (ptr->answer)
1756     continue;
1757     if (pos++ != head->read_step)
1758     continue;
1759     len = ptr->query_len;
1760     break;
1761     }
1762     spin_unlock(&ccs_query_list_lock);
1763     /***** CRITICAL SECTION END *****/
1764     if (!len) {
1765     head->read_step = 0;
1766     return 0;
1767     }
1768     buf = kzalloc(len, GFP_KERNEL);
1769     if (!buf)
1770     return 0;
1771     pos = 0;
1772     /***** CRITICAL SECTION START *****/
1773     spin_lock(&ccs_query_list_lock);
1774     list_for_each(tmp, &ccs_query_list) {
1775     struct ccs_query_entry *ptr
1776     = list_entry(tmp, struct ccs_query_entry, list);
1777     if (ptr->answer)
1778     continue;
1779     if (pos++ != head->read_step)
1780     continue;
1781     /*
1782     * Some query can be skipped because ccs_query_list
1783     * can change, but I don't care.
1784     */
1785     if (len == ptr->query_len)
1786     memmove(buf, ptr->query, len);
1787     break;
1788     }
1789     spin_unlock(&ccs_query_list_lock);
1790     /***** CRITICAL SECTION END *****/
1791     if (buf[0]) {
1792     head->read_avail = len;
1793     head->readbuf_size = head->read_avail;
1794     head->read_buf = buf;
1795     head->read_step++;
1796     } else {
1797     kfree(buf);
1798     }
1799     return 0;
1800     }
1801    
1802     /**
1803     * ccs_write_answer - Write the supervisor's decision.
1804     *
1805     * @head: Pointer to "struct ccs_io_buffer".
1806     *
1807     * Returns 0 on success, -EINVAL otherwise.
1808     */
1809     static int ccs_write_answer(struct ccs_io_buffer *head)
1810     {
1811     char *data = head->write_buf;
1812     struct list_head *tmp;
1813     unsigned int serial;
1814     unsigned int answer;
1815     /***** CRITICAL SECTION START *****/
1816     spin_lock(&ccs_query_list_lock);
1817     list_for_each(tmp, &ccs_query_list) {
1818     struct ccs_query_entry *ptr
1819     = list_entry(tmp, struct ccs_query_entry, list);
1820     ptr->timer = 0;
1821     }
1822     spin_unlock(&ccs_query_list_lock);
1823     /***** CRITICAL SECTION END *****/
1824     if (sscanf(data, "A%u=%u", &serial, &answer) != 2)
1825     return -EINVAL;
1826     /***** CRITICAL SECTION START *****/
1827     spin_lock(&ccs_query_list_lock);
1828     list_for_each(tmp, &ccs_query_list) {
1829     struct ccs_query_entry *ptr
1830     = list_entry(tmp, struct ccs_query_entry, list);
1831     if (ptr->serial != serial)
1832     continue;
1833     if (!ptr->answer)
1834     ptr->answer = answer;
1835     break;
1836     }
1837     spin_unlock(&ccs_query_list_lock);
1838     /***** CRITICAL SECTION END *****/
1839     return 0;
1840     }
1841    
1842     /**
1843     * ccs_read_version: Get version.
1844     *
1845     * @head: Pointer to "struct ccs_io_buffer".
1846     *
1847     * Returns version information.
1848     */
1849     static int ccs_read_version(struct ccs_io_buffer *head)
1850     {
1851     if (!head->read_eof) {
1852     ccs_io_printf(head, "1.7.0-pre");
1853     head->read_eof = true;
1854     }
1855     return 0;
1856     }
1857    
1858     /**
1859     * ccs_read_self_domain - Get the current process's domainname.
1860     *
1861     * @head: Pointer to "struct ccs_io_buffer".
1862     *
1863     * Returns the current process's domainname.
1864     */
1865     static int ccs_read_self_domain(struct ccs_io_buffer *head)
1866     {
1867     if (!head->read_eof) {
1868     /*
1869     * ccs_current_domain()->domainname != NULL
1870     * because every process belongs to a domain and
1871     * the domain's name cannot be NULL.
1872     */
1873     ccs_io_printf(head, "%s",
1874     ccs_current_domain()->domainname->name);
1875     head->read_eof = true;
1876     }
1877     return 0;
1878     }
1879    
1880     /**
1881     * ccs_open_control - open() for /proc/ccs/ interface.
1882     *
1883     * @type: Type of interface.
1884     * @file: Pointer to "struct file".
1885     *
1886     * Associates policy handler and returns 0 on success, -ENOMEM otherwise.
1887     */
1888     int ccs_open_control(const u8 type, struct file *file)
1889     {
1890     struct ccs_io_buffer *head = kzalloc(sizeof(*head), GFP_KERNEL);
1891     if (!head)
1892     return -ENOMEM;
1893     mutex_init(&head->io_sem);
1894     head->type = type;
1895     switch (type) {
1896     case CCS_DOMAINPOLICY: /* /proc/ccs/domain_policy */
1897     head->write = ccs_write_domain_policy;
1898     head->read = ccs_read_domain_policy;
1899     break;
1900     case CCS_EXCEPTIONPOLICY: /* /proc/ccs/exception_policy */
1901     head->write = ccs_write_exception_policy;
1902     head->read = ccs_read_exception_policy;
1903     break;
1904     #ifdef CONFIG_CCSECURITY_AUDIT
1905     case CCS_GRANTLOG: /* /proc/ccs/grant_log */
1906     head->poll = ccs_poll_grant_log;
1907     head->read = ccs_read_grant_log;
1908     break;
1909     case CCS_REJECTLOG: /* /proc/ccs/reject_log */
1910     head->poll = ccs_poll_reject_log;
1911     head->read = ccs_read_reject_log;
1912     break;
1913     #endif
1914     case CCS_SELFDOMAIN: /* /proc/ccs/self_domain */
1915     head->read = ccs_read_self_domain;
1916     break;
1917     case CCS_DOMAIN_STATUS: /* /proc/ccs/.domain_status */
1918     head->write = ccs_write_domain_profile;
1919     head->read = ccs_read_domain_profile;
1920     break;
1921     case CCS_EXECUTE_HANDLER: /* /proc/ccs/.execute_handler */
1922     /* Allow execute_handler to read process's status. */
1923     if (!(current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {
1924     kfree(head);
1925     return -EPERM;
1926     }
1927     /* fall through */
1928     case CCS_PROCESS_STATUS: /* /proc/ccs/.process_status */
1929     head->write = ccs_write_pid;
1930     head->read = ccs_read_pid;
1931     break;
1932     case CCS_VERSION: /* /proc/ccs/version */
1933     head->read = ccs_read_version;
1934     head->readbuf_size = 128;
1935     break;
1936     case CCS_MEMINFO: /* /proc/ccs/meminfo */
1937     head->write = ccs_write_memory_quota;
1938     head->read = ccs_read_memory_counter;
1939     head->readbuf_size = 512;
1940     break;
1941     case CCS_PROFILE: /* /proc/ccs/profile */
1942     head->write = ccs_write_profile;
1943     head->read = ccs_read_profile;
1944     break;
1945     case CCS_QUERY: /* /proc/ccs/query */
1946     head->poll = ccs_poll_query;
1947     head->write = ccs_write_answer;
1948     head->read = ccs_read_query;
1949     break;
1950     case CCS_MANAGER: /* /proc/ccs/manager */
1951     head->write = ccs_write_manager_policy;
1952     head->read = ccs_read_manager_policy;
1953     break;
1954     }
1955     if (!(file->f_mode & FMODE_READ)) {
1956     /*
1957     * No need to allocate read_buf since it is not opened
1958     * for reading.
1959     */
1960     head->read = NULL;
1961     head->poll = NULL;
1962     } else if (type != CCS_QUERY &&
1963     type != CCS_GRANTLOG && type != CCS_REJECTLOG) {
1964     /*
1965     * Don't allocate buffer for reading if the file is one of
1966     * /proc/ccs/grant_log , /proc/ccs/reject_log , /proc/ccs/query.
1967     */
1968     if (!head->readbuf_size)
1969     head->readbuf_size = 4096 * 2;
1970     head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL);
1971     if (!head->read_buf) {
1972     kfree(head);
1973     return -ENOMEM;
1974     }
1975     }
1976     if (!(file->f_mode & FMODE_WRITE)) {
1977     /*
1978     * No need to allocate write_buf since it is not opened
1979     * for writing.
1980     */
1981     head->write = NULL;
1982     } else if (head->write) {
1983     head->writebuf_size = 4096 * 2;
1984     head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL);
1985     if (!head->write_buf) {
1986     kfree(head->read_buf);
1987     kfree(head);
1988     return -ENOMEM;
1989     }
1990     }
1991     if (type != CCS_QUERY &&
1992     type != CCS_GRANTLOG && type != CCS_REJECTLOG)
1993     head->reader_idx = ccs_read_lock();
1994     file->private_data = head;
1995     /*
1996     * Call the handler now if the file is /proc/ccs/self_domain
1997     * so that the user can use "cat < /proc/ccs/self_domain" to
1998     * know the current process's domainname.
1999     */
2000     if (type == CCS_SELFDOMAIN)
2001     ccs_read_control(file, NULL, 0);
2002     /*
2003     * If the file is /proc/ccs/query , increment the observer counter.
2004     * The obserber counter is used by ccs_check_supervisor() to see if
2005     * there is some process monitoring /proc/ccs/query.
2006     */
2007     else if (type == CCS_QUERY)
2008     atomic_inc(&ccs_query_observers);
2009     return 0;
2010     }
2011    
2012     /**
2013     * ccs_poll_control - poll() for /proc/ccs/ interface.
2014     *
2015     * @file: Pointer to "struct file".
2016     * @wait: Pointer to "poll_table".
2017     *
2018     * Waits for read readiness.
2019     * /proc/ccs/query is handled by /usr/lib/ccs/ccs-queryd and
2020     * /proc/ccs/grant_log and /proc/ccs/reject_log are handled by
2021     * /usr/lib/ccs/ccs-auditd.
2022     */
2023     int ccs_poll_control(struct file *file, poll_table *wait)
2024     {
2025     struct ccs_io_buffer *head = file->private_data;
2026     if (!head->poll)
2027     return -ENOSYS;
2028     return head->poll(file, wait);
2029     }
2030    
2031     /**
2032     * ccs_read_control - read() for /proc/ccs/ interface.
2033     *
2034     * @file: Pointer to "struct file".
2035     * @buffer: Poiner to buffer to write to.
2036     * @buffer_len: Size of @buffer.
2037     *
2038     * Returns bytes read on success, negative value otherwise.
2039     */
2040     int ccs_read_control(struct file *file, char __user *buffer,
2041     const int buffer_len)
2042     {
2043     int len = 0;
2044     struct ccs_io_buffer *head = file->private_data;
2045     char *cp;
2046     if (!head->read)
2047     return -ENOSYS;
2048     if (!access_ok(VERIFY_WRITE, buffer, buffer_len))
2049     return -EFAULT;
2050     if (mutex_lock_interruptible(&head->io_sem))
2051     return -EINTR;
2052     /* Call the policy handler. */
2053     len = head->read(head);
2054     if (len < 0)
2055     goto out;
2056     /* Write to buffer. */
2057     len = head->read_avail;
2058     if (len > buffer_len)
2059     len = buffer_len;
2060     if (!len)
2061     goto out;
2062     /* head->read_buf changes by some functions. */
2063     cp = head->read_buf;
2064     if (copy_to_user(buffer, cp, len)) {
2065     len = -EFAULT;
2066     goto out;
2067     }
2068     head->read_avail -= len;
2069     memmove(cp, cp + len, head->read_avail);
2070     out:
2071     mutex_unlock(&head->io_sem);
2072     return len;
2073     }
2074    
2075     /**
2076     * ccs_write_control - write() for /proc/ccs/ interface.
2077     *
2078     * @file: Pointer to "struct file".
2079     * @buffer: Pointer to buffer to read from.
2080     * @buffer_len: Size of @buffer.
2081     *
2082     * Returns @buffer_len on success, negative value otherwise.
2083     */
2084     int ccs_write_control(struct file *file, const char __user *buffer,
2085     const int buffer_len)
2086     {
2087     struct ccs_io_buffer *head = file->private_data;
2088     int error = buffer_len;
2089     int avail_len = buffer_len;
2090     char *cp0 = head->write_buf;
2091     if (!head->write)
2092     return -ENOSYS;
2093     if (!access_ok(VERIFY_READ, buffer, buffer_len))
2094     return -EFAULT;
2095     /* Don't allow updating policies by non manager programs. */
2096     if (head->write != ccs_write_pid &&
2097     head->write != ccs_write_domain_policy &&
2098     !ccs_is_policy_manager())
2099     return -EPERM;
2100     if (mutex_lock_interruptible(&head->io_sem))
2101     return -EINTR;
2102     /* Read a line and dispatch it to the policy handler. */
2103     while (avail_len > 0) {
2104     char c;
2105     if (head->write_avail >= head->writebuf_size - 1) {
2106     error = -ENOMEM;
2107     break;
2108     } else if (get_user(c, buffer)) {
2109     error = -EFAULT;
2110     break;
2111     }
2112     buffer++;
2113     avail_len--;
2114     cp0[head->write_avail++] = c;
2115     if (c != '\n')
2116     continue;
2117     cp0[head->write_avail - 1] = '\0';
2118     head->write_avail = 0;
2119     ccs_normalize_line(cp0);
2120     head->write(head);
2121     }
2122     mutex_unlock(&head->io_sem);
2123     return error;
2124     }
2125    
2126     /**
2127     * ccs_close_control - close() for /proc/ccs/ interface.
2128     *
2129     * @file: Pointer to "struct file".
2130     *
2131     * Releases memory and returns 0.
2132     */
2133     int ccs_close_control(struct file *file)
2134     {
2135     struct ccs_io_buffer *head = file->private_data;
2136     const bool is_write = head->write_buf != NULL;
2137     const u8 type = head->type;
2138     /*
2139     * If the file is /proc/ccs/query , decrement the observer counter.
2140     */
2141     if (type == CCS_QUERY)
2142     atomic_dec(&ccs_query_observers);
2143     if (type != CCS_QUERY &&
2144     type != CCS_GRANTLOG && type != CCS_REJECTLOG)
2145     ccs_read_unlock(head->reader_idx);
2146     /* Release memory used for policy I/O. */
2147     kfree(head->read_buf);
2148     head->read_buf = NULL;
2149     kfree(head->write_buf);
2150     head->write_buf = NULL;
2151     kfree(head);
2152     head = NULL;
2153     file->private_data = NULL;
2154     if (is_write)
2155     ccs_run_gc();
2156     return 0;
2157     }

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