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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2908 - (hide annotations) (download) (as text)
Sat Aug 15 07:28:22 2009 UTC (14 years, 9 months ago) by kumaneko
Original Path: branches/ccs-patch/security/ccsecurity/util.c
File MIME type: text/x-csrc
File size: 25870 byte(s)


1 kumaneko 111 /*
2 kumaneko 2864 * security/ccsecurity/util.c
3 kumaneko 111 *
4 kumaneko 2030 * Copyright (C) 2005-2009 NTT DATA CORPORATION
5 kumaneko 111 *
6 kumaneko 2869 * Version: 1.7.0-pre 2009/08/08
7 kumaneko 111 *
8     * This file is applicable to both 2.4.30 and 2.6.11 and later.
9     * See README.ccs for ChangeLog.
10     *
11     */
12    
13 kumaneko 2854 #include "internal.h"
14 kumaneko 1052
15 kumaneko 2690 DEFINE_MUTEX(ccs_policy_lock);
16 kumaneko 2540
17 kumaneko 1052 /* Has /sbin/init started? */
18 kumaneko 2040 bool ccs_policy_loaded;
19 kumaneko 111
20 kumaneko 1052 /* Capability name used by domain policy. */
21 kumaneko 2908 const char *ccs_capability_list[CCS_MAX_CAPABILITY_INDEX] = {
22 kumaneko 2282 [CCS_INET_STREAM_SOCKET_CREATE] = "inet_tcp_create",
23     [CCS_INET_STREAM_SOCKET_LISTEN] = "inet_tcp_listen",
24     [CCS_INET_STREAM_SOCKET_CONNECT] = "inet_tcp_connect",
25     [CCS_USE_INET_DGRAM_SOCKET] = "use_inet_udp",
26     [CCS_USE_INET_RAW_SOCKET] = "use_inet_ip",
27     [CCS_USE_ROUTE_SOCKET] = "use_route",
28     [CCS_USE_PACKET_SOCKET] = "use_packet",
29     [CCS_SYS_MOUNT] = "SYS_MOUNT",
30     [CCS_SYS_UMOUNT] = "SYS_UMOUNT",
31     [CCS_SYS_REBOOT] = "SYS_REBOOT",
32     [CCS_SYS_CHROOT] = "SYS_CHROOT",
33     [CCS_SYS_KILL] = "SYS_KILL",
34     [CCS_SYS_VHANGUP] = "SYS_VHANGUP",
35     [CCS_SYS_SETTIME] = "SYS_TIME",
36     [CCS_SYS_NICE] = "SYS_NICE",
37     [CCS_SYS_SETHOSTNAME] = "SYS_SETHOSTNAME",
38     [CCS_USE_KERNEL_MODULE] = "use_kernel_module",
39     [CCS_CREATE_FIFO] = "create_fifo",
40     [CCS_CREATE_BLOCK_DEV] = "create_block_dev",
41     [CCS_CREATE_CHAR_DEV] = "create_char_dev",
42     [CCS_CREATE_UNIX_SOCKET] = "create_unix_socket",
43     [CCS_SYS_LINK] = "SYS_LINK",
44     [CCS_SYS_SYMLINK] = "SYS_SYMLINK",
45     [CCS_SYS_RENAME] = "SYS_RENAME",
46     [CCS_SYS_UNLINK] = "SYS_UNLINK",
47     [CCS_SYS_CHMOD] = "SYS_CHMOD",
48     [CCS_SYS_CHOWN] = "SYS_CHOWN",
49     [CCS_SYS_IOCTL] = "SYS_IOCTL",
50     [CCS_SYS_KEXEC_LOAD] = "SYS_KEXEC_LOAD",
51     [CCS_SYS_PIVOT_ROOT] = "SYS_PIVOT_ROOT",
52     [CCS_SYS_PTRACE] = "SYS_PTRACE",
53 kumaneko 2708 [CCS_CONCEAL_MOUNT] = "conceal_mount",
54 kumaneko 1015 };
55    
56 kumaneko 1052 /* Profile table. Memory is allocated as needed. */
57 kumaneko 2892 struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES];
58 kumaneko 111
59 kumaneko 1052 /* Utility functions. */
60 kumaneko 111
61 kumaneko 1052 /**
62 kumaneko 2871 * ccs_parse_ulong - Parse an "unsigned long" value.
63     *
64     * @result: Pointer to "unsigned long".
65     * @str: Pointer to string to parse.
66     *
67     * Returns value type on success, 0 otherwise.
68     *
69     * The @src is updated to point the first character after the value
70     * on success.
71     */
72     u8 ccs_parse_ulong(unsigned long *result, char **str)
73     {
74     const char *cp = *str;
75     char *ep;
76     int base = 10;
77     if (*cp == '0') {
78     char c = *(cp + 1);
79     if (c == 'x' || c == 'X') {
80     base = 16;
81     cp += 2;
82     } else if (c >= '0' && c <= '7') {
83     base = 8;
84     cp++;
85     }
86     }
87     *result = simple_strtoul(cp, &ep, base);
88     if (cp == ep)
89     return 0;
90     *str = ep;
91     switch (base) {
92     case 16:
93 kumaneko 2892 return CCS_VALUE_TYPE_HEXADECIMAL;
94 kumaneko 2871 case 8:
95 kumaneko 2892 return CCS_VALUE_TYPE_OCTAL;
96 kumaneko 2871 default:
97 kumaneko 2892 return CCS_VALUE_TYPE_DECIMAL;
98 kumaneko 2871 }
99     }
100    
101     /**
102     * ccs_print_ulong - Print an "unsigned long" value.
103     *
104     * @buffer: Pointer to buffer.
105     * @buffer_len: Size of @buffer.
106     * @value: An "unsigned long" value.
107     * @type: Type of @value.
108     *
109     * Returns nothing.
110     */
111     void ccs_print_ulong(char *buffer, const int buffer_len,
112     const unsigned long value, const u8 type)
113     {
114 kumaneko 2892 if (type == CCS_VALUE_TYPE_DECIMAL)
115 kumaneko 2871 snprintf(buffer, buffer_len, "%lu", value);
116 kumaneko 2892 else if (type == CCS_VALUE_TYPE_OCTAL)
117 kumaneko 2871 snprintf(buffer, buffer_len, "0%lo", value);
118 kumaneko 2892 else if (type == CCS_VALUE_TYPE_HEXADECIMAL)
119 kumaneko 2871 snprintf(buffer, buffer_len, "0x%lX", value);
120     else
121     snprintf(buffer, buffer_len, "type(%u)", type);
122     }
123    
124 kumaneko 2894 bool ccs_parse_name_union(const char *filename, struct ccs_name_union *ptr)
125     {
126     if (!ccs_is_correct_path(filename, 0, 0, 0))
127     return false;
128     if (filename[0] == '@') {
129     ptr->group = ccs_get_path_group(filename + 1);
130     ptr->is_group = true;
131     return ptr->group != NULL;
132     }
133     ptr->filename = ccs_get_name(filename);
134     ptr->is_group = false;
135     return ptr->filename != NULL;
136     }
137    
138 kumaneko 2888 bool ccs_parse_number_union(char *data, struct ccs_number_union *num)
139 kumaneko 2871 {
140     u8 type;
141     unsigned long v;
142     memset(num, 0, sizeof(*num));
143 kumaneko 2890 if (data[0] == '@') {
144     if (!ccs_is_correct_path(data, 0, 0, 0))
145     return false;
146     num->group = ccs_get_number_group(data + 1);
147     num->is_group = true;
148     return num->group != NULL;
149     }
150 kumaneko 2871 type = ccs_parse_ulong(&v, &data);
151     if (!type)
152     return false;
153 kumaneko 2888 num->values[0] = v;
154     num->min_type = type;
155 kumaneko 2871 if (!*data) {
156 kumaneko 2888 num->values[1] = v;
157     num->max_type = type;
158 kumaneko 2871 return true;
159     }
160     if (*data++ != '-')
161     return false;
162     type = ccs_parse_ulong(&v, &data);
163     if (!type || *data)
164     return false;
165 kumaneko 2888 num->values[1] = v;
166     num->max_type = type;
167 kumaneko 2871 return true;
168     }
169    
170     /**
171 kumaneko 2002 * ccs_is_byte_range - Check whether the string isa \ooo style octal value.
172 kumaneko 1052 *
173     * @str: Pointer to the string.
174     *
175     * Returns true if @str is a \ooo style octal value, false otherwise.
176     */
177 kumaneko 2002 static inline bool ccs_is_byte_range(const char *str)
178 kumaneko 1052 {
179     return *str >= '0' && *str++ <= '3' &&
180     *str >= '0' && *str++ <= '7' &&
181     *str >= '0' && *str <= '7';
182     }
183    
184     /**
185 kumaneko 2002 * ccs_is_decimal - Check whether the character is a decimal character.
186 kumaneko 1052 *
187     * @c: The character to check.
188     *
189     * Returns true if @c is a decimal character, false otherwise.
190     */
191 kumaneko 2002 static inline bool ccs_is_decimal(const char c)
192 kumaneko 1052 {
193 kumaneko 1468 return c >= '0' && c <= '9';
194 kumaneko 1052 }
195    
196     /**
197 kumaneko 2002 * ccs_is_hexadecimal - Check whether the character is a hexadecimal character.
198 kumaneko 1052 *
199     * @c: The character to check.
200     *
201     * Returns true if @c is a hexadecimal character, false otherwise.
202     */
203 kumaneko 2002 static inline bool ccs_is_hexadecimal(const char c)
204 kumaneko 1052 {
205 kumaneko 1468 return (c >= '0' && c <= '9') ||
206 kumaneko 1052 (c >= 'A' && c <= 'F') ||
207 kumaneko 1468 (c >= 'a' && c <= 'f');
208 kumaneko 1052 }
209    
210     /**
211 kumaneko 2002 * ccs_is_alphabet_char - Check whether the character is an alphabet.
212 kumaneko 1052 *
213     * @c: The character to check.
214     *
215     * Returns true if @c is an alphabet character, false otherwise.
216     */
217 kumaneko 2002 static inline bool ccs_is_alphabet_char(const char c)
218 kumaneko 1052 {
219 kumaneko 1794 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
220 kumaneko 1052 }
221    
222     /**
223 kumaneko 2002 * ccs_make_byte - Make byte value from three octal characters.
224 kumaneko 1064 *
225     * @c1: The first character.
226     * @c2: The second character.
227     * @c3: The third character.
228     *
229     * Returns byte value.
230     */
231 kumaneko 2002 static inline u8 ccs_make_byte(const u8 c1, const u8 c2, const u8 c3)
232 kumaneko 1064 {
233     return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
234     }
235    
236     /**
237 kumaneko 2002 * ccs_str_starts - Check whether the given string starts with the given keyword.
238 kumaneko 1052 *
239     * @src: Pointer to pointer to the string.
240     * @find: Pointer to the keyword.
241     *
242     * Returns true if @src starts with @find, false otherwise.
243     *
244     * The @src is updated to point the first character after the @find
245 kumaneko 1064 * if @src starts with @find.
246 kumaneko 1052 */
247 kumaneko 2863 bool ccs_str_starts(char **src, const char *find)
248 kumaneko 1052 {
249     const int len = strlen(find);
250     char *tmp = *src;
251     if (strncmp(tmp, find, len))
252     return false;
253     tmp += len;
254     *src = tmp;
255     return true;
256     }
257    
258     /**
259 kumaneko 2002 * ccs_normalize_line - Format string.
260 kumaneko 1052 *
261     * @buffer: The line to normalize.
262     *
263 kumaneko 111 * Leading and trailing whitespaces are removed.
264     * Multiple whitespaces are packed into single space.
265 kumaneko 1052 *
266     * Returns nothing.
267 kumaneko 111 */
268 kumaneko 2308 void ccs_normalize_line(unsigned char *buffer)
269 kumaneko 111 {
270 kumaneko 1064 unsigned char *sp = buffer;
271     unsigned char *dp = buffer;
272 kumaneko 1006 bool first = true;
273 kumaneko 1052 while (*sp && (*sp <= ' ' || *sp >= 127))
274     sp++;
275 kumaneko 111 while (*sp) {
276 kumaneko 1052 if (!first)
277     *dp++ = ' ';
278 kumaneko 1006 first = false;
279 kumaneko 1052 while (*sp > ' ' && *sp < 127)
280     *dp++ = *sp++;
281     while (*sp && (*sp <= ' ' || *sp >= 127))
282     sp++;
283 kumaneko 111 }
284     *dp = '\0';
285     }
286    
287 kumaneko 1052 /**
288 kumaneko 2779 * ccs_tokenize - Tokenize string.
289     *
290     * @buffer: The line to tokenize.
291     * @w: Pointer to "char *".
292     * @size: Sizeof @w .
293     *
294     * Returns true on success, false otherwise.
295     */
296     bool ccs_tokenize(char *buffer, char *w[], size_t size)
297     {
298     int count = size / sizeof(char *);
299     int i;
300     for (i = 0; i < count; i++)
301     w[i] = "";
302     for (i = 0; i < count; i++) {
303     char *cp = strchr(buffer, ' ');
304     if (cp)
305     *cp = '\0';
306     w[i] = buffer;
307     if (!cp)
308     break;
309     buffer = cp + 1;
310     }
311     return i < count || !*buffer;
312     }
313    
314     /**
315 kumaneko 1054 * ccs_is_correct_path - Validate a pathname.
316     * @filename: The pathname to check.
317     * @start_type: Should the pathname start with '/'?
318     * 1 = must / -1 = must not / 0 = don't care
319     * @pattern_type: Can the pathname contain a wildcard?
320     * 1 = must / -1 = must not / 0 = don't care
321     * @end_type: Should the pathname end with '/'?
322     * 1 = must / -1 = must not / 0 = don't care
323 kumaneko 1052 *
324 kumaneko 1054 * Check whether the given filename follows the naming rules.
325 kumaneko 1052 * Returns true if @filename follows the naming rules, false otherwise.
326 kumaneko 111 */
327 kumaneko 1052 bool ccs_is_correct_path(const char *filename, const s8 start_type,
328 kumaneko 2577 const s8 pattern_type, const s8 end_type)
329 kumaneko 111 {
330 kumaneko 1006 bool contains_pattern = false;
331 kumaneko 1064 unsigned char c;
332     unsigned char d;
333     unsigned char e;
334 kumaneko 111 const char *original_filename = filename;
335 kumaneko 1052 if (!filename)
336     goto out;
337 kumaneko 111 c = *filename;
338     if (start_type == 1) { /* Must start with '/' */
339 kumaneko 1052 if (c != '/')
340     goto out;
341 kumaneko 111 } else if (start_type == -1) { /* Must not start with '/' */
342 kumaneko 1052 if (c == '/')
343     goto out;
344 kumaneko 111 }
345 kumaneko 1052 if (c)
346 kumaneko 1795 c = *(filename + strlen(filename) - 1);
347 kumaneko 111 if (end_type == 1) { /* Must end with '/' */
348 kumaneko 1052 if (c != '/')
349     goto out;
350 kumaneko 111 } else if (end_type == -1) { /* Must not end with '/' */
351 kumaneko 1052 if (c == '/')
352     goto out;
353 kumaneko 111 }
354 kumaneko 1747 while (1) {
355     c = *filename++;
356     if (!c)
357     break;
358 kumaneko 111 if (c == '\\') {
359 kumaneko 1747 c = *filename++;
360     switch (c) {
361 kumaneko 111 case '\\': /* "\\" */
362     continue;
363     case '$': /* "\$" */
364     case '+': /* "\+" */
365     case '?': /* "\?" */
366     case '*': /* "\*" */
367     case '@': /* "\@" */
368     case 'x': /* "\x" */
369     case 'X': /* "\X" */
370     case 'a': /* "\a" */
371     case 'A': /* "\A" */
372 kumaneko 206 case '-': /* "\-" */
373 kumaneko 1052 if (pattern_type == -1)
374     break; /* Must not contain pattern */
375 kumaneko 1006 contains_pattern = true;
376 kumaneko 111 continue;
377     case '0': /* "\ooo" */
378     case '1':
379     case '2':
380     case '3':
381 kumaneko 1052 d = *filename++;
382     if (d < '0' || d > '7')
383     break;
384     e = *filename++;
385     if (e < '0' || e > '7')
386     break;
387 kumaneko 2002 c = ccs_make_byte(c, d, e);
388 kumaneko 1052 if (c && (c <= ' ' || c >= 127))
389     continue; /* pattern is not \000 */
390 kumaneko 111 }
391     goto out;
392     } else if (c <= ' ' || c >= 127) {
393     goto out;
394     }
395     }
396     if (pattern_type == 1) { /* Must contain pattern */
397 kumaneko 1052 if (!contains_pattern)
398     goto out;
399 kumaneko 111 }
400 kumaneko 1006 return true;
401 kumaneko 111 out:
402 kumaneko 2577 printk(KERN_DEBUG "Invalid pathname '%s'\n", original_filename);
403 kumaneko 1006 return false;
404 kumaneko 111 }
405    
406 kumaneko 1052 /**
407 kumaneko 1054 * ccs_is_correct_domain - Check whether the given domainname follows the naming rules.
408     * @domainname: The domainname to check.
409 kumaneko 1052 *
410     * Returns true if @domainname follows the naming rules, false otherwise.
411 kumaneko 111 */
412 kumaneko 2577 bool ccs_is_correct_domain(const unsigned char *domainname)
413 kumaneko 111 {
414 kumaneko 1064 unsigned char c;
415     unsigned char d;
416     unsigned char e;
417 kumaneko 111 const char *org_domainname = domainname;
418 kumaneko 1052 if (!domainname || strncmp(domainname, ROOT_NAME, ROOT_NAME_LEN))
419     goto out;
420 kumaneko 111 domainname += ROOT_NAME_LEN;
421 kumaneko 1052 if (!*domainname)
422     return true;
423 kumaneko 111 do {
424 kumaneko 1052 if (*domainname++ != ' ')
425     goto out;
426     if (*domainname++ != '/')
427     goto out;
428 kumaneko 1747 while (1) {
429     c = *domainname;
430     if (!c || c == ' ')
431     break;
432 kumaneko 111 domainname++;
433     if (c == '\\') {
434 kumaneko 1052 c = *domainname++;
435     switch ((c)) {
436 kumaneko 111 case '\\': /* "\\" */
437     continue;
438     case '0': /* "\ooo" */
439     case '1':
440     case '2':
441     case '3':
442 kumaneko 1052 d = *domainname++;
443     if (d < '0' || d > '7')
444     break;
445     e = *domainname++;
446     if (e < '0' || e > '7')
447     break;
448 kumaneko 2002 c = ccs_make_byte(c, d, e);
449 kumaneko 1052 if (c && (c <= ' ' || c >= 127))
450     /* pattern is not \000 */
451     continue;
452 kumaneko 111 }
453     goto out;
454     } else if (c < ' ' || c >= 127) {
455     goto out;
456     }
457     }
458     } while (*domainname);
459 kumaneko 1006 return true;
460 kumaneko 111 out:
461 kumaneko 2577 printk(KERN_DEBUG "Invalid domainname '%s'\n", org_domainname);
462 kumaneko 1006 return false;
463 kumaneko 111 }
464    
465 kumaneko 1052 /**
466     * ccs_is_domain_def - Check whether the given token can be a domainname.
467     *
468     * @buffer: The token to check.
469     *
470     * Returns true if @buffer possibly be a domainname, false otherwise.
471     */
472     bool ccs_is_domain_def(const unsigned char *buffer)
473 kumaneko 461 {
474 kumaneko 1052 return !strncmp(buffer, ROOT_NAME, ROOT_NAME_LEN);
475 kumaneko 461 }
476    
477 kumaneko 1052 /**
478     * ccs_find_domain - Find a domain by the given name.
479     *
480 kumaneko 1054 * @domainname: The domainname to find.
481 kumaneko 1052 *
482 kumaneko 2690 * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise.
483     *
484 kumaneko 2828 * Caller holds ccs_read_lock().
485 kumaneko 1052 */
486 kumaneko 2690 struct ccs_domain_info *ccs_find_domain(const char *domainname)
487 kumaneko 461 {
488 kumaneko 2282 struct ccs_domain_info *domain;
489 kumaneko 2002 struct ccs_path_info name;
490 kumaneko 2828 ccs_check_read_lock();
491 kumaneko 1052 name.name = domainname;
492     ccs_fill_path_info(&name);
493 kumaneko 2690 list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
494 kumaneko 2692 if (!domain->is_deleted &&
495     !ccs_pathcmp(&name, domain->domainname))
496     return domain;
497 kumaneko 461 }
498 kumaneko 2692 return NULL;
499 kumaneko 461 }
500    
501 kumaneko 1052 /**
502 kumaneko 2002 * ccs_path_depth - Evaluate the number of '/' in a string.
503 kumaneko 1052 *
504     * @pathname: The string to evaluate.
505     *
506     * Returns path depth of the string.
507     *
508     * I score 2 for each of the '/' in the @pathname
509     * and score 1 if the @pathname ends with '/'.
510     */
511 kumaneko 2002 static int ccs_path_depth(const char *pathname)
512 kumaneko 111 {
513     int i = 0;
514     if (pathname) {
515 kumaneko 1795 const char *ep = pathname + strlen(pathname);
516 kumaneko 111 if (pathname < ep--) {
517 kumaneko 1052 if (*ep != '/')
518     i++;
519     while (pathname <= ep)
520     if (*ep-- == '/')
521     i += 2;
522 kumaneko 111 }
523     }
524     return i;
525     }
526    
527 kumaneko 1052 /**
528 kumaneko 2002 * ccs_const_part_length - Evaluate the initial length without a pattern in a token.
529 kumaneko 1052 *
530     * @filename: The string to evaluate.
531     *
532 kumaneko 1064 * Returns the initial length without a pattern in @filename.
533 kumaneko 1052 */
534 kumaneko 2002 static int ccs_const_part_length(const char *filename)
535 kumaneko 111 {
536 kumaneko 1052 char c;
537 kumaneko 111 int len = 0;
538 kumaneko 1052 if (!filename)
539     return 0;
540 kumaneko 1747 while (1) {
541     c = *filename++;
542     if (!c)
543     break;
544 kumaneko 1052 if (c != '\\') {
545     len++;
546     continue;
547 kumaneko 111 }
548 kumaneko 1052 c = *filename++;
549     switch (c) {
550     case '\\': /* "\\" */
551     len += 2;
552     continue;
553     case '0': /* "\ooo" */
554     case '1':
555     case '2':
556     case '3':
557     c = *filename++;
558     if (c < '0' || c > '7')
559     break;
560     c = *filename++;
561     if (c < '0' || c > '7')
562     break;
563     len += 4;
564     continue;
565     }
566     break;
567 kumaneko 111 }
568     return len;
569     }
570    
571 kumaneko 1052 /**
572 kumaneko 2002 * ccs_fill_path_info - Fill in "struct ccs_path_info" members.
573 kumaneko 1052 *
574 kumaneko 2002 * @ptr: Pointer to "struct ccs_path_info" to fill in.
575 kumaneko 1052 *
576 kumaneko 2002 * The caller sets "struct ccs_path_info"->name.
577 kumaneko 1052 */
578 kumaneko 2002 void ccs_fill_path_info(struct ccs_path_info *ptr)
579 kumaneko 111 {
580     const char *name = ptr->name;
581     const int len = strlen(name);
582     ptr->total_len = len;
583 kumaneko 2002 ptr->const_len = ccs_const_part_length(name);
584 kumaneko 111 ptr->is_dir = len && (name[len - 1] == '/');
585     ptr->is_patterned = (ptr->const_len < len);
586     ptr->hash = full_name_hash(name, len);
587 kumaneko 2002 ptr->depth = ccs_path_depth(name);
588 kumaneko 111 }
589    
590 kumaneko 1052 /**
591 kumaneko 2039 * ccs_file_matches_pattern2 - Pattern matching without '/' character
592 kumaneko 1052 * and "\-" pattern.
593     *
594     * @filename: The start of string to check.
595     * @filename_end: The end of string to check.
596     * @pattern: The start of pattern to compare.
597     * @pattern_end: The end of pattern to compare.
598     *
599     * Returns true if @filename matches @pattern, false otherwise.
600     */
601 kumaneko 2039 static bool ccs_file_matches_pattern2(const char *filename,
602     const char *filename_end,
603     const char *pattern,
604     const char *pattern_end)
605 kumaneko 111 {
606     while (filename < filename_end && pattern < pattern_end) {
607 kumaneko 1052 char c;
608 kumaneko 111 if (*pattern != '\\') {
609 kumaneko 1052 if (*filename++ != *pattern++)
610     return false;
611     continue;
612     }
613     c = *filename;
614     pattern++;
615     switch (*pattern) {
616 kumaneko 1064 int i;
617     int j;
618 kumaneko 1052 case '?':
619     if (c == '/') {
620     return false;
621     } else if (c == '\\') {
622     if (filename[1] == '\\')
623     filename++;
624 kumaneko 2002 else if (ccs_is_byte_range(filename + 1))
625 kumaneko 1052 filename += 3;
626     else
627 kumaneko 1006 return false;
628 kumaneko 1052 }
629     break;
630     case '\\':
631     if (c != '\\')
632     return false;
633     if (*++filename != '\\')
634     return false;
635     break;
636     case '+':
637 kumaneko 2002 if (!ccs_is_decimal(c))
638 kumaneko 1052 return false;
639     break;
640     case 'x':
641 kumaneko 2002 if (!ccs_is_hexadecimal(c))
642 kumaneko 1052 return false;
643     break;
644     case 'a':
645 kumaneko 2002 if (!ccs_is_alphabet_char(c))
646 kumaneko 1052 return false;
647     break;
648     case '0':
649     case '1':
650     case '2':
651     case '3':
652 kumaneko 2002 if (c == '\\' && ccs_is_byte_range(filename + 1)
653 kumaneko 1052 && strncmp(filename + 1, pattern, 3) == 0) {
654     filename += 3;
655     pattern += 2;
656 kumaneko 111 break;
657 kumaneko 1052 }
658     return false; /* Not matched. */
659     case '*':
660     case '@':
661     for (i = 0; i <= filename_end - filename; i++) {
662 kumaneko 2039 if (ccs_file_matches_pattern2(filename + i,
663     filename_end,
664     pattern + 1,
665     pattern_end))
666 kumaneko 1052 return true;
667     c = filename[i];
668     if (c == '.' && *pattern == '@')
669 kumaneko 111 break;
670 kumaneko 1052 if (c != '\\')
671     continue;
672     if (filename[i + 1] == '\\')
673     i++;
674 kumaneko 2002 else if (ccs_is_byte_range(filename + i + 1))
675 kumaneko 1052 i += 3;
676     else
677     break; /* Bad pattern. */
678 kumaneko 111 }
679 kumaneko 1052 return false; /* Not matched. */
680     default:
681     j = 0;
682     c = *pattern;
683     if (c == '$') {
684 kumaneko 2002 while (ccs_is_decimal(filename[j]))
685 kumaneko 1052 j++;
686     } else if (c == 'X') {
687 kumaneko 2002 while (ccs_is_hexadecimal(filename[j]))
688 kumaneko 1052 j++;
689     } else if (c == 'A') {
690 kumaneko 2002 while (ccs_is_alphabet_char(filename[j]))
691 kumaneko 1052 j++;
692     }
693     for (i = 1; i <= j; i++) {
694 kumaneko 2039 if (ccs_file_matches_pattern2(filename + i,
695     filename_end,
696     pattern + 1,
697     pattern_end))
698 kumaneko 1052 return true;
699     }
700     return false; /* Not matched or bad pattern. */
701 kumaneko 111 }
702 kumaneko 1052 filename++;
703     pattern++;
704 kumaneko 111 }
705 kumaneko 1052 while (*pattern == '\\' &&
706     (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
707     pattern += 2;
708 kumaneko 1468 return filename == filename_end && pattern == pattern_end;
709 kumaneko 111 }
710    
711 kumaneko 1052 /**
712 kumaneko 2039 * ccs_file_matches_pattern - Pattern matching without without '/' character.
713 kumaneko 1052 *
714     * @filename: The start of string to check.
715     * @filename_end: The end of string to check.
716     * @pattern: The start of pattern to compare.
717     * @pattern_end: The end of pattern to compare.
718     *
719     * Returns true if @filename matches @pattern, false otherwise.
720     */
721 kumaneko 2039 static bool ccs_file_matches_pattern(const char *filename,
722     const char *filename_end,
723     const char *pattern,
724     const char *pattern_end)
725 kumaneko 206 {
726     const char *pattern_start = pattern;
727 kumaneko 1006 bool first = true;
728     bool result;
729 kumaneko 206 while (pattern < pattern_end - 1) {
730 kumaneko 1052 /* Split at "\-" pattern. */
731     if (*pattern++ != '\\' || *pattern++ != '-')
732     continue;
733 kumaneko 2039 result = ccs_file_matches_pattern2(filename, filename_end,
734 kumaneko 2040 pattern_start, pattern - 2);
735 kumaneko 1052 if (first)
736     result = !result;
737     if (result)
738     return false;
739 kumaneko 1006 first = false;
740 kumaneko 206 pattern_start = pattern;
741     }
742 kumaneko 2039 result = ccs_file_matches_pattern2(filename, filename_end,
743     pattern_start, pattern_end);
744 kumaneko 206 return first ? result : !result;
745     }
746    
747 kumaneko 1052 /**
748 kumaneko 1054 * ccs_path_matches_pattern - Check whether the given filename matches the given pattern.
749 kumaneko 1052 * @filename: The filename to check.
750     * @pattern: The pattern to compare.
751 kumaneko 111 *
752 kumaneko 1052 * Returns true if matches, false otherwise.
753     *
754     * The following patterns are available.
755     * \\ \ itself.
756     * \ooo Octal representation of a byte.
757     * \* More than or equals to 0 character other than '/'.
758     * \@ More than or equals to 0 character other than '/' or '.'.
759     * \? 1 byte character other than '/'.
760     * \$ More than or equals to 1 decimal digit.
761     * \+ 1 decimal digit.
762     * \X More than or equals to 1 hexadecimal digit.
763     * \x 1 hexadecimal digit.
764     * \A More than or equals to 1 alphabet character.
765     * \a 1 alphabet character.
766     * \- Subtraction operator.
767 kumaneko 111 */
768 kumaneko 2002 bool ccs_path_matches_pattern(const struct ccs_path_info *filename,
769     const struct ccs_path_info *pattern)
770 kumaneko 111 {
771 kumaneko 1052 /*
772     if (!filename || !pattern)
773     return false;
774     */
775     const char *f = filename->name;
776     const char *p = pattern->name;
777     const int len = pattern->const_len;
778     /* If @pattern doesn't contain pattern, I can use strcmp(). */
779     if (!pattern->is_patterned)
780     return !ccs_pathcmp(filename, pattern);
781 kumaneko 2892 /* Don't compare if the number of '/' differs. */
782 kumaneko 1052 if (filename->depth != pattern->depth)
783     return false;
784     /* Compare the initial length without patterns. */
785     if (strncmp(f, p, len))
786     return false;
787     f += len;
788     p += len;
789     /* Main loop. Compare each directory component. */
790     while (*f && *p) {
791     const char *f_delimiter = strchr(f, '/');
792     const char *p_delimiter = strchr(p, '/');
793     if (!f_delimiter)
794 kumaneko 1795 f_delimiter = f + strlen(f);
795 kumaneko 1052 if (!p_delimiter)
796 kumaneko 1795 p_delimiter = p + strlen(p);
797 kumaneko 2040 if (!ccs_file_matches_pattern(f, f_delimiter, p, p_delimiter))
798 kumaneko 1052 return false;
799     f = f_delimiter;
800     if (*f)
801     f++;
802     p = p_delimiter;
803     if (*p)
804     p++;
805 kumaneko 111 }
806 kumaneko 1052 /* Ignore trailing "\*" and "\@" in @pattern. */
807     while (*p == '\\' &&
808     (*(p + 1) == '*' || *(p + 1) == '@'))
809     p += 2;
810 kumaneko 1468 return !*f && !*p;
811 kumaneko 111 }
812    
813 kumaneko 1052 /**
814     * ccs_get_exe - Get ccs_realpath() of current process.
815     *
816     * Returns the ccs_realpath() of current process on success, NULL otherwise.
817     *
818 kumaneko 2711 * This function uses kzalloc(), so the caller must kfree()
819 kumaneko 1052 * if this function didn't return NULL.
820 kumaneko 111 */
821 kumaneko 1052 const char *ccs_get_exe(void)
822 kumaneko 111 {
823 kumaneko 737 struct mm_struct *mm = current->mm;
824     struct vm_area_struct *vma;
825     const char *cp = NULL;
826 kumaneko 1052 if (!mm)
827     return NULL;
828 kumaneko 737 down_read(&mm->mmap_sem);
829     for (vma = mm->mmap; vma; vma = vma->vm_next) {
830     if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
831 kumaneko 1052 cp = ccs_realpath_from_dentry(vma->vm_file->f_dentry,
832     vma->vm_file->f_vfsmnt);
833 kumaneko 737 break;
834 kumaneko 111 }
835     }
836 kumaneko 737 up_read(&mm->mmap_sem);
837     return cp;
838 kumaneko 111 }
839    
840 kumaneko 1052 /**
841     * ccs_get_msg - Get warning message.
842     *
843     * @is_enforce: Is it enforcing mode?
844     *
845     * Returns "ERROR" or "WARNING".
846     */
847     const char *ccs_get_msg(const bool is_enforce)
848 kumaneko 111 {
849 kumaneko 1052 if (is_enforce)
850     return "ERROR";
851     else
852     return "WARNING";
853 kumaneko 111 }
854    
855 kumaneko 1052 /**
856 kumaneko 1657 * ccs_can_sleep - Check whether it is permitted to do operations that may sleep.
857 kumaneko 1052 *
858     * Returns true if it is permitted to do operations that may sleep,
859     * false otherwise.
860     *
861     * TOMOYO Linux supports interactive enforcement that lets processes
862     * wait for the administrator's decision.
863     * All hooks but the one for ccs_may_autobind() are inserted where
864     * it is permitted to do operations that may sleep.
865     * Thus, this warning should not happen.
866     */
867 kumaneko 1657 bool ccs_can_sleep(void)
868 kumaneko 899 {
869 kumaneko 1052 static u8 count = 20;
870     if (likely(!in_interrupt()))
871     return true;
872     if (count) {
873     count--;
874     printk(KERN_ERR "BUG: sleeping function called "
875     "from invalid context.\n");
876     dump_stack();
877 kumaneko 899 }
878 kumaneko 1052 return false;
879 kumaneko 899 }
880    
881 kumaneko 1052 /**
882     * ccs_check_flags - Check mode for specified functionality.
883     *
884 kumaneko 2282 * @domain: Pointer to "struct ccs_domain_info". NULL for ccs_current_domain().
885 kumaneko 1657 * @index: The functionality to check mode.
886 kumaneko 1052 *
887     * Returns the mode of specified functionality.
888     */
889 kumaneko 2282 unsigned int ccs_check_flags(const struct ccs_domain_info *domain,
890     const u8 index)
891 kumaneko 1015 {
892 kumaneko 1657 u8 profile;
893     if (!domain)
894 kumaneko 2282 domain = ccs_current_domain();
895 kumaneko 1657 profile = domain->profile;
896 kumaneko 2040 return ccs_policy_loaded && index < CCS_MAX_CONTROL_INDEX
897 kumaneko 2892 #if CCS_MAX_PROFILES != 256
898     && profile < CCS_MAX_PROFILES
899 kumaneko 1657 #endif
900 kumaneko 2002 && ccs_profile_ptr[profile] ?
901     ccs_profile_ptr[profile]->value[index] : 0;
902 kumaneko 1015 }
903    
904 kumaneko 1052 /**
905     * ccs_cap2keyword - Convert capability operation to capability name.
906     *
907     * @operation: The capability index.
908     *
909     * Returns the name of the specified capability's name.
910     */
911     const char *ccs_cap2keyword(const u8 operation)
912 kumaneko 1015 {
913 kumaneko 2282 return operation < CCS_MAX_CAPABILITY_INDEX
914 kumaneko 2908 ? ccs_capability_list[operation] : NULL;
915 kumaneko 1015 }
916    
917 kumaneko 1052 /**
918 kumaneko 1657 * ccs_init_request_info - Initialize "struct ccs_request_info" members.
919     *
920     * @r: Pointer to "struct ccs_request_info" to initialize.
921 kumaneko 2282 * @domain: Pointer to "struct ccs_domain_info". NULL for ccs_current_domain().
922 kumaneko 1657 * @index: Index number of functionality.
923     */
924     void ccs_init_request_info(struct ccs_request_info *r,
925 kumaneko 2282 struct ccs_domain_info *domain, const u8 index)
926 kumaneko 1657 {
927     memset(r, 0, sizeof(*r));
928     if (!domain)
929 kumaneko 2282 domain = ccs_current_domain();
930 kumaneko 2690 r->domain = domain;
931 kumaneko 1657 r->profile = domain->profile;
932     if (index < CCS_MAX_CONTROL_INDEX)
933     r->mode = ccs_check_flags(domain, index);
934     }
935    
936     /**
937 kumaneko 1052 * ccs_verbose_mode - Check whether TOMOYO is verbose mode.
938     *
939 kumaneko 2282 * @domain: Pointer to "struct ccs_domain_info". NULL for ccs_current_domain().
940 kumaneko 1657 *
941 kumaneko 1052 * Returns true if domain policy violation warning should be printed to
942     * console.
943     */
944 kumaneko 2282 bool ccs_verbose_mode(const struct ccs_domain_info *domain)
945 kumaneko 111 {
946 kumaneko 2282 return ccs_check_flags(domain, CCS_VERBOSE) != 0;
947 kumaneko 111 }
948    
949 kumaneko 1052 /**
950 kumaneko 2209 * ccs_domain_quota_ok - Check for domain's quota.
951 kumaneko 1052 *
952 kumaneko 2780 * @r: Pointer to "struct ccs_request_info".
953 kumaneko 1052 *
954     * Returns true if the domain is not exceeded quota, false otherwise.
955 kumaneko 2690 *
956 kumaneko 2828 * Caller holds ccs_read_lock().
957 kumaneko 1052 */
958 kumaneko 2780 bool ccs_domain_quota_ok(struct ccs_request_info *r)
959 kumaneko 512 {
960     unsigned int count = 0;
961 kumaneko 2780 struct ccs_domain_info *domain = r->domain;
962 kumaneko 2002 struct ccs_acl_info *ptr;
963 kumaneko 2828 ccs_check_read_lock();
964 kumaneko 2780 if (r->mode != 1)
965     return false;
966 kumaneko 1052 if (!domain)
967     return true;
968 kumaneko 2690 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
969 kumaneko 2900 if (ptr->is_deleted)
970 kumaneko 1064 continue;
971 kumaneko 2900 switch (ptr->type) {
972 kumaneko 2002 struct ccs_single_path_acl_record *acl1;
973     struct ccs_double_path_acl_record *acl2;
974 kumaneko 1064 u16 perm;
975 kumaneko 2892 case CCS_TYPE_SINGLE_PATH_ACL:
976 kumaneko 2002 acl1 = container_of(ptr,
977     struct ccs_single_path_acl_record,
978 kumaneko 1064 head);
979     perm = acl1->perm;
980 kumaneko 2892 if (perm & (1 << CCS_TYPE_EXECUTE_ACL))
981 kumaneko 1064 count++;
982 kumaneko 2892 if (perm & ((1 << CCS_TYPE_READ_ACL) |
983     (1 << CCS_TYPE_WRITE_ACL)))
984 kumaneko 1064 count++;
985 kumaneko 2892 if (perm & (1 << CCS_TYPE_CREATE_ACL))
986 kumaneko 1064 count++;
987 kumaneko 2892 if (perm & (1 << CCS_TYPE_UNLINK_ACL))
988 kumaneko 1064 count++;
989 kumaneko 2892 if (perm & (1 << CCS_TYPE_MKDIR_ACL))
990 kumaneko 1064 count++;
991 kumaneko 2892 if (perm & (1 << CCS_TYPE_RMDIR_ACL))
992 kumaneko 1064 count++;
993 kumaneko 2892 if (perm & (1 << CCS_TYPE_MKFIFO_ACL))
994 kumaneko 1064 count++;
995 kumaneko 2892 if (perm & (1 << CCS_TYPE_MKSOCK_ACL))
996 kumaneko 1064 count++;
997 kumaneko 2892 if (perm & (1 << CCS_TYPE_MKBLOCK_ACL))
998 kumaneko 1064 count++;
999 kumaneko 2892 if (perm & (1 << CCS_TYPE_MKCHAR_ACL))
1000 kumaneko 1064 count++;
1001 kumaneko 2892 if (perm & (1 << CCS_TYPE_TRUNCATE_ACL))
1002 kumaneko 1064 count++;
1003 kumaneko 2892 if (perm & (1 << CCS_TYPE_SYMLINK_ACL))
1004 kumaneko 1064 count++;
1005 kumaneko 2892 if (perm & (1 << CCS_TYPE_REWRITE_ACL))
1006 kumaneko 1064 count++;
1007     break;
1008 kumaneko 2892 case CCS_TYPE_DOUBLE_PATH_ACL:
1009 kumaneko 2002 acl2 = container_of(ptr,
1010     struct ccs_double_path_acl_record,
1011 kumaneko 1064 head);
1012     perm = acl2->perm;
1013 kumaneko 2892 if (perm & (1 << CCS_TYPE_LINK_ACL))
1014 kumaneko 1064 count++;
1015 kumaneko 2892 if (perm & (1 << CCS_TYPE_RENAME_ACL))
1016 kumaneko 1064 count++;
1017     break;
1018 kumaneko 2892 case CCS_TYPE_EXECUTE_HANDLER:
1019     case CCS_TYPE_DENIED_EXECUTE_HANDLER:
1020 kumaneko 1064 break;
1021     default:
1022 kumaneko 1052 count++;
1023 kumaneko 1064 }
1024 kumaneko 512 }
1025 kumaneko 2282 if (count < ccs_check_flags(domain, CCS_MAX_ACCEPT_ENTRY))
1026 kumaneko 2692 return true;
1027     if (!domain->quota_warned) {
1028 kumaneko 1006 domain->quota_warned = true;
1029 kumaneko 1052 printk(KERN_WARNING "TOMOYO-WARNING: "
1030     "Domain '%s' has so many ACLs to hold. "
1031     "Stopped learning mode.\n", domain->domainname->name);
1032 kumaneko 512 }
1033 kumaneko 2692 return false;
1034 kumaneko 512 }

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