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

Subversion リポジトリの参照

Annotation of /trunk/1.5.x/ccs-patch/fs/ccs_common.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 325 - (hide annotations) (download) (as text)
Mon Aug 6 12:55:41 2007 UTC (16 years, 10 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 51561 byte(s)


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

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