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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2863 - (hide annotations) (download) (as text)
Fri Aug 7 06:27:45 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: 24060 byte(s)


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

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