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

Subversion リポジトリの参照

Annotation of /trunk/1.7.x/ccs-patch/security/ccsecurity/util.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1005 - (hide annotations) (download) (as text)
Mon Feb 25 04:57:38 2008 UTC (16 years, 3 months ago) by kumaneko
Original Path: trunk/1.6.x/ccs-patch/fs/ccs_common.c
File MIME type: text/x-csrc
File size: 56476 byte(s)


1 kumaneko 111 /*
2     * fs/ccs_common.c
3     *
4     * Common functions for SAKURA and TOMOYO.
5     *
6 kumaneko 849 * Copyright (C) 2005-2008 NTT DATA CORPORATION
7 kumaneko 111 *
8 kumaneko 1005 * Version: 1.6.0-pre 2008/02/25
9 kumaneko 111 *
10     * This file is applicable to both 2.4.30 and 2.6.11 and later.
11     * See README.ccs for ChangeLog.
12     *
13     */
14    
15     #include <linux/string.h>
16     #include <linux/mm.h>
17     #include <linux/utime.h>
18     #include <linux/file.h>
19     #include <linux/module.h>
20     #include <linux/slab.h>
21     #include <asm/uaccess.h>
22     #include <stdarg.h>
23     #include <linux/version.h>
24     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
25     #include <linux/namei.h>
26     #include <linux/mount.h>
27     static const int lookup_flags = LOOKUP_FOLLOW;
28     #else
29     static const int lookup_flags = LOOKUP_FOLLOW | LOOKUP_POSITIVE;
30     #endif
31     #include <linux/realpath.h>
32     #include <linux/ccs_common.h>
33     #include <linux/ccs_proc.h>
34     #include <linux/tomoyo.h>
35 kumaneko 964 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
36     #define find_task_by_pid find_task_by_vpid
37     #endif
38 kumaneko 111
39 kumaneko 120 #ifdef CONFIG_TOMOYO_MAX_ACCEPT_ENTRY
40     #define MAX_ACCEPT_ENTRY (CONFIG_TOMOYO_MAX_ACCEPT_ENTRY)
41 kumaneko 111 #else
42 kumaneko 120 #define MAX_ACCEPT_ENTRY 2048
43 kumaneko 111 #endif
44     #ifdef CONFIG_TOMOYO_MAX_GRANT_LOG
45     #define MAX_GRANT_LOG (CONFIG_TOMOYO_MAX_GRANT_LOG)
46     #else
47     #define MAX_GRANT_LOG 1024
48     #endif
49     #ifdef CONFIG_TOMOYO_MAX_REJECT_LOG
50     #define MAX_REJECT_LOG (CONFIG_TOMOYO_MAX_REJECT_LOG)
51     #else
52     #define MAX_REJECT_LOG 1024
53     #endif
54    
55     /************************* VARIABLES *************************/
56    
57     /* /sbin/init started? */
58 kumaneko 853 bool sbin_init_started = 0;
59 kumaneko 111
60     const char *ccs_log_level = KERN_DEBUG;
61    
62     static struct {
63     const char *keyword;
64     unsigned int current_value;
65     const unsigned int max_value;
66     } ccs_control_array[CCS_MAX_CONTROL_INDEX] = {
67     [CCS_PROFILE_COMMENT] = { "COMMENT", 0, 0 }, /* Reserved for string. */
68     [CCS_TOMOYO_MAC_FOR_FILE] = { "MAC_FOR_FILE", 0, 3 },
69     [CCS_TOMOYO_MAC_FOR_ARGV0] = { "MAC_FOR_ARGV0", 0, 3 },
70 kumaneko 581 [CCS_TOMOYO_MAC_FOR_ENV] = { "MAC_FOR_ENV", 0, 3 },
71 kumaneko 111 [CCS_TOMOYO_MAC_FOR_NETWORK] = { "MAC_FOR_NETWORK", 0, 3 },
72     [CCS_TOMOYO_MAC_FOR_SIGNAL] = { "MAC_FOR_SIGNAL", 0, 3 },
73     [CCS_SAKURA_DENY_CONCEAL_MOUNT] = { "DENY_CONCEAL_MOUNT", 0, 3 },
74     [CCS_SAKURA_RESTRICT_CHROOT] = { "RESTRICT_CHROOT", 0, 3 },
75     [CCS_SAKURA_RESTRICT_MOUNT] = { "RESTRICT_MOUNT", 0, 3 },
76     [CCS_SAKURA_RESTRICT_UNMOUNT] = { "RESTRICT_UNMOUNT", 0, 3 },
77 kumaneko 141 [CCS_SAKURA_RESTRICT_PIVOT_ROOT] = { "RESTRICT_PIVOT_ROOT", 0, 3 },
78 kumaneko 111 [CCS_SAKURA_RESTRICT_AUTOBIND] = { "RESTRICT_AUTOBIND", 0, 1 },
79 kumaneko 120 [CCS_TOMOYO_MAX_ACCEPT_ENTRY] = { "MAX_ACCEPT_ENTRY", MAX_ACCEPT_ENTRY, INT_MAX },
80 kumaneko 111 [CCS_TOMOYO_MAX_GRANT_LOG] = { "MAX_GRANT_LOG", MAX_GRANT_LOG, INT_MAX },
81     [CCS_TOMOYO_MAX_REJECT_LOG] = { "MAX_REJECT_LOG", MAX_REJECT_LOG, INT_MAX },
82     [CCS_TOMOYO_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 },
83     [CCS_ALLOW_ENFORCE_GRACE] = { "ALLOW_ENFORCE_GRACE", 0, 1 },
84 kumaneko 708 [CCS_SLEEP_PERIOD] = { "SLEEP_PERIOD", 0, 3000 }, /* in 0.1 second */
85     [CCS_TOMOYO_ALT_EXEC] = { "ALT_EXEC", 0, 0 }, /* Reserved for string. */
86 kumaneko 111 };
87    
88 kumaneko 214 struct profile {
89 kumaneko 111 unsigned int value[CCS_MAX_CONTROL_INDEX];
90     const struct path_info *comment;
91 kumaneko 708 const struct path_info *alt_exec;
92 kumaneko 214 };
93 kumaneko 111
94 kumaneko 214 static struct profile *profile_ptr[MAX_PROFILES];
95 kumaneko 111
96     /************************* UTILITY FUNCTIONS *************************/
97    
98     #ifdef CONFIG_TOMOYO
99     static int __init TOMOYO_Quiet_Setup(char *str)
100     {
101     ccs_control_array[CCS_TOMOYO_VERBOSE].current_value = 0;
102     return 0;
103     }
104    
105     __setup("TOMOYO_QUIET", TOMOYO_Quiet_Setup);
106     #endif
107    
108     /* Am I root? */
109 kumaneko 921 static int isRoot(struct io_buffer *head)
110 kumaneko 111 {
111 kumaneko 921 const struct task_struct *task = current;
112 kumaneko 924 return (!task->uid && !task->euid) || (task->uid && task->uid == head->uid) || (task->gid && task->gid == head->gid);
113 kumaneko 111 }
114    
115     /*
116     * Format string.
117     * Leading and trailing whitespaces are removed.
118     * Multiple whitespaces are packed into single space.
119     */
120     static void NormalizeLine(unsigned char *buffer)
121     {
122     unsigned char *sp = buffer, *dp = buffer;
123     int first = 1;
124     while (*sp && (*sp <= ' ' || *sp >= 127)) sp++;
125     while (*sp) {
126     if (!first) *dp++ = ' ';
127     first = 0;
128     while (*sp > ' ' && *sp < 127) *dp++ = *sp++;
129     while (*sp && (*sp <= ' ' || *sp >= 127)) sp++;
130     }
131     *dp = '\0';
132     }
133    
134     /*
135     * Check whether the given filename follows the naming rules.
136     * Returns nonzero if follows, zero otherwise.
137     */
138 kumaneko 853 bool IsCorrectPath(const char *filename, const s8 start_type, const s8 pattern_type, const s8 end_type, const char *function)
139 kumaneko 111 {
140     int contains_pattern = 0;
141     char c, d, e;
142     const char *original_filename = filename;
143     if (!filename) goto out;
144     c = *filename;
145     if (start_type == 1) { /* Must start with '/' */
146     if (c != '/') goto out;
147     } else if (start_type == -1) { /* Must not start with '/' */
148     if (c == '/') goto out;
149     }
150     if (c) c = * (strchr(filename, '\0') - 1);
151     if (end_type == 1) { /* Must end with '/' */
152     if (c != '/') goto out;
153     } else if (end_type == -1) { /* Must not end with '/' */
154     if (c == '/') goto out;
155     }
156     while ((c = *filename++) != '\0') {
157     if (c == '\\') {
158     switch ((c = *filename++)) {
159     case '\\': /* "\\" */
160     continue;
161     case '$': /* "\$" */
162     case '+': /* "\+" */
163     case '?': /* "\?" */
164     case '*': /* "\*" */
165     case '@': /* "\@" */
166     case 'x': /* "\x" */
167     case 'X': /* "\X" */
168     case 'a': /* "\a" */
169     case 'A': /* "\A" */
170 kumaneko 206 case '-': /* "\-" */
171 kumaneko 111 if (pattern_type == -1) break; /* Must not contain pattern */
172     contains_pattern = 1;
173     continue;
174     case '0': /* "\ooo" */
175     case '1':
176     case '2':
177     case '3':
178     if ((d = *filename++) >= '0' && d <= '7' && (e = *filename++) >= '0' && e <= '7') {
179     const unsigned char f =
180     (((unsigned char) (c - '0')) << 6) +
181     (((unsigned char) (d - '0')) << 3) +
182     (((unsigned char) (e - '0')));
183     if (f && (f <= ' ' || f >= 127)) continue; /* pattern is not \000 */
184     }
185     }
186     goto out;
187     } else if (c <= ' ' || c >= 127) {
188     goto out;
189     }
190     }
191     if (pattern_type == 1) { /* Must contain pattern */
192     if (!contains_pattern) goto out;
193     }
194     return 1;
195     out:
196     printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function, original_filename);
197     return 0;
198     }
199    
200     /*
201     * Check whether the given domainname follows the naming rules.
202     * Returns nonzero if follows, zero otherwise.
203     */
204 kumaneko 621 bool IsCorrectDomain(const unsigned char *domainname, const char *function)
205 kumaneko 111 {
206     unsigned char c, d, e;
207     const char *org_domainname = domainname;
208     if (!domainname || strncmp(domainname, ROOT_NAME, ROOT_NAME_LEN)) goto out;
209     domainname += ROOT_NAME_LEN;
210     if (!*domainname) return 1;
211     do {
212     if (*domainname++ != ' ') goto out;
213     if (*domainname++ != '/') goto out;
214     while ((c = *domainname) != '\0' && c != ' ') {
215     domainname++;
216     if (c == '\\') {
217     switch ((c = *domainname++)) {
218     case '\\': /* "\\" */
219     continue;
220     case '0': /* "\ooo" */
221     case '1':
222     case '2':
223     case '3':
224     if ((d = *domainname++) >= '0' && d <= '7' && (e = *domainname++) >= '0' && e <= '7') {
225     const unsigned char f =
226     (((unsigned char) (c - '0')) << 6) +
227     (((unsigned char) (d - '0')) << 3) +
228     (((unsigned char) (e - '0')));
229     if (f && (f <= ' ' || f >= 127)) continue; /* pattern is not \000 */
230     }
231     }
232     goto out;
233     } else if (c < ' ' || c >= 127) {
234     goto out;
235     }
236     }
237     } while (*domainname);
238     return 1;
239     out:
240     printk(KERN_DEBUG "%s: Invalid domainname '%s'\n", function, org_domainname);
241     return 0;
242     }
243    
244 kumaneko 621 bool IsDomainDef(const unsigned char *buffer)
245 kumaneko 461 {
246     /* while (*buffer && (*buffer <= ' ' || *buffer >= 127)) buffer++; */
247     return strncmp(buffer, ROOT_NAME, ROOT_NAME_LEN) == 0;
248     }
249    
250     struct domain_info *FindDomain(const char *domainname0)
251     {
252     struct domain_info *domain;
253     struct path_info domainname;
254     domainname.name = domainname0;
255     fill_path_info(&domainname);
256 kumaneko 722 list1_for_each_entry(domain, &domain_list, list) {
257 kumaneko 461 if (!domain->is_deleted && !pathcmp(&domainname, domain->domainname)) return domain;
258     }
259     return NULL;
260     }
261    
262 kumaneko 111 static int PathDepth(const char *pathname)
263     {
264     int i = 0;
265     if (pathname) {
266     char *ep = strchr(pathname, '\0');
267     if (pathname < ep--) {
268     if (*ep != '/') i++;
269     while (pathname <= ep) if (*ep-- == '/') i += 2;
270     }
271     }
272     return i;
273     }
274    
275     static int const_part_length(const char *filename)
276     {
277     int len = 0;
278     if (filename) {
279     char c;
280     while ((c = *filename++) != '\0') {
281     if (c != '\\') { len++; continue; }
282     switch (c = *filename++) {
283     case '\\': /* "\\" */
284     len += 2; continue;
285     case '0': /* "\ooo" */
286     case '1':
287     case '2':
288     case '3':
289     if ((c = *filename++) >= '0' && c <= '7' && (c = *filename++) >= '0' && c <= '7') { len += 4; continue; }
290     }
291     break;
292     }
293     }
294     return len;
295     }
296    
297     void fill_path_info(struct path_info *ptr)
298     {
299     const char *name = ptr->name;
300     const int len = strlen(name);
301     ptr->total_len = len;
302     ptr->const_len = const_part_length(name);
303     ptr->is_dir = len && (name[len - 1] == '/');
304     ptr->is_patterned = (ptr->const_len < len);
305     ptr->hash = full_name_hash(name, len);
306     ptr->depth = PathDepth(name);
307     }
308    
309 kumaneko 206 static int FileMatchesToPattern2(const char *filename, const char *filename_end, const char *pattern, const char *pattern_end)
310 kumaneko 111 {
311     while (filename < filename_end && pattern < pattern_end) {
312     if (*pattern != '\\') {
313     if (*filename++ != *pattern++) return 0;
314     } else {
315     char c = *filename;
316     pattern++;
317     switch (*pattern) {
318     case '?':
319     if (c == '/') {
320     return 0;
321     } else if (c == '\\') {
322     if ((c = filename[1]) == '\\') {
323     filename++; /* safe because filename is \\ */
324     } else if (c >= '0' && c <= '3' && (c = filename[2]) >= '0' && c <= '7' && (c = filename[3]) >= '0' && c <= '7') {
325     filename += 3; /* safe because filename is \ooo */
326     } else {
327     return 0;
328     }
329     }
330     break;
331     case '\\':
332     if (c != '\\') return 0;
333     if (*++filename != '\\') return 0; /* safe because *filename != '\0' */
334     break;
335     case '+':
336     if (c < '0' || c > '9') return 0;
337     break;
338     case 'x':
339     if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))) return 0;
340     break;
341     case 'a':
342     if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))) return 0;
343     break;
344     case '0':
345     case '1':
346     case '2':
347     case '3':
348     if (c == '\\' && (c = filename[1]) >= '0' && c <= '3' && c == *pattern
349     && (c = filename[2]) >= '0' && c <= '7' && c == pattern[1]
350     && (c = filename[3]) >= '0' && c <= '7' && c == pattern[2]) {
351     filename += 3; /* safe because filename is \ooo */
352     pattern += 2; /* safe because pattern is \ooo */
353     break;
354     }
355     return 0; /* Not matched. */
356     case '*':
357     case '@':
358     {
359     int i;
360     for (i = 0; i <= filename_end - filename; i++) {
361 kumaneko 206 if (FileMatchesToPattern2(filename + i, filename_end, pattern + 1, pattern_end)) return 1;
362 kumaneko 111 if ((c = filename[i]) == '.' && *pattern == '@') break;
363     if (c == '\\') {
364     if ((c = filename[i + 1]) == '\\') {
365     i++; /* safe because filename is \\ */
366     } else if (c >= '0' && c <= '3' && (c = filename[i + 2]) >= '0' && c <= '7' && (c = filename[i + 3]) >= '0' && c <= '7') {
367     i += 3; /* safe because filename is \ooo */
368     } else {
369     break; /* Bad pattern. */
370     }
371     }
372     }
373     return 0; /* Not matched. */
374     }
375     default:
376     {
377     int i, j = 0;
378     if ((c = *pattern) == '$') {
379     while ((c = filename[j]) >= '0' && c <= '9') j++;
380     } else if (c == 'X') {
381     while (((c = filename[j]) >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) j++;
382     } else if (c == 'A') {
383     while (((c = filename[j]) >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) j++;
384     }
385     for (i = 1; i <= j; i++) {
386 kumaneko 206 if (FileMatchesToPattern2(filename + i, filename_end, pattern + 1, pattern_end)) return 1;
387 kumaneko 111 }
388     }
389     return 0; /* Not matched or bad pattern. */
390     }
391     filename++; /* safe because *filename != '\0' */
392     pattern++; /* safe because *pattern != '\0' */
393     }
394     }
395     while (*pattern == '\\' && (*(pattern + 1) == '*' || *(pattern + 1) == '@')) pattern += 2;
396     return (filename == filename_end && pattern == pattern_end);
397     }
398    
399 kumaneko 206 static int FileMatchesToPattern(const char *filename, const char *filename_end, const char *pattern, const char *pattern_end)
400     {
401     const char *pattern_start = pattern;
402     int first = 1;
403     int result;
404     while (pattern < pattern_end - 1) {
405     if (*pattern++ != '\\' || *pattern++ != '-') continue;
406     result = FileMatchesToPattern2(filename, filename_end, pattern_start, pattern - 2);
407     if (first) result = !result;
408     if (result) return 0;
409     first = 0;
410     pattern_start = pattern;
411     }
412     result = FileMatchesToPattern2(filename, filename_end, pattern_start, pattern_end);
413     return first ? result : !result;
414     }
415    
416 kumaneko 111 /*
417     * Check whether the given pathname matches to the given pattern.
418     * Returns nonzero if matches, zero otherwise.
419     *
420     * The following patterns are available.
421     * \\ \ itself.
422     * \ooo Octal representation of a byte.
423     * \* More than or equals to 0 character other than '/'.
424     * \@ More than or equals to 0 character other than '/' or '.'.
425     * \? 1 byte character other than '/'.
426     * \$ More than or equals to 1 decimal digit.
427     * \+ 1 decimal digit.
428     * \X More than or equals to 1 hexadecimal digit.
429     * \x 1 hexadecimal digit.
430     * \A More than or equals to 1 alphabet character.
431     * \a 1 alphabet character.
432 kumaneko 206 * \- Subtraction operator.
433 kumaneko 111 */
434    
435     int PathMatchesToPattern(const struct path_info *pathname0, const struct path_info *pattern0)
436     {
437 kumaneko 240 /* if (!pathname || !pattern) return 0; */
438 kumaneko 111 const char *pathname = pathname0->name, *pattern = pattern0->name;
439     const int len = pattern0->const_len;
440     if (!pattern0->is_patterned) return !pathcmp(pathname0, pattern0);
441     if (pathname0->depth != pattern0->depth) return 0;
442     if (strncmp(pathname, pattern, len)) return 0;
443     pathname += len; pattern += len;
444     while (*pathname && *pattern) {
445     const char *pathname_delimiter = strchr(pathname, '/'), *pattern_delimiter = strchr(pattern, '/');
446     if (!pathname_delimiter) pathname_delimiter = strchr(pathname, '\0');
447     if (!pattern_delimiter) pattern_delimiter = strchr(pattern, '\0');
448     if (!FileMatchesToPattern(pathname, pathname_delimiter, pattern, pattern_delimiter)) return 0;
449     pathname = *pathname_delimiter ? pathname_delimiter + 1 : pathname_delimiter;
450     pattern = *pattern_delimiter ? pattern_delimiter + 1 : pattern_delimiter;
451     }
452     while (*pattern == '\\' && (*(pattern + 1) == '*' || *(pattern + 1) == '@')) pattern += 2;
453     return (!*pathname && !*pattern);
454     }
455    
456     /*
457 kumaneko 214 * Transactional printf() to struct io_buffer structure.
458 kumaneko 111 * snprintf() will truncate, but io_printf() won't.
459     * Returns zero on success, nonzero otherwise.
460     */
461 kumaneko 214 int io_printf(struct io_buffer *head, const char *fmt, ...)
462 kumaneko 111 {
463     va_list args;
464     int len, pos = head->read_avail, size = head->readbuf_size - pos;
465     if (size <= 0) return -ENOMEM;
466     va_start(args, fmt);
467     len = vsnprintf(head->read_buf + pos, size, fmt, args);
468     va_end(args);
469     if (pos + len >= head->readbuf_size) return -ENOMEM;
470     head->read_avail += len;
471     return 0;
472     }
473    
474     /*
475     * Get realpath() of current process.
476     * This function uses ccs_alloc(), so caller must ccs_free() if this function didn't return NULL.
477     */
478     const char *GetEXE(void)
479     {
480 kumaneko 737 struct mm_struct *mm = current->mm;
481     struct vm_area_struct *vma;
482     const char *cp = NULL;
483     if (!mm) return NULL;
484     down_read(&mm->mmap_sem);
485     for (vma = mm->mmap; vma; vma = vma->vm_next) {
486     if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
487     cp = realpath_from_dentry(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt);
488     break;
489 kumaneko 111 }
490     }
491 kumaneko 737 up_read(&mm->mmap_sem);
492     return cp;
493 kumaneko 111 }
494    
495 kumaneko 621 const char *GetMSG(const bool is_enforce)
496 kumaneko 111 {
497     if (is_enforce) return "ERROR"; else return "WARNING";
498     }
499    
500 kumaneko 708 const char *GetAltExec(void)
501     {
502     const u8 profile = current->domain_info->profile;
503     const struct path_info *alt_exec = profile_ptr[profile] ? profile_ptr[profile]->alt_exec : NULL;
504     return alt_exec ? alt_exec->name : NULL;
505     }
506    
507 kumaneko 111 /************************* DOMAIN POLICY HANDLER *************************/
508    
509     /* Check whether the given access control is enabled. */
510 kumaneko 899 unsigned int CheckCCSFlags_NoSleepCheck(const u8 index)
511 kumaneko 111 {
512     const u8 profile = current->domain_info->profile;
513 kumaneko 121 return sbin_init_started && index < CCS_MAX_CONTROL_INDEX
514     #if MAX_PROFILES != 256
515     && profile < MAX_PROFILES
516     #endif
517     && profile_ptr[profile] ? profile_ptr[profile]->value[index] : 0;
518 kumaneko 111 }
519    
520 kumaneko 899 unsigned int CheckCCSFlags(const u8 index)
521     {
522     #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
523     if (unlikely(in_interrupt()))
524     #else
525     if (unlikely(in_atomic()))
526     #endif
527     {
528     static u8 count = 20;
529     if (count) {
530     count--;
531     printk(KERN_ERR "BUG: sleeping function called from invalid context.\n");
532     dump_stack();
533     }
534     /* Return 0 so that no MAC checks are performed. */
535     return 0;
536     }
537     return CheckCCSFlags_NoSleepCheck(index);
538     }
539    
540 kumaneko 621 bool TomoyoVerboseMode(void)
541 kumaneko 111 {
542 kumaneko 621 return CheckCCSFlags(CCS_TOMOYO_VERBOSE) != 0;
543 kumaneko 111 }
544    
545 kumaneko 621 bool CheckDomainQuota(struct domain_info * const domain)
546 kumaneko 512 {
547     unsigned int count = 0;
548     struct acl_info *ptr;
549     if (!domain) return 1;
550 kumaneko 722 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
551 kumaneko 906 if (!(ptr->type & ACL_DELETED)) count++;
552 kumaneko 512 }
553     if (count < CheckCCSFlags(CCS_TOMOYO_MAX_ACCEPT_ENTRY)) return 1;
554     if (!domain->quota_warned) {
555     domain->quota_warned = 1;
556     printk("TOMOYO-WARNING: Domain '%s' has so many ACLs to hold. Stopped learning mode.\n", domain->domainname->name);
557     }
558     return 0;
559     }
560    
561 kumaneko 214 static struct profile *FindOrAssignNewProfile(const unsigned int profile)
562 kumaneko 111 {
563 kumaneko 652 static DEFINE_MUTEX(profile_lock);
564 kumaneko 214 struct profile *ptr = NULL;
565 kumaneko 652 mutex_lock(&profile_lock);
566 kumaneko 111 if (profile < MAX_PROFILES && (ptr = profile_ptr[profile]) == NULL) {
567 kumaneko 214 if ((ptr = alloc_element(sizeof(*ptr))) != NULL) {
568 kumaneko 111 int i;
569     for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++) ptr->value[i] = ccs_control_array[i].current_value;
570 kumaneko 708 mb(); /* Avoid out-of-order execution. */
571 kumaneko 111 profile_ptr[profile] = ptr;
572     }
573     }
574 kumaneko 652 mutex_unlock(&profile_lock);
575 kumaneko 111 return ptr;
576     }
577    
578 kumaneko 740 /* #define ALT_EXEC */
579    
580 kumaneko 418 static int SetProfile(struct io_buffer *head)
581 kumaneko 111 {
582     char *data = head->write_buf;
583     unsigned int i, value;
584     char *cp;
585 kumaneko 214 struct profile *profile;
586 kumaneko 921 if (!isRoot(head)) return -EPERM;
587 kumaneko 111 i = simple_strtoul(data, &cp, 10);
588     if (data != cp) {
589     if (*cp != '-') return -EINVAL;
590     data= cp + 1;
591     }
592     profile = FindOrAssignNewProfile(i);
593     if (!profile) return -EINVAL;
594     cp = strchr(data, '=');
595     if (!cp) return -EINVAL;
596     *cp = '\0';
597 kumaneko 418 UpdateCounter(CCS_UPDATES_COUNTER_PROFILE);
598 kumaneko 111 if (strcmp(data, ccs_control_array[CCS_PROFILE_COMMENT].keyword) == 0) {
599     profile->comment = SaveName(cp + 1);
600     return 0;
601     }
602 kumaneko 740 #ifdef ALT_EXEC
603 kumaneko 708 #ifdef CONFIG_TOMOYO
604     if (strcmp(data, ccs_control_array[CCS_TOMOYO_ALT_EXEC].keyword) == 0) {
605     cp++;
606     if (*cp && !IsCorrectPath(cp, 1, -1, -1, __FUNCTION__)) cp = "";
607     profile->alt_exec = SaveName(cp);
608     return 0;
609     }
610     #endif
611     #endif
612 kumaneko 111 if (sscanf(cp + 1, "%u", &value) != 1) return -EINVAL;
613 kumaneko 461 #ifdef CONFIG_TOMOYO
614 kumaneko 111 if (strncmp(data, KEYWORD_MAC_FOR_CAPABILITY, KEYWORD_MAC_FOR_CAPABILITY_LEN) == 0) {
615     return SetCapabilityStatus(data + KEYWORD_MAC_FOR_CAPABILITY_LEN, value, i);
616     }
617 kumaneko 461 #endif
618 kumaneko 111 for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++) {
619     if (strcmp(data, ccs_control_array[i].keyword)) continue;
620     if (value > ccs_control_array[i].max_value) value = ccs_control_array[i].max_value;
621     profile->value[i] = value;
622     return 0;
623     }
624     return -EINVAL;
625     }
626    
627 kumaneko 418 static int ReadProfile(struct io_buffer *head)
628 kumaneko 111 {
629     if (!head->read_eof) {
630 kumaneko 921 if (!isRoot(head)) return -EPERM;
631 kumaneko 111 if (!head->read_var2) {
632     int step;
633     for (step = head->read_step; step < MAX_PROFILES * CCS_MAX_CONTROL_INDEX; step++) {
634     const int i = step / CCS_MAX_CONTROL_INDEX, j = step % CCS_MAX_CONTROL_INDEX;
635 kumaneko 214 const struct profile *profile = profile_ptr[i];
636 kumaneko 111 head->read_step = step;
637     if (!profile) continue;
638     switch (j) {
639 kumaneko 240 case -1: /* Dummy */
640 kumaneko 461 #ifndef CONFIG_SAKURA
641     case CCS_SAKURA_DENY_CONCEAL_MOUNT:
642     case CCS_SAKURA_RESTRICT_CHROOT:
643     case CCS_SAKURA_RESTRICT_MOUNT:
644     case CCS_SAKURA_RESTRICT_UNMOUNT:
645     case CCS_SAKURA_RESTRICT_PIVOT_ROOT:
646     case CCS_SAKURA_RESTRICT_AUTOBIND:
647     #endif
648 kumaneko 111 #ifndef CONFIG_TOMOYO
649 kumaneko 461 case CCS_TOMOYO_MAC_FOR_FILE:
650     case CCS_TOMOYO_MAC_FOR_ARGV0:
651 kumaneko 581 case CCS_TOMOYO_MAC_FOR_ENV:
652 kumaneko 461 case CCS_TOMOYO_MAC_FOR_NETWORK:
653     case CCS_TOMOYO_MAC_FOR_SIGNAL:
654 kumaneko 120 case CCS_TOMOYO_MAX_ACCEPT_ENTRY:
655 kumaneko 111 case CCS_TOMOYO_MAX_GRANT_LOG:
656     case CCS_TOMOYO_MAX_REJECT_LOG:
657     case CCS_TOMOYO_VERBOSE:
658     #endif
659 kumaneko 740 #ifndef ALT_EXEC
660 kumaneko 708 case CCS_TOMOYO_ALT_EXEC:
661     case CCS_SLEEP_PERIOD:
662 kumaneko 740 #endif
663 kumaneko 111 continue;
664     }
665     if (j == CCS_PROFILE_COMMENT) {
666     if (io_printf(head, "%u-%s=%s\n", i, ccs_control_array[CCS_PROFILE_COMMENT].keyword, profile->comment ? profile->comment->name : "")) break;
667 kumaneko 708 } else if (j == CCS_TOMOYO_ALT_EXEC) {
668     const struct path_info *alt_exec = profile->alt_exec;
669     if (io_printf(head, "%u-%s=%s\n", i, ccs_control_array[CCS_TOMOYO_ALT_EXEC].keyword, alt_exec ? alt_exec->name : "")) break;
670 kumaneko 111 } else {
671     if (io_printf(head, "%u-%s=%u\n", i, ccs_control_array[j].keyword, profile->value[j])) break;
672     }
673     }
674     if (step == MAX_PROFILES * CCS_MAX_CONTROL_INDEX) {
675 kumaneko 708 head->read_var2 = (void *) "";
676 kumaneko 111 head->read_step = 0;
677     }
678     }
679     if (head->read_var2) {
680 kumaneko 461 #ifdef CONFIG_TOMOYO
681     if (ReadCapabilityStatus(head) == 0)
682     #endif
683     head->read_eof = 1;
684 kumaneko 111 }
685     }
686     return 0;
687     }
688    
689     /************************* POLICY MANAGER HANDLER *************************/
690    
691 kumaneko 214 struct policy_manager_entry {
692 kumaneko 722 struct list1_head list;
693 kumaneko 111 const struct path_info *manager;
694 kumaneko 621 bool is_domain;
695     bool is_deleted;
696 kumaneko 214 };
697 kumaneko 111
698 kumaneko 722 static LIST1_HEAD(policy_manager_list);
699 kumaneko 111
700 kumaneko 621 static int AddManagerEntry(const char *manager, const bool is_delete)
701 kumaneko 111 {
702 kumaneko 214 struct policy_manager_entry *new_entry, *ptr;
703 kumaneko 652 static DEFINE_MUTEX(lock);
704 kumaneko 111 const struct path_info *saved_manager;
705     int error = -ENOMEM;
706 kumaneko 621 bool is_domain = 0;
707 kumaneko 111 if (IsDomainDef(manager)) {
708     if (!IsCorrectDomain(manager, __FUNCTION__)) return -EINVAL;
709     is_domain = 1;
710     } else {
711     if (!IsCorrectPath(manager, 1, -1, -1, __FUNCTION__)) return -EINVAL;
712     }
713     if ((saved_manager = SaveName(manager)) == NULL) return -ENOMEM;
714 kumaneko 652 mutex_lock(&lock);
715 kumaneko 722 list1_for_each_entry(ptr, &policy_manager_list, list) {
716 kumaneko 111 if (ptr->manager == saved_manager) {
717     ptr->is_deleted = is_delete;
718     error = 0;
719     goto out;
720     }
721     }
722     if (is_delete) {
723     error = -ENOENT;
724     goto out;
725     }
726 kumaneko 214 if ((new_entry = alloc_element(sizeof(*new_entry))) == NULL) goto out;
727 kumaneko 111 new_entry->manager = saved_manager;
728     new_entry->is_domain = is_domain;
729 kumaneko 722 list1_add_tail_mb(&new_entry->list, &policy_manager_list);
730 kumaneko 111 error = 0;
731     out:
732 kumaneko 652 mutex_unlock(&lock);
733 kumaneko 111 if (!error) UpdateCounter(CCS_UPDATES_COUNTER_MANAGER);
734     return error;
735     }
736    
737 kumaneko 214 static int AddManagerPolicy(struct io_buffer *head)
738 kumaneko 111 {
739     const char *data = head->write_buf;
740 kumaneko 621 bool is_delete = 0;
741 kumaneko 921 if (!isRoot(head)) return -EPERM;
742 kumaneko 111 if (strncmp(data, KEYWORD_DELETE, KEYWORD_DELETE_LEN) == 0) {
743     data += KEYWORD_DELETE_LEN;
744     is_delete = 1;
745     }
746     return AddManagerEntry(data, is_delete);
747     }
748    
749 kumaneko 214 static int ReadManagerPolicy(struct io_buffer *head)
750 kumaneko 111 {
751 kumaneko 722 struct list1_head *pos;
752 kumaneko 708 if (head->read_eof) return 0;
753 kumaneko 921 if (!isRoot(head)) return -EPERM;
754 kumaneko 722 list1_for_each_cookie(pos, head->read_var2, &policy_manager_list) {
755 kumaneko 708 struct policy_manager_entry *ptr;
756 kumaneko 722 ptr = list1_entry(pos, struct policy_manager_entry, list);
757 kumaneko 708 if (ptr->is_deleted) continue;
758     if (io_printf(head, "%s\n", ptr->manager->name)) return 0;
759 kumaneko 111 }
760 kumaneko 708 head->read_eof = 1;
761 kumaneko 111 return 0;
762     }
763    
764     /* Check whether the current process is a policy manager. */
765     static int IsPolicyManager(void)
766     {
767 kumaneko 214 struct policy_manager_entry *ptr;
768 kumaneko 111 const char *exe;
769     const struct path_info *domainname = current->domain_info->domainname;
770 kumaneko 708 bool found = 0;
771 kumaneko 111 if (!sbin_init_started) return 1;
772 kumaneko 722 list1_for_each_entry(ptr, &policy_manager_list, list) {
773 kumaneko 111 if (!ptr->is_deleted && ptr->is_domain && !pathcmp(domainname, ptr->manager)) return 1;
774     }
775     if ((exe = GetEXE()) == NULL) return 0;
776 kumaneko 722 list1_for_each_entry(ptr, &policy_manager_list, list) {
777 kumaneko 708 if (!ptr->is_deleted && !ptr->is_domain && !strcmp(exe, ptr->manager->name)) {
778     found = 1;
779     break;
780     }
781 kumaneko 111 }
782 kumaneko 708 if (!found) { /* Reduce error messages. */
783 kumaneko 111 static pid_t last_pid = 0;
784     const pid_t pid = current->pid;
785     if (last_pid != pid) {
786 kumaneko 248 printk("%s ( %s ) is not permitted to update policies.\n", domainname->name, exe);
787 kumaneko 111 last_pid = pid;
788     }
789     }
790     ccs_free(exe);
791 kumaneko 708 return found;
792 kumaneko 111 }
793    
794     #ifdef CONFIG_TOMOYO
795    
796     /************************* DOMAIN POLICY HANDLER *************************/
797    
798 kumaneko 581 static char *FindConditionPart(char *data)
799     {
800     char *cp = strstr(data, " if "), *cp2;
801     if (cp) {
802     while ((cp2 = strstr(cp + 3, " if ")) != NULL) cp = cp2;
803     *cp++ = '\0';
804 kumaneko 994 } else if ((cp = strstr(data, " ; set ")) != NULL) {
805     *cp++ = '\0';
806 kumaneko 581 }
807     return cp;
808     }
809    
810 kumaneko 214 static int AddDomainPolicy(struct io_buffer *head)
811 kumaneko 111 {
812     char *data = head->write_buf;
813     struct domain_info *domain = head->write_var1;
814 kumaneko 621 bool is_delete = 0, is_select = 0, is_undelete = 0;
815 kumaneko 111 unsigned int profile;
816 kumaneko 581 const struct condition_list *cond = NULL;
817 kumaneko 906 char *cp;
818 kumaneko 921 if (!isRoot(head)) return -EPERM;
819 kumaneko 111 if (strncmp(data, KEYWORD_DELETE, KEYWORD_DELETE_LEN) == 0) {
820     data += KEYWORD_DELETE_LEN;
821     is_delete = 1;
822     } else if (strncmp(data, KEYWORD_SELECT, KEYWORD_SELECT_LEN) == 0) {
823     data += KEYWORD_SELECT_LEN;
824     is_select = 1;
825     } else if (strncmp(data, KEYWORD_UNDELETE, KEYWORD_UNDELETE_LEN) == 0) {
826     data += KEYWORD_UNDELETE_LEN;
827     is_undelete = 1;
828     }
829     if (IsDomainDef(data)) {
830     if (is_delete) {
831     DeleteDomain(data);
832     domain = NULL;
833     } else if (is_select) {
834     domain = FindDomain(data);
835     } else if (is_undelete) {
836     domain = UndeleteDomain(data);
837     } else {
838     domain = FindOrAssignNewDomain(data, 0);
839     }
840     head->write_var1 = domain;
841 kumaneko 906 UpdateCounter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);
842 kumaneko 111 return 0;
843     }
844     if (!domain) return -EINVAL;
845 kumaneko 581
846 kumaneko 111 if (sscanf(data, KEYWORD_USE_PROFILE "%u", &profile) == 1 && profile < MAX_PROFILES) {
847     if (profile_ptr[profile] || !sbin_init_started) domain->profile = (u8) profile;
848 kumaneko 581 return 0;
849     }
850     cp = FindConditionPart(data);
851     if (cp && (cond = FindOrAssignNewCondition(cp)) == NULL) return -EINVAL;
852     if (strncmp(data, KEYWORD_ALLOW_CAPABILITY, KEYWORD_ALLOW_CAPABILITY_LEN) == 0) {
853     return AddCapabilityPolicy(data + KEYWORD_ALLOW_CAPABILITY_LEN, domain, cond, is_delete);
854 kumaneko 111 } else if (strncmp(data, KEYWORD_ALLOW_NETWORK, KEYWORD_ALLOW_NETWORK_LEN) == 0) {
855 kumaneko 581 return AddNetworkPolicy(data + KEYWORD_ALLOW_NETWORK_LEN, domain, cond, is_delete);
856 kumaneko 111 } else if (strncmp(data, KEYWORD_ALLOW_SIGNAL, KEYWORD_ALLOW_SIGNAL_LEN) == 0) {
857 kumaneko 581 return AddSignalPolicy(data + KEYWORD_ALLOW_SIGNAL_LEN, domain, cond, is_delete);
858 kumaneko 111 } else if (strncmp(data, KEYWORD_ALLOW_ARGV0, KEYWORD_ALLOW_ARGV0_LEN) == 0) {
859 kumaneko 581 return AddArgv0Policy(data + KEYWORD_ALLOW_ARGV0_LEN, domain, cond, is_delete);
860     } else if (strncmp(data, KEYWORD_ALLOW_ENV, KEYWORD_ALLOW_ENV_LEN) == 0) {
861     return AddEnvPolicy(data + KEYWORD_ALLOW_ENV_LEN, domain, cond, is_delete);
862 kumaneko 111 } else {
863 kumaneko 581 return AddFilePolicy(data, domain, cond, is_delete);
864 kumaneko 111 }
865     return -EINVAL;
866     }
867    
868 kumaneko 860 static bool print_single_path_acl(struct io_buffer *head, struct single_path_acl_record *ptr, const struct condition_list *cond)
869 kumaneko 856 {
870     int pos;
871     u8 bit;
872     const bool b = ptr->u_is_group;
873     const u16 perm = ptr->perm;
874     for (bit = head->read_bit; bit < MAX_SINGLE_PATH_OPERATION; bit++) {
875     const char *msg;
876     if (!(perm & (1 << bit))) continue;
877     /* Print "read/write" instead of "read" and "write". */
878     if ((bit == TYPE_READ_ACL || bit == TYPE_WRITE_ACL) && (perm & (1 << TYPE_READ_WRITE_ACL))) continue;
879     msg = sp_operation2keyword(bit);
880     pos = head->read_avail;
881     if (b && io_printf(head, "allow_%s @%s ", msg, ptr->u.group->group_name->name)) goto out;
882     if (!b && io_printf(head, "allow_%s %s ", msg, ptr->u.filename->name)) goto out;
883     if (DumpCondition(head, cond)) goto out;
884     }
885     head->read_bit = 0;
886     return 1;
887     out:
888     head->read_bit = bit;
889     head->read_avail = pos;
890     return 0;
891     }
892    
893 kumaneko 860 static bool print_double_path_acl(struct io_buffer *head, struct double_path_acl_record *ptr, const struct condition_list *cond)
894 kumaneko 856 {
895     int pos;
896     const bool b0 = ptr->u1_is_group, b1 = ptr->u2_is_group;
897     const u8 perm = ptr->perm;
898     u8 bit;
899     for (bit = head->read_bit; bit < MAX_DOUBLE_PATH_OPERATION; bit++) {
900     const char *msg;
901     if (!(perm & (1 << bit))) continue;
902     msg = dp_operation2keyword(bit);
903     pos = head->read_avail;
904     if (io_printf(head, "allow_%s ", msg)) goto out;
905 kumaneko 931 if (b0 && io_printf(head, "@%s ", ptr->u1.group1->group_name->name)) goto out;
906     if (!b0 && io_printf(head, "%s ", ptr->u1.filename1->name)) goto out;
907 kumaneko 856 if (b1 && io_printf(head, "@%s", ptr->u2.group2->group_name->name)) goto out;
908     if (!b1 && io_printf(head, "%s", ptr->u2.filename2->name)) goto out;
909     if (DumpCondition(head, cond)) goto out;
910     }
911     head->read_bit = 0;
912     return 1;
913     out:
914     head->read_bit = bit;
915     head->read_avail = pos;
916     return 0;
917     }
918    
919     static bool print_argv0_acl(struct io_buffer *head, struct argv0_acl_record *ptr, const struct condition_list *cond)
920     {
921     int pos = head->read_avail;
922     if (io_printf(head, KEYWORD_ALLOW_ARGV0 "%s %s",
923     ptr->filename->name, ptr->argv0->name)) goto out;
924     if (DumpCondition(head, cond)) goto out;
925     return 1;
926     out:
927     head->read_avail = pos;
928     return 0;
929     }
930    
931     static bool print_env_acl(struct io_buffer *head, struct env_acl_record *ptr, const struct condition_list *cond)
932     {
933     int pos = head->read_avail;
934     if (io_printf(head, KEYWORD_ALLOW_ENV "%s", ptr->env->name)) goto out;
935     if (DumpCondition(head, cond)) goto out;
936     return 1;
937     out:
938     head->read_avail = pos;
939     return 0;
940     }
941    
942     static bool print_capability_acl(struct io_buffer *head, struct capability_acl_record *ptr, const struct condition_list *cond)
943     {
944 kumaneko 860 int pos = head->read_avail;
945     if (io_printf(head, KEYWORD_ALLOW_CAPABILITY "%s", cap_operation2keyword(ptr->operation))) goto out;
946     if (DumpCondition(head, cond)) goto out;
947 kumaneko 856 return 1;
948     out:
949     head->read_avail = pos;
950     return 0;
951     }
952    
953     static bool print_network_acl(struct io_buffer *head, struct ip_network_acl_record *ptr, const struct condition_list *cond)
954     {
955     int pos = head->read_avail;
956     if (io_printf(head, KEYWORD_ALLOW_NETWORK "%s ", net_operation2keyword(ptr->operation_type))) goto out;
957     switch (ptr->record_type) {
958     case IP_RECORD_TYPE_ADDRESS_GROUP:
959     if (io_printf(head, "@%s", ptr->u.group->group_name->name)) goto out;
960     break;
961     case IP_RECORD_TYPE_IPv4:
962     {
963     const u32 min_address = ptr->u.ipv4.min, max_address = ptr->u.ipv4.max;
964     if (io_printf(head, "%u.%u.%u.%u", HIPQUAD(min_address))) goto out;
965     if (min_address != max_address && io_printf(head, "-%u.%u.%u.%u", HIPQUAD(max_address))) goto out;
966     }
967     break;
968     case IP_RECORD_TYPE_IPv6:
969     {
970     char buf[64];
971     const struct in6_addr *min_address = ptr->u.ipv6.min, *max_address = ptr->u.ipv6.max;
972     print_ipv6(buf, sizeof(buf), min_address);
973     if (io_printf(head, "%s", buf)) goto out;
974     if (min_address != max_address) {
975     print_ipv6(buf, sizeof(buf), max_address);
976     if (io_printf(head, "-%s", buf)) goto out;
977     }
978     }
979     break;
980     }
981     {
982     const u16 min_port = ptr->min_port, max_port = ptr->max_port;
983     if (io_printf(head, " %u", min_port)) goto out;
984     if (min_port != max_port && io_printf(head, "-%u", max_port)) goto out;
985     }
986     if (DumpCondition(head, cond)) goto out;
987     return 1;
988     out:
989     head->read_avail = pos;
990     return 0;
991     }
992    
993     static bool print_signal_acl(struct io_buffer *head, struct signal_acl_record *ptr, const struct condition_list *cond)
994     {
995     int pos = head->read_avail;
996     if (io_printf(head, KEYWORD_ALLOW_SIGNAL "%u %s", ptr->sig, ptr->domainname->name)) goto out;
997     if (DumpCondition(head, cond)) goto out;
998     return 1;
999     out:
1000     head->read_avail = pos;
1001     return 0;
1002     }
1003    
1004 kumaneko 214 static int ReadDomainPolicy(struct io_buffer *head)
1005 kumaneko 111 {
1006 kumaneko 722 struct list1_head *dpos;
1007     struct list1_head *apos;
1008 kumaneko 708 if (head->read_eof) return 0;
1009     if (head->read_step == 0) {
1010 kumaneko 921 if (!isRoot(head)) return -EPERM;
1011 kumaneko 708 head->read_step = 1;
1012     }
1013 kumaneko 722 list1_for_each_cookie(dpos, head->read_var1, &domain_list) {
1014 kumaneko 708 struct domain_info *domain;
1015 kumaneko 722 domain = list1_entry(dpos, struct domain_info, list);
1016 kumaneko 708 if (head->read_step != 1) goto acl_loop;
1017     if (domain->is_deleted) continue;
1018     if (io_printf(head, "%s\n" KEYWORD_USE_PROFILE "%u\n%s\n", domain->domainname->name, domain->profile, domain->quota_warned ? "quota_exceeded\n" : "")) return 0;
1019     head->read_step = 2;
1020     acl_loop: ;
1021     if (head->read_step == 3) goto tail_mark;
1022 kumaneko 722 list1_for_each_cookie(apos, head->read_var2, &domain->acl_info_list) {
1023 kumaneko 111 struct acl_info *ptr;
1024 kumaneko 708 u8 acl_type;
1025 kumaneko 912 const struct condition_list *cond;
1026 kumaneko 722 ptr = list1_entry(apos, struct acl_info, list);
1027 kumaneko 912 cond = GetConditionPart(ptr);
1028     acl_type = ptr->type & ~ACL_WITH_CONDITION;
1029 kumaneko 906 if (acl_type & ACL_DELETED) {
1030     /* Deleted entry. */
1031     } else if (acl_type == TYPE_SINGLE_PATH_ACL) {
1032 kumaneko 912 if (!print_single_path_acl(head, container_of(ptr, struct single_path_acl_record, head), cond)) return 0;
1033 kumaneko 849 } else if (acl_type == TYPE_DOUBLE_PATH_ACL) {
1034 kumaneko 912 if (!print_double_path_acl(head, container_of(ptr, struct double_path_acl_record, head), cond)) return 0;
1035 kumaneko 708 } else if (acl_type == TYPE_ARGV0_ACL) {
1036 kumaneko 912 if (!print_argv0_acl(head, container_of(ptr, struct argv0_acl_record, head), cond)) return 0;
1037 kumaneko 708 } else if (acl_type == TYPE_ENV_ACL) {
1038 kumaneko 912 if (!print_env_acl(head, container_of(ptr, struct env_acl_record, head), cond)) return 0;
1039 kumaneko 708 } else if (acl_type == TYPE_CAPABILITY_ACL) {
1040 kumaneko 912 if (!print_capability_acl(head, container_of(ptr, struct capability_acl_record, head), cond)) return 0;
1041 kumaneko 708 } else if (acl_type == TYPE_IP_NETWORK_ACL) {
1042 kumaneko 912 if (!print_network_acl(head, container_of(ptr, struct ip_network_acl_record, head), cond)) return 0;
1043 kumaneko 708 } else if (acl_type == TYPE_SIGNAL_ACL) {
1044 kumaneko 912 if (!print_signal_acl(head, container_of(ptr, struct signal_acl_record, head), cond)) return 0;
1045 kumaneko 708 } else {
1046 kumaneko 849 BUG();
1047 kumaneko 111 }
1048     }
1049 kumaneko 708 head->read_step = 3;
1050     tail_mark: ;
1051     if (io_printf(head, "\n")) return 0;
1052     head->read_step = 1;
1053 kumaneko 111 }
1054 kumaneko 708 head->read_eof = 1;
1055 kumaneko 111 return 0;
1056     }
1057    
1058 kumaneko 461 #endif
1059    
1060     static int UpdateDomainProfile(struct io_buffer *head)
1061     {
1062     char *data = head->write_buf;
1063     char *cp = strchr(data, ' ');
1064     struct domain_info *domain;
1065     unsigned int profile;
1066 kumaneko 921 if (!isRoot(head)) return -EPERM;
1067 kumaneko 461 if (!cp) return -EINVAL;
1068     *cp = '\0';
1069     domain = FindDomain(cp + 1);
1070     profile = simple_strtoul(data, NULL, 10);
1071     if (domain && profile < MAX_PROFILES && (profile_ptr[profile] || !sbin_init_started)) domain->profile = (u8) profile;
1072     UpdateCounter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);
1073     return 0;
1074     }
1075    
1076 kumaneko 214 static int ReadDomainProfile(struct io_buffer *head)
1077 kumaneko 111 {
1078 kumaneko 722 struct list1_head *pos;
1079 kumaneko 708 if (head->read_eof) return 0;
1080 kumaneko 921 if (!isRoot(head)) return -EPERM;
1081 kumaneko 722 list1_for_each_cookie(pos, head->read_var1, &domain_list) {
1082 kumaneko 111 struct domain_info *domain;
1083 kumaneko 722 domain = list1_entry(pos, struct domain_info, list);
1084 kumaneko 708 if (domain->is_deleted) continue;
1085     if (io_printf(head, "%u %s\n", domain->profile, domain->domainname->name)) return 0;
1086 kumaneko 111 }
1087 kumaneko 708 head->read_eof = 1;
1088 kumaneko 111 return 0;
1089     }
1090    
1091 kumaneko 214 static int WritePID(struct io_buffer *head)
1092 kumaneko 111 {
1093     head->read_step = (int) simple_strtoul(head->write_buf, NULL, 10);
1094     head->read_eof = 0;
1095     return 0;
1096     }
1097    
1098 kumaneko 214 static int ReadPID(struct io_buffer *head)
1099 kumaneko 111 {
1100     if (head->read_avail == 0 && !head->read_eof) {
1101     const int pid = head->read_step;
1102     struct task_struct *p;
1103     struct domain_info *domain = NULL;
1104     /***** CRITICAL SECTION START *****/
1105     read_lock(&tasklist_lock);
1106     p = find_task_by_pid(pid);
1107     if (p) domain = p->domain_info;
1108     read_unlock(&tasklist_lock);
1109     /***** CRITICAL SECTION END *****/
1110     if (domain) io_printf(head, "%d %u %s", pid, domain->profile, domain->domainname->name);
1111     head->read_eof = 1;
1112     }
1113     return 0;
1114     }
1115    
1116     /************************* EXCEPTION POLICY HANDLER *************************/
1117    
1118     #ifdef CONFIG_TOMOYO
1119    
1120 kumaneko 214 static int AddExceptionPolicy(struct io_buffer *head)
1121 kumaneko 111 {
1122     char *data = head->write_buf;
1123 kumaneko 621 bool is_delete = 0;
1124 kumaneko 921 if (!isRoot(head)) return -EPERM;
1125 kumaneko 111 UpdateCounter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
1126     if (strncmp(data, KEYWORD_DELETE, KEYWORD_DELETE_LEN) == 0) {
1127     data += KEYWORD_DELETE_LEN;
1128     is_delete = 1;
1129     }
1130     if (strncmp(data, KEYWORD_KEEP_DOMAIN, KEYWORD_KEEP_DOMAIN_LEN) == 0) {
1131     return AddDomainKeeperPolicy(data + KEYWORD_KEEP_DOMAIN_LEN, 0, is_delete);
1132     } else if (strncmp(data, KEYWORD_NO_KEEP_DOMAIN, KEYWORD_NO_KEEP_DOMAIN_LEN) == 0) {
1133     return AddDomainKeeperPolicy(data + KEYWORD_NO_KEEP_DOMAIN_LEN, 1, is_delete);
1134     } else if (strncmp(data, KEYWORD_INITIALIZE_DOMAIN, KEYWORD_INITIALIZE_DOMAIN_LEN) == 0) {
1135 kumaneko 366 return AddDomainInitializerPolicy(data + KEYWORD_INITIALIZE_DOMAIN_LEN, 0, is_delete);
1136 kumaneko 111 } else if (strncmp(data, KEYWORD_NO_INITIALIZE_DOMAIN, KEYWORD_NO_INITIALIZE_DOMAIN_LEN) == 0) {
1137 kumaneko 366 return AddDomainInitializerPolicy(data + KEYWORD_NO_INITIALIZE_DOMAIN_LEN, 1, is_delete);
1138 kumaneko 111 } else if (strncmp(data, KEYWORD_ALIAS, KEYWORD_ALIAS_LEN) == 0) {
1139     return AddAliasPolicy(data + KEYWORD_ALIAS_LEN, is_delete);
1140     } else if (strncmp(data, KEYWORD_AGGREGATOR, KEYWORD_AGGREGATOR_LEN) == 0) {
1141     return AddAggregatorPolicy(data + KEYWORD_AGGREGATOR_LEN, is_delete);
1142     } else if (strncmp(data, KEYWORD_ALLOW_READ, KEYWORD_ALLOW_READ_LEN) == 0) {
1143     return AddGloballyReadablePolicy(data + KEYWORD_ALLOW_READ_LEN, is_delete);
1144 kumaneko 581 } else if (strncmp(data, KEYWORD_ALLOW_ENV, KEYWORD_ALLOW_ENV_LEN) == 0) {
1145     return AddGloballyUsableEnvPolicy(data + KEYWORD_ALLOW_ENV_LEN, is_delete);
1146 kumaneko 111 } else if (strncmp(data, KEYWORD_FILE_PATTERN, KEYWORD_FILE_PATTERN_LEN) == 0) {
1147 kumaneko 851 return AddFilePatternPolicy(data + KEYWORD_FILE_PATTERN_LEN, is_delete);
1148 kumaneko 111 } else if (strncmp(data, KEYWORD_PATH_GROUP, KEYWORD_PATH_GROUP_LEN) == 0) {
1149 kumaneko 708 return AddPathGroupPolicy(data + KEYWORD_PATH_GROUP_LEN, is_delete);
1150 kumaneko 111 } else if (strncmp(data, KEYWORD_DENY_REWRITE, KEYWORD_DENY_REWRITE_LEN) == 0) {
1151     return AddNoRewritePolicy(data + KEYWORD_DENY_REWRITE_LEN, is_delete);
1152     } else if (strncmp(data, KEYWORD_ADDRESS_GROUP, KEYWORD_ADDRESS_GROUP_LEN) == 0) {
1153     return AddAddressGroupPolicy(data + KEYWORD_ADDRESS_GROUP_LEN, is_delete);
1154     }
1155     return -EINVAL;
1156     }
1157    
1158 kumaneko 214 static int ReadExceptionPolicy(struct io_buffer *head)
1159 kumaneko 111 {
1160     if (!head->read_eof) {
1161     switch (head->read_step) {
1162     case 0:
1163 kumaneko 921 if (!isRoot(head)) return -EPERM;
1164 kumaneko 111 head->read_var2 = NULL; head->read_step = 1;
1165     case 1:
1166     if (ReadDomainKeeperPolicy(head)) break;
1167     head->read_var2 = NULL; head->read_step = 2;
1168     case 2:
1169     if (ReadGloballyReadablePolicy(head)) break;
1170     head->read_var2 = NULL; head->read_step = 3;
1171     case 3:
1172 kumaneko 581 if (ReadGloballyUsableEnvPolicy(head)) break;
1173 kumaneko 111 head->read_var2 = NULL; head->read_step = 4;
1174     case 4:
1175 kumaneko 581 if (ReadDomainInitializerPolicy(head)) break;
1176 kumaneko 111 head->read_var2 = NULL; head->read_step = 5;
1177     case 5:
1178 kumaneko 581 if (ReadAliasPolicy(head)) break;
1179 kumaneko 111 head->read_var2 = NULL; head->read_step = 6;
1180     case 6:
1181 kumaneko 581 if (ReadAggregatorPolicy(head)) break;
1182 kumaneko 111 head->read_var2 = NULL; head->read_step = 7;
1183     case 7:
1184 kumaneko 851 if (ReadFilePatternPolicy(head)) break;
1185 kumaneko 111 head->read_var2 = NULL; head->read_step = 8;
1186     case 8:
1187 kumaneko 581 if (ReadNoRewritePolicy(head)) break;
1188     head->read_var2 = NULL; head->read_step = 9;
1189     case 9:
1190 kumaneko 708 if (ReadPathGroupPolicy(head)) break;
1191 kumaneko 581 head->read_var1 = head->read_var2 = NULL; head->read_step = 10;
1192     case 10:
1193 kumaneko 111 if (ReadAddressGroupPolicy(head)) break;
1194     head->read_eof = 1;
1195     break;
1196     default:
1197     return -EINVAL;
1198     }
1199     }
1200     return 0;
1201     }
1202    
1203     #endif
1204    
1205     /************************* SYSTEM POLICY HANDLER *************************/
1206    
1207     #ifdef CONFIG_SAKURA
1208    
1209 kumaneko 214 static int AddSystemPolicy(struct io_buffer *head)
1210 kumaneko 111 {
1211     char *data = head->write_buf;
1212 kumaneko 621 bool is_delete = 0;
1213 kumaneko 921 if (!isRoot(head)) return -EPERM;
1214 kumaneko 111 UpdateCounter(CCS_UPDATES_COUNTER_SYSTEM_POLICY);
1215     if (strncmp(data, KEYWORD_DELETE, KEYWORD_DELETE_LEN) == 0) {
1216     data += KEYWORD_DELETE_LEN;
1217     is_delete = 1;
1218     }
1219     if (strncmp(data, KEYWORD_ALLOW_MOUNT, KEYWORD_ALLOW_MOUNT_LEN) == 0)
1220     return AddMountPolicy(data + KEYWORD_ALLOW_MOUNT_LEN, is_delete);
1221     if (strncmp(data, KEYWORD_DENY_UNMOUNT, KEYWORD_DENY_UNMOUNT_LEN) == 0)
1222     return AddNoUmountPolicy(data + KEYWORD_DENY_UNMOUNT_LEN, is_delete);
1223     if (strncmp(data, KEYWORD_ALLOW_CHROOT, KEYWORD_ALLOW_CHROOT_LEN) == 0)
1224     return AddChrootPolicy(data + KEYWORD_ALLOW_CHROOT_LEN, is_delete);
1225 kumaneko 141 if (strncmp(data, KEYWORD_ALLOW_PIVOT_ROOT, KEYWORD_ALLOW_PIVOT_ROOT_LEN) == 0)
1226     return AddPivotRootPolicy(data + KEYWORD_ALLOW_PIVOT_ROOT_LEN, is_delete);
1227 kumaneko 111 if (strncmp(data, KEYWORD_DENY_AUTOBIND, KEYWORD_DENY_AUTOBIND_LEN) == 0)
1228     return AddReservedPortPolicy(data + KEYWORD_DENY_AUTOBIND_LEN, is_delete);
1229     return -EINVAL;
1230     }
1231    
1232 kumaneko 214 static int ReadSystemPolicy(struct io_buffer *head)
1233 kumaneko 111 {
1234     if (!head->read_eof) {
1235     switch (head->read_step) {
1236     case 0:
1237 kumaneko 921 if (!isRoot(head)) return -EPERM;
1238 kumaneko 111 head->read_var2 = NULL; head->read_step = 1;
1239     case 1:
1240     if (ReadMountPolicy(head)) break;
1241     head->read_var2 = NULL; head->read_step = 2;
1242     case 2:
1243     if (ReadNoUmountPolicy(head)) break;
1244     head->read_var2 = NULL; head->read_step = 3;
1245     case 3:
1246     if (ReadChrootPolicy(head)) break;
1247     head->read_var2 = NULL; head->read_step = 4;
1248     case 4:
1249 kumaneko 141 if (ReadPivotRootPolicy(head)) break;
1250     head->read_var2 = NULL; head->read_step = 5;
1251     case 5:
1252 kumaneko 111 if (ReadReservedPortPolicy(head)) break;
1253     head->read_eof = 1;
1254     break;
1255     default:
1256     return -EINVAL;
1257     }
1258     }
1259     return 0;
1260     }
1261    
1262     #endif
1263    
1264     /************************* POLICY LOADER *************************/
1265    
1266 kumaneko 325 static int profile_loaded = 0;
1267    
1268 kumaneko 111 static const char *ccs_loader = NULL;
1269    
1270     static int __init CCS_loader_Setup(char *str)
1271     {
1272     ccs_loader = str;
1273     return 0;
1274     }
1275    
1276     __setup("CCS_loader=", CCS_loader_Setup);
1277    
1278     void CCS_LoadPolicy(const char *filename)
1279     {
1280     if (sbin_init_started) return;
1281     /*
1282     * Check filename is /sbin/init or /sbin/ccs-start .
1283     * /sbin/ccs-start is a dummy filename in case where /sbin/init can't be passed.
1284     * You can create /sbin/ccs-start by "ln -s /bin/true /sbin/ccs-start", for
1285     * only the pathname is needed to activate Mandatory Access Control.
1286     */
1287     if (strcmp(filename, "/sbin/init") != 0 && strcmp(filename, "/sbin/ccs-start") != 0) return;
1288     /*
1289     * Don't activate MAC if the path given by 'CCS_loader=' option doesn't exist.
1290     * If initrd.img includes /sbin/init but real-root-dev has not mounted on / yet,
1291     * activating MAC will block the system since policies are not loaded yet.
1292     * So let do_execve() call this function everytime.
1293     */
1294     {
1295     struct nameidata nd;
1296 kumaneko 325 if (!ccs_loader) ccs_loader = "/sbin/ccs-init";
1297 kumaneko 111 if (path_lookup(ccs_loader, lookup_flags, &nd)) {
1298     printk("Not activating Mandatory Access Control now since %s doesn't exist.\n", ccs_loader);
1299     return;
1300     }
1301 kumaneko 992 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
1302 kumaneko 990 path_put(&nd.path);
1303     #else
1304 kumaneko 111 path_release(&nd);
1305 kumaneko 990 #endif
1306 kumaneko 111 }
1307 kumaneko 325 if (!profile_loaded) {
1308     char *argv[2], *envp[3];
1309     printk("Calling %s to load policy. Please wait.\n", ccs_loader);
1310     argv[0] = (char *) ccs_loader;
1311     argv[1] = NULL;
1312     envp[0] = "HOME=/";
1313     envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
1314     envp[2] = NULL;
1315     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1316     call_usermodehelper(argv[0], argv, envp, 1);
1317     #else
1318     call_usermodehelper(argv[0], argv, envp);
1319     #endif
1320     while (!profile_loaded) {
1321     set_current_state(TASK_INTERRUPTIBLE);
1322     schedule_timeout(HZ / 10);
1323     }
1324     }
1325 kumaneko 473 #ifdef CONFIG_SAKURA
1326 kumaneko 990 printk("SAKURA: 1.6.0-pre 2008/02/16\n");
1327 kumaneko 473 #endif
1328     #ifdef CONFIG_TOMOYO
1329 kumaneko 1005 printk("TOMOYO: 1.6.0-pre 2008/02/25\n");
1330 kumaneko 473 #endif
1331 kumaneko 111 printk("Mandatory Access Control activated.\n");
1332     sbin_init_started = 1;
1333     ccs_log_level = KERN_WARNING;
1334     { /* Check all profiles currently assigned to domains are defined. */
1335     struct domain_info *domain;
1336 kumaneko 722 list1_for_each_entry(domain, &domain_list, list) {
1337 kumaneko 111 const u8 profile = domain->profile;
1338 kumaneko 708 if (!profile_ptr[profile]) panic("Profile %u (used by '%s') not defined.\n", profile, domain->domainname->name);
1339 kumaneko 111 }
1340     }
1341     }
1342    
1343    
1344     /************************* MAC Decision Delayer *************************/
1345    
1346     static DECLARE_WAIT_QUEUE_HEAD(query_wait);
1347    
1348     static spinlock_t query_lock = SPIN_LOCK_UNLOCKED;
1349    
1350 kumaneko 214 struct query_entry {
1351 kumaneko 111 struct list_head list;
1352     char *query;
1353     int query_len;
1354     unsigned int serial;
1355     int timer;
1356     int answer;
1357 kumaneko 214 };
1358 kumaneko 111
1359     static LIST_HEAD(query_list);
1360     static atomic_t queryd_watcher = ATOMIC_INIT(0);
1361    
1362     int CheckSupervisor(const char *fmt, ...)
1363     {
1364     va_list args;
1365     int error = -EPERM;
1366     int pos, len;
1367     static unsigned int serial = 0;
1368 kumaneko 214 struct query_entry *query_entry;
1369 kumaneko 708 if (!CheckCCSFlags(CCS_ALLOW_ENFORCE_GRACE) || !atomic_read(&queryd_watcher)) {
1370 kumaneko 742 #ifdef ALT_EXEC
1371 kumaneko 708 if ((current->tomoyo_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR) == 0) {
1372     int i;
1373     for (i = 0; i < CheckCCSFlags(CCS_SLEEP_PERIOD); i++) {
1374     set_current_state(TASK_INTERRUPTIBLE);
1375     schedule_timeout(HZ / 10);
1376     }
1377     }
1378     #endif
1379     return -EPERM;
1380     }
1381 kumaneko 111 va_start(args, fmt);
1382     len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;
1383     va_end(args);
1384 kumaneko 214 if ((query_entry = ccs_alloc(sizeof(*query_entry))) == NULL ||
1385 kumaneko 111 (query_entry->query = ccs_alloc(len)) == NULL) goto out;
1386     INIT_LIST_HEAD(&query_entry->list);
1387     /***** CRITICAL SECTION START *****/
1388     spin_lock(&query_lock);
1389     query_entry->serial = serial++;
1390     spin_unlock(&query_lock);
1391     /***** CRITICAL SECTION END *****/
1392     pos = snprintf(query_entry->query, len - 1, "Q%u\n", query_entry->serial);
1393     va_start(args, fmt);
1394     vsnprintf(query_entry->query + pos, len - 1 - pos, fmt, args);
1395     query_entry->query_len = strlen(query_entry->query) + 1;
1396     va_end(args);
1397     /***** CRITICAL SECTION START *****/
1398     spin_lock(&query_lock);
1399     list_add_tail(&query_entry->list, &query_list);
1400     spin_unlock(&query_lock);
1401     /***** CRITICAL SECTION END *****/
1402     UpdateCounter(CCS_UPDATES_COUNTER_QUERY);
1403     /* Give 10 seconds for supervisor's opinion. */
1404     for (query_entry->timer = 0; atomic_read(&queryd_watcher) && CheckCCSFlags(CCS_ALLOW_ENFORCE_GRACE) && query_entry->timer < 100; query_entry->timer++) {
1405     wake_up(&query_wait);
1406     set_current_state(TASK_INTERRUPTIBLE);
1407     schedule_timeout(HZ / 10);
1408     if (query_entry->answer) break;
1409     }
1410     UpdateCounter(CCS_UPDATES_COUNTER_QUERY);
1411     /***** CRITICAL SECTION START *****/
1412     spin_lock(&query_lock);
1413     list_del(&query_entry->list);
1414     spin_unlock(&query_lock);
1415     /***** CRITICAL SECTION END *****/
1416     switch (query_entry->answer) {
1417     case 1:
1418     /* Granted by administrator. */
1419     error = 0;
1420     break;
1421     case 0:
1422     /* Timed out. */
1423     break;
1424     default:
1425     /* Rejected by administrator. */
1426     break;
1427     }
1428     out: ;
1429     if (query_entry) ccs_free(query_entry->query);
1430     ccs_free(query_entry);
1431     return error;
1432     }
1433    
1434     static int PollQuery(struct file *file, poll_table *wait)
1435     {
1436     int found;
1437     /***** CRITICAL SECTION START *****/
1438     spin_lock(&query_lock);
1439     found = !list_empty(&query_list);
1440     spin_unlock(&query_lock);
1441     /***** CRITICAL SECTION END *****/
1442     if (found) return POLLIN | POLLRDNORM;
1443     poll_wait(file, &query_wait, wait);
1444     /***** CRITICAL SECTION START *****/
1445     spin_lock(&query_lock);
1446     found = !list_empty(&query_list);
1447     spin_unlock(&query_lock);
1448     /***** CRITICAL SECTION END *****/
1449     if (found) return POLLIN | POLLRDNORM;
1450     return 0;
1451     }
1452    
1453 kumaneko 214 static int ReadQuery(struct io_buffer *head)
1454 kumaneko 111 {
1455     struct list_head *tmp;
1456     int pos = 0, len = 0;
1457     char *buf;
1458     if (head->read_avail) return 0;
1459     if (head->read_buf) {
1460     ccs_free(head->read_buf); head->read_buf = NULL;
1461     head->readbuf_size = 0;
1462     }
1463     /***** CRITICAL SECTION START *****/
1464     spin_lock(&query_lock);
1465     list_for_each(tmp, &query_list) {
1466 kumaneko 214 struct query_entry *ptr = list_entry(tmp, struct query_entry, list);
1467 kumaneko 111 if (pos++ == head->read_step) {
1468     len = ptr->query_len;
1469     break;
1470     }
1471     }
1472     spin_unlock(&query_lock);
1473     /***** CRITICAL SECTION END *****/
1474     if (!len) {
1475     head->read_step = 0;
1476     return 0;
1477     }
1478 kumaneko 214 if ((buf = ccs_alloc(len)) != NULL) {
1479 kumaneko 111 pos = 0;
1480     /***** CRITICAL SECTION START *****/
1481     spin_lock(&query_lock);
1482     list_for_each(tmp, &query_list) {
1483 kumaneko 214 struct query_entry *ptr = list_entry(tmp, struct query_entry, list);
1484 kumaneko 111 if (pos++ == head->read_step) {
1485     /* Some query can be skiipped since query_list can change, but I don't care. */
1486     if (len == ptr->query_len) memmove(buf, ptr->query, len);
1487     break;
1488     }
1489     }
1490     spin_unlock(&query_lock);
1491     /***** CRITICAL SECTION END *****/
1492     if (buf[0]) {
1493     head->readbuf_size = head->read_avail = len;
1494     head->read_buf = buf;
1495     head->read_step++;
1496     } else {
1497     ccs_free(buf);
1498     }
1499     }
1500     return 0;
1501     }
1502    
1503 kumaneko 214 static int WriteAnswer(struct io_buffer *head)
1504 kumaneko 111 {
1505     char *data = head->write_buf;
1506     struct list_head *tmp;
1507     unsigned int serial, answer;
1508     /***** CRITICAL SECTION START *****/
1509     spin_lock(&query_lock);
1510     list_for_each(tmp, &query_list) {
1511 kumaneko 214 struct query_entry *ptr = list_entry(tmp, struct query_entry, list);
1512 kumaneko 111 ptr->timer = 0;
1513     }
1514     spin_unlock(&query_lock);
1515     /***** CRITICAL SECTION END *****/
1516     if (sscanf(data, "A%u=%u", &serial, &answer) != 2) return -EINVAL;
1517     /***** CRITICAL SECTION START *****/
1518     spin_lock(&query_lock);
1519     list_for_each(tmp, &query_list) {
1520 kumaneko 214 struct query_entry *ptr = list_entry(tmp, struct query_entry, list);
1521 kumaneko 111 if (ptr->serial != serial) continue;
1522     if (!ptr->answer) ptr->answer = answer;
1523     break;
1524     }
1525     spin_unlock(&query_lock);
1526     /***** CRITICAL SECTION END *****/
1527     return 0;
1528     }
1529    
1530     /************************* /proc INTERFACE HANDLER *************************/
1531    
1532     /* Policy updates counter. */
1533     static unsigned int updates_counter[MAX_CCS_UPDATES_COUNTER];
1534     static spinlock_t updates_counter_lock = SPIN_LOCK_UNLOCKED;
1535    
1536     void UpdateCounter(const unsigned char index)
1537     {
1538     /***** CRITICAL SECTION START *****/
1539     spin_lock(&updates_counter_lock);
1540     if (index < MAX_CCS_UPDATES_COUNTER) updates_counter[index]++;
1541     spin_unlock(&updates_counter_lock);
1542     /***** CRITICAL SECTION END *****/
1543     }
1544    
1545 kumaneko 214 static int ReadUpdatesCounter(struct io_buffer *head)
1546 kumaneko 111 {
1547     if (!head->read_eof) {
1548     unsigned int counter[MAX_CCS_UPDATES_COUNTER];
1549     /***** CRITICAL SECTION START *****/
1550     spin_lock(&updates_counter_lock);
1551     memmove(counter, updates_counter, sizeof(updates_counter));
1552     memset(updates_counter, 0, sizeof(updates_counter));
1553     spin_unlock(&updates_counter_lock);
1554     /***** CRITICAL SECTION END *****/
1555     io_printf(head,
1556 kumaneko 346 "/proc/ccs/system_policy: %10u\n"
1557     "/proc/ccs/domain_policy: %10u\n"
1558     "/proc/ccs/exception_policy: %10u\n"
1559 kumaneko 418 "/proc/ccs/profile: %10u\n"
1560 kumaneko 346 "/proc/ccs/query: %10u\n"
1561     "/proc/ccs/manager: %10u\n"
1562     "/proc/ccs/grant_log: %10u\n"
1563     "/proc/ccs/reject_log: %10u\n",
1564 kumaneko 111 counter[CCS_UPDATES_COUNTER_SYSTEM_POLICY],
1565     counter[CCS_UPDATES_COUNTER_DOMAIN_POLICY],
1566     counter[CCS_UPDATES_COUNTER_EXCEPTION_POLICY],
1567 kumaneko 418 counter[CCS_UPDATES_COUNTER_PROFILE],
1568 kumaneko 111 counter[CCS_UPDATES_COUNTER_QUERY],
1569     counter[CCS_UPDATES_COUNTER_MANAGER],
1570     counter[CCS_UPDATES_COUNTER_GRANT_LOG],
1571     counter[CCS_UPDATES_COUNTER_REJECT_LOG]);
1572     head->read_eof = 1;
1573     }
1574     return 0;
1575     }
1576    
1577 kumaneko 332 static int ReadVersion(struct io_buffer *head)
1578     {
1579     if (!head->read_eof) {
1580 kumaneko 898 if (io_printf(head, "1.6.0-pre") == 0) head->read_eof = 1;
1581 kumaneko 332 }
1582     return 0;
1583     }
1584    
1585 kumaneko 214 static int ReadMemoryCounter(struct io_buffer *head)
1586 kumaneko 111 {
1587     if (!head->read_eof) {
1588     const int shared = GetMemoryUsedForSaveName(), private = GetMemoryUsedForElements(), dynamic = GetMemoryUsedForDynamic();
1589     if (io_printf(head, "Shared: %10u\nPrivate: %10u\nDynamic: %10u\nTotal: %10u\n", shared, private, dynamic, shared + private + dynamic) == 0) head->read_eof = 1;
1590     }
1591     return 0;
1592     }
1593    
1594 kumaneko 461 static int ReadSelfDomain(struct io_buffer *head)
1595     {
1596     if (!head->read_eof) {
1597     io_printf(head, "%s", current->domain_info->domainname->name);
1598     head->read_eof = 1;
1599     }
1600     return 0;
1601     }
1602    
1603 kumaneko 853 int CCS_OpenControl(const u8 type, struct file *file)
1604 kumaneko 111 {
1605 kumaneko 214 struct io_buffer *head = ccs_alloc(sizeof(*head));
1606 kumaneko 111 if (!head) return -ENOMEM;
1607 kumaneko 652 mutex_init(&head->read_sem);
1608     mutex_init(&head->write_sem);
1609 kumaneko 111 switch (type) {
1610 kumaneko 461 #ifdef CONFIG_SAKURA
1611     case CCS_SYSTEMPOLICY:
1612     head->write = AddSystemPolicy;
1613     head->read = ReadSystemPolicy;
1614     break;
1615     #endif
1616 kumaneko 111 #ifdef CONFIG_TOMOYO
1617 kumaneko 418 case CCS_DOMAINPOLICY:
1618 kumaneko 111 head->write = AddDomainPolicy;
1619     head->read = ReadDomainPolicy;
1620     break;
1621 kumaneko 418 case CCS_EXCEPTIONPOLICY:
1622 kumaneko 111 head->write = AddExceptionPolicy;
1623     head->read = ReadExceptionPolicy;
1624     break;
1625 kumaneko 418 case CCS_GRANTLOG:
1626 kumaneko 111 head->poll = PollGrantLog;
1627     head->read = ReadGrantLog;
1628     break;
1629 kumaneko 418 case CCS_REJECTLOG:
1630 kumaneko 111 head->poll = PollRejectLog;
1631     head->read = ReadRejectLog;
1632     break;
1633 kumaneko 461 #endif
1634 kumaneko 418 case CCS_SELFDOMAIN:
1635 kumaneko 111 head->read = ReadSelfDomain;
1636     break;
1637 kumaneko 461 case CCS_DOMAIN_STATUS:
1638     head->write = UpdateDomainProfile;
1639     head->read = ReadDomainProfile;
1640 kumaneko 111 break;
1641 kumaneko 461 case CCS_PROCESS_STATUS:
1642     head->write = WritePID;
1643     head->read = ReadPID;
1644     break;
1645 kumaneko 332 case CCS_VERSION:
1646     head->read = ReadVersion;
1647     head->readbuf_size = 128;
1648     break;
1649 kumaneko 418 case CCS_MEMINFO:
1650 kumaneko 111 head->read = ReadMemoryCounter;
1651     head->readbuf_size = 128;
1652     break;
1653 kumaneko 418 case CCS_PROFILE:
1654     head->write = SetProfile;
1655     head->read = ReadProfile;
1656 kumaneko 111 break;
1657 kumaneko 418 case CCS_QUERY:
1658 kumaneko 111 head->poll = PollQuery;
1659     head->write = WriteAnswer;
1660     head->read = ReadQuery;
1661     break;
1662 kumaneko 418 case CCS_MANAGER:
1663 kumaneko 111 head->write = AddManagerPolicy;
1664     head->read = ReadManagerPolicy;
1665     break;
1666 kumaneko 418 case CCS_UPDATESCOUNTER:
1667 kumaneko 111 head->read = ReadUpdatesCounter;
1668     break;
1669     }
1670 kumaneko 418 if (type != CCS_GRANTLOG && type != CCS_REJECTLOG && type != CCS_QUERY) {
1671 kumaneko 111 if (!head->readbuf_size) head->readbuf_size = PAGE_SIZE * 2;
1672     if ((head->read_buf = ccs_alloc(head->readbuf_size)) == NULL) {
1673     ccs_free(head);
1674     return -ENOMEM;
1675     }
1676     }
1677     if (head->write) {
1678     head->writebuf_size = PAGE_SIZE * 2;
1679     if ((head->write_buf = ccs_alloc(head->writebuf_size)) == NULL) {
1680     ccs_free(head->read_buf);
1681     ccs_free(head);
1682     return -ENOMEM;
1683     }
1684     }
1685 kumaneko 921 { /* Set owner of this entry. */
1686     struct inode *inode = file->f_dentry->d_inode;
1687     head->uid = inode ? inode->i_uid : 0;
1688     head->gid = inode ? inode->i_gid : 0;
1689     }
1690 kumaneko 111 file->private_data = head;
1691 kumaneko 418 if (type == CCS_SELFDOMAIN) CCS_ReadControl(file, NULL, 0);
1692 kumaneko 111 else if (head->write == WriteAnswer) atomic_inc(&queryd_watcher);
1693     return 0;
1694     }
1695    
1696 kumaneko 214 static int CopyToUser(struct io_buffer *head, char __user * buffer, int buffer_len)
1697 kumaneko 111 {
1698     int len = head->read_avail;
1699     char *cp = head->read_buf;
1700     if (len > buffer_len) len = buffer_len;
1701     if (len) {
1702     if (copy_to_user(buffer, cp, len)) return -EFAULT;
1703     head->read_avail -= len;
1704     memmove(cp, cp + len, head->read_avail);
1705     }
1706     return len;
1707     }
1708    
1709     int CCS_PollControl(struct file *file, poll_table *wait)
1710     {
1711 kumaneko 214 struct io_buffer *head = file->private_data;
1712 kumaneko 111 if (!head->poll) return -ENOSYS;
1713     return head->poll(file, wait);
1714     }
1715    
1716     int CCS_ReadControl(struct file *file, char __user *buffer, const int buffer_len)
1717     {
1718     int len = 0;
1719 kumaneko 214 struct io_buffer *head = file->private_data;
1720 kumaneko 111 if (!head->read) return -ENOSYS;
1721     if (!access_ok(VERIFY_WRITE, buffer, buffer_len)) return -EFAULT;
1722 kumaneko 652 if (mutex_lock_interruptible(&head->read_sem)) return -EINTR;
1723 kumaneko 111 len = head->read(head);
1724     if (len >= 0) len = CopyToUser(head, buffer, buffer_len);
1725 kumaneko 652 mutex_unlock(&head->read_sem);
1726 kumaneko 111 return len;
1727     }
1728    
1729     int CCS_WriteControl(struct file *file, const char __user *buffer, const int buffer_len)
1730     {
1731 kumaneko 214 struct io_buffer *head = file->private_data;
1732 kumaneko 111 int error = buffer_len;
1733     int avail_len = buffer_len;
1734     char *cp0 = head->write_buf;
1735     if (!head->write) return -ENOSYS;
1736     if (!access_ok(VERIFY_READ, buffer, buffer_len)) return -EFAULT;
1737 kumaneko 921 if (!isRoot(head)) return -EPERM;
1738 kumaneko 111 if (head->write != WritePID && !IsPolicyManager()) {
1739     return -EPERM; /* Forbid updating policies for non manager programs. */
1740     }
1741 kumaneko 652 if (mutex_lock_interruptible(&head->write_sem)) return -EINTR;
1742 kumaneko 111 while (avail_len > 0) {
1743     char c;
1744     if (head->write_avail >= head->writebuf_size - 1) {
1745     error = -ENOMEM;
1746     break;
1747     } else if (get_user(c, buffer)) {
1748     error = -EFAULT;
1749     break;
1750     }
1751     buffer++; avail_len--;
1752     cp0[head->write_avail++] = c;
1753     if (c != '\n') continue;
1754     cp0[head->write_avail - 1] = '\0';
1755     head->write_avail = 0;
1756     NormalizeLine(cp0);
1757     head->write(head);
1758     }
1759 kumaneko 652 mutex_unlock(&head->write_sem);
1760 kumaneko 111 return error;
1761     }
1762    
1763    
1764     int CCS_CloseControl(struct file *file)
1765     {
1766 kumaneko 214 struct io_buffer *head = file->private_data;
1767 kumaneko 111 if (head->write == WriteAnswer) atomic_dec(&queryd_watcher);
1768 kumaneko 325 else if (head->read == ReadMemoryCounter) profile_loaded = 1;
1769 kumaneko 111 ccs_free(head->read_buf); head->read_buf = NULL;
1770     ccs_free(head->write_buf); head->write_buf = NULL;
1771     ccs_free(head); head = NULL;
1772     file->private_data = NULL;
1773     return 0;
1774     }
1775 kumaneko 912
1776     void *alloc_acl_element(const u8 acl_type, const struct condition_list *condition)
1777     {
1778     int len;
1779 kumaneko 913 struct acl_info *ptr;
1780 kumaneko 912 switch (acl_type) {
1781     case TYPE_SINGLE_PATH_ACL:
1782     len = sizeof(struct single_path_acl_record);
1783     break;
1784     case TYPE_DOUBLE_PATH_ACL:
1785     len = sizeof(struct double_path_acl_record);
1786     break;
1787     case TYPE_ARGV0_ACL:
1788     len = sizeof(struct argv0_acl_record);
1789     break;
1790     case TYPE_ENV_ACL:
1791     len = sizeof(struct env_acl_record);
1792     break;
1793     case TYPE_CAPABILITY_ACL:
1794     len = sizeof(struct capability_acl_record);
1795     break;
1796     case TYPE_IP_NETWORK_ACL:
1797     len = sizeof(struct ip_network_acl_record);
1798     break;
1799     case TYPE_SIGNAL_ACL:
1800     len = sizeof(struct signal_acl_record);
1801     break;
1802     default:
1803     return NULL;
1804     }
1805 kumaneko 913 if (!condition) len -= sizeof(ptr->cond);
1806 kumaneko 912 ptr = alloc_element(len);
1807     if (!ptr) return NULL;
1808     if (condition) {
1809     ptr->cond = condition;
1810 kumaneko 913 ptr->type = acl_type | ACL_WITH_CONDITION;
1811     return ptr;
1812 kumaneko 912 }
1813 kumaneko 913 ptr = (void *) (((u8 *) ptr) - sizeof(ptr->cond));
1814     ptr->type = acl_type;
1815 kumaneko 912 return ptr;
1816     }
1817    
1818     const struct condition_list *GetConditionPart(const struct acl_info *acl)
1819     {
1820 kumaneko 913 return (acl->type & ACL_WITH_CONDITION) ? acl->cond : NULL;
1821 kumaneko 912 }

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