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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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