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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2708 - (hide annotations) (download) (as text)
Tue Jun 30 06:38:14 2009 UTC (14 years, 10 months ago) by kumaneko
Original Path: branches/ccs-patch/fs/ccs_common.c
File MIME type: text/x-csrc
File size: 86232 byte(s)


1 kumaneko 111 /*
2     * fs/ccs_common.c
3     *
4     * Common functions for SAKURA and TOMOYO.
5     *
6 kumaneko 2030 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 kumaneko 111 *
8 kumaneko 2704 * Version: 1.7.0-pre 2009/05/28
9 kumaneko 111 *
10     * This file is applicable to both 2.4.30 and 2.6.11 and later.
11     * See README.ccs for ChangeLog.
12     *
13     */
14    
15 kumaneko 1255 #include <linux/version.h>
16     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
17     #define __KERNEL_SYSCALLS__
18     #endif
19 kumaneko 111 #include <linux/string.h>
20     #include <linux/mm.h>
21     #include <linux/utime.h>
22     #include <linux/file.h>
23     #include <linux/module.h>
24     #include <linux/slab.h>
25     #include <asm/uaccess.h>
26     #include <stdarg.h>
27 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
28 kumaneko 111 #include <linux/namei.h>
29     #include <linux/mount.h>
30 kumaneko 2002 static const int ccs_lookup_flags = LOOKUP_FOLLOW;
31 kumaneko 111 #else
32 kumaneko 2002 static const int ccs_lookup_flags = LOOKUP_FOLLOW | LOOKUP_POSITIVE;
33 kumaneko 111 #endif
34 kumaneko 2540 #include <linux/ccs_common.h>
35 kumaneko 111 #include <linux/realpath.h>
36     #include <linux/ccs_proc.h>
37     #include <linux/tomoyo.h>
38 kumaneko 1255 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
39     #include <linux/unistd.h>
40     #endif
41 kumaneko 1052
42     /* To support PID namespace. */
43     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
44 kumaneko 964 #define find_task_by_pid find_task_by_vpid
45     #endif
46 kumaneko 111
47 kumaneko 1052 /* Set default specified by the kernel config. */
48 kumaneko 2703 #define MAX_ACCEPT_ENTRY (CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY)
49     #define MAX_GRANT_LOG (CONFIG_CCSECURITY_MAX_GRANT_LOG)
50     #define MAX_REJECT_LOG (CONFIG_CCSECURITY_MAX_REJECT_LOG)
51 kumaneko 111
52 kumaneko 2690 DEFINE_MUTEX(ccs_policy_lock);
53 kumaneko 2540
54 kumaneko 1052 /* Has /sbin/init started? */
55 kumaneko 2040 bool ccs_policy_loaded;
56 kumaneko 111
57 kumaneko 1052 /* Log level for SAKURA's printk(). */
58 kumaneko 111 const char *ccs_log_level = KERN_DEBUG;
59    
60 kumaneko 1052 /* String table for functionality that takes 4 modes. */
61 kumaneko 2002 static const char *ccs_mode_4[4] = {
62 kumaneko 1052 "disabled", "learning", "permissive", "enforcing"
63     };
64     /* String table for functionality that takes 2 modes. */
65 kumaneko 2002 static const char *ccs_mode_2[4] = {
66 kumaneko 1052 "disabled", "enabled", "enabled", "enabled"
67     };
68 kumaneko 1014
69 kumaneko 1052 /* Table for profile. */
70 kumaneko 111 static struct {
71     const char *keyword;
72     unsigned int current_value;
73     const unsigned int max_value;
74     } ccs_control_array[CCS_MAX_CONTROL_INDEX] = {
75 kumaneko 2282 [CCS_MAC_FOR_FILE] = { "MAC_FOR_FILE", 0, 3 },
76     [CCS_MAC_FOR_IOCTL] = { "MAC_FOR_IOCTL", 0, 3 },
77     [CCS_MAC_FOR_ARGV0] = { "MAC_FOR_ARGV0", 0, 3 },
78     [CCS_MAC_FOR_ENV] = { "MAC_FOR_ENV", 0, 3 },
79     [CCS_MAC_FOR_NETWORK] = { "MAC_FOR_NETWORK", 0, 3 },
80     [CCS_MAC_FOR_SIGNAL] = { "MAC_FOR_SIGNAL", 0, 3 },
81 kumaneko 2708 [CCS_MAC_FOR_NAMESPACE] = { "MAC_FOR_NAMESPACE", 0, 3 },
82 kumaneko 2282 [CCS_RESTRICT_AUTOBIND] = { "RESTRICT_AUTOBIND", 0, 1 },
83     [CCS_MAX_ACCEPT_ENTRY]
84 kumaneko 1052 = { "MAX_ACCEPT_ENTRY", MAX_ACCEPT_ENTRY, INT_MAX },
85 kumaneko 2703 #ifdef CONFIG_CCSECURITY_AUDIT
86 kumaneko 2282 [CCS_MAX_GRANT_LOG]
87 kumaneko 1052 = { "MAX_GRANT_LOG", MAX_GRANT_LOG, INT_MAX },
88 kumaneko 2282 [CCS_MAX_REJECT_LOG]
89 kumaneko 1052 = { "MAX_REJECT_LOG", MAX_REJECT_LOG, INT_MAX },
90 kumaneko 2213 #endif
91 kumaneko 2282 [CCS_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 },
92 kumaneko 1052 [CCS_SLEEP_PERIOD]
93     = { "SLEEP_PERIOD", 0, 3000 }, /* in 0.1 second */
94 kumaneko 111 };
95    
96 kumaneko 1052 /* Capability name used by domain policy. */
97 kumaneko 2282 static const char *ccs_capability_control_keyword[CCS_MAX_CAPABILITY_INDEX]
98 kumaneko 2002 = {
99 kumaneko 2282 [CCS_INET_STREAM_SOCKET_CREATE] = "inet_tcp_create",
100     [CCS_INET_STREAM_SOCKET_LISTEN] = "inet_tcp_listen",
101     [CCS_INET_STREAM_SOCKET_CONNECT] = "inet_tcp_connect",
102     [CCS_USE_INET_DGRAM_SOCKET] = "use_inet_udp",
103     [CCS_USE_INET_RAW_SOCKET] = "use_inet_ip",
104     [CCS_USE_ROUTE_SOCKET] = "use_route",
105     [CCS_USE_PACKET_SOCKET] = "use_packet",
106     [CCS_SYS_MOUNT] = "SYS_MOUNT",
107     [CCS_SYS_UMOUNT] = "SYS_UMOUNT",
108     [CCS_SYS_REBOOT] = "SYS_REBOOT",
109     [CCS_SYS_CHROOT] = "SYS_CHROOT",
110     [CCS_SYS_KILL] = "SYS_KILL",
111     [CCS_SYS_VHANGUP] = "SYS_VHANGUP",
112     [CCS_SYS_SETTIME] = "SYS_TIME",
113     [CCS_SYS_NICE] = "SYS_NICE",
114     [CCS_SYS_SETHOSTNAME] = "SYS_SETHOSTNAME",
115     [CCS_USE_KERNEL_MODULE] = "use_kernel_module",
116     [CCS_CREATE_FIFO] = "create_fifo",
117     [CCS_CREATE_BLOCK_DEV] = "create_block_dev",
118     [CCS_CREATE_CHAR_DEV] = "create_char_dev",
119     [CCS_CREATE_UNIX_SOCKET] = "create_unix_socket",
120     [CCS_SYS_LINK] = "SYS_LINK",
121     [CCS_SYS_SYMLINK] = "SYS_SYMLINK",
122     [CCS_SYS_RENAME] = "SYS_RENAME",
123     [CCS_SYS_UNLINK] = "SYS_UNLINK",
124     [CCS_SYS_CHMOD] = "SYS_CHMOD",
125     [CCS_SYS_CHOWN] = "SYS_CHOWN",
126     [CCS_SYS_IOCTL] = "SYS_IOCTL",
127     [CCS_SYS_KEXEC_LOAD] = "SYS_KEXEC_LOAD",
128     [CCS_SYS_PIVOT_ROOT] = "SYS_PIVOT_ROOT",
129     [CCS_SYS_PTRACE] = "SYS_PTRACE",
130 kumaneko 2708 [CCS_CONCEAL_MOUNT] = "conceal_mount",
131 kumaneko 1015 };
132    
133 kumaneko 2254 static bool ccs_profile_entry_used[CCS_MAX_CONTROL_INDEX +
134 kumaneko 2282 CCS_MAX_CAPABILITY_INDEX + 1];
135 kumaneko 2254
136 kumaneko 1052 /* Profile table. Memory is allocated as needed. */
137 kumaneko 2002 static struct ccs_profile {
138 kumaneko 111 unsigned int value[CCS_MAX_CONTROL_INDEX];
139 kumaneko 2002 const struct ccs_path_info *comment;
140 kumaneko 2282 unsigned char capability_value[CCS_MAX_CAPABILITY_INDEX];
141 kumaneko 2002 } *ccs_profile_ptr[MAX_PROFILES];
142 kumaneko 111
143 kumaneko 1052 /* Permit policy management by non-root user? */
144 kumaneko 2002 static bool ccs_manage_by_non_root;
145 kumaneko 111
146 kumaneko 1052 /* Utility functions. */
147 kumaneko 111
148 kumaneko 1052 /**
149 kumaneko 2282 * ccs_quiet_setup - Set CCS_VERBOSE=0 by default.
150 kumaneko 1052 *
151     * @str: Unused.
152     *
153     * Returns 0.
154     */
155 kumaneko 2002 static int __init ccs_quiet_setup(char *str)
156 kumaneko 111 {
157 kumaneko 2282 ccs_control_array[CCS_VERBOSE].current_value = 0;
158 kumaneko 111 return 0;
159     }
160    
161 kumaneko 2282 __setup("CCS_QUIET", ccs_quiet_setup);
162 kumaneko 111
163 kumaneko 1052 /**
164 kumaneko 2002 * ccs_is_byte_range - Check whether the string isa \ooo style octal value.
165 kumaneko 1052 *
166     * @str: Pointer to the string.
167     *
168     * Returns true if @str is a \ooo style octal value, false otherwise.
169     */
170 kumaneko 2002 static inline bool ccs_is_byte_range(const char *str)
171 kumaneko 1052 {
172     return *str >= '0' && *str++ <= '3' &&
173     *str >= '0' && *str++ <= '7' &&
174     *str >= '0' && *str <= '7';
175     }
176    
177     /**
178 kumaneko 2002 * ccs_is_decimal - Check whether the character is a decimal character.
179 kumaneko 1052 *
180     * @c: The character to check.
181     *
182     * Returns true if @c is a decimal character, false otherwise.
183     */
184 kumaneko 2002 static inline bool ccs_is_decimal(const char c)
185 kumaneko 1052 {
186 kumaneko 1468 return c >= '0' && c <= '9';
187 kumaneko 1052 }
188    
189     /**
190 kumaneko 2002 * ccs_is_hexadecimal - Check whether the character is a hexadecimal character.
191 kumaneko 1052 *
192     * @c: The character to check.
193     *
194     * Returns true if @c is a hexadecimal character, false otherwise.
195     */
196 kumaneko 2002 static inline bool ccs_is_hexadecimal(const char c)
197 kumaneko 1052 {
198 kumaneko 1468 return (c >= '0' && c <= '9') ||
199 kumaneko 1052 (c >= 'A' && c <= 'F') ||
200 kumaneko 1468 (c >= 'a' && c <= 'f');
201 kumaneko 1052 }
202    
203     /**
204 kumaneko 2002 * ccs_is_alphabet_char - Check whether the character is an alphabet.
205 kumaneko 1052 *
206     * @c: The character to check.
207     *
208     * Returns true if @c is an alphabet character, false otherwise.
209     */
210 kumaneko 2002 static inline bool ccs_is_alphabet_char(const char c)
211 kumaneko 1052 {
212 kumaneko 1794 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
213 kumaneko 1052 }
214    
215     /**
216 kumaneko 2002 * ccs_make_byte - Make byte value from three octal characters.
217 kumaneko 1064 *
218     * @c1: The first character.
219     * @c2: The second character.
220     * @c3: The third character.
221     *
222     * Returns byte value.
223     */
224 kumaneko 2002 static inline u8 ccs_make_byte(const u8 c1, const u8 c2, const u8 c3)
225 kumaneko 1064 {
226     return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
227     }
228    
229     /**
230 kumaneko 2002 * ccs_str_starts - Check whether the given string starts with the given keyword.
231 kumaneko 1052 *
232     * @src: Pointer to pointer to the string.
233     * @find: Pointer to the keyword.
234     *
235     * Returns true if @src starts with @find, false otherwise.
236     *
237     * The @src is updated to point the first character after the @find
238 kumaneko 1064 * if @src starts with @find.
239 kumaneko 1052 */
240 kumaneko 2002 static bool ccs_str_starts(char **src, const char *find)
241 kumaneko 1052 {
242     const int len = strlen(find);
243     char *tmp = *src;
244     if (strncmp(tmp, find, len))
245     return false;
246     tmp += len;
247     *src = tmp;
248     return true;
249     }
250    
251     /**
252 kumaneko 2002 * ccs_normalize_line - Format string.
253 kumaneko 1052 *
254     * @buffer: The line to normalize.
255     *
256 kumaneko 111 * Leading and trailing whitespaces are removed.
257     * Multiple whitespaces are packed into single space.
258 kumaneko 1052 *
259     * Returns nothing.
260 kumaneko 111 */
261 kumaneko 2308 void ccs_normalize_line(unsigned char *buffer)
262 kumaneko 111 {
263 kumaneko 1064 unsigned char *sp = buffer;
264     unsigned char *dp = buffer;
265 kumaneko 1006 bool first = true;
266 kumaneko 1052 while (*sp && (*sp <= ' ' || *sp >= 127))
267     sp++;
268 kumaneko 111 while (*sp) {
269 kumaneko 1052 if (!first)
270     *dp++ = ' ';
271 kumaneko 1006 first = false;
272 kumaneko 1052 while (*sp > ' ' && *sp < 127)
273     *dp++ = *sp++;
274     while (*sp && (*sp <= ' ' || *sp >= 127))
275     sp++;
276 kumaneko 111 }
277     *dp = '\0';
278     }
279    
280 kumaneko 1052 /**
281 kumaneko 1054 * ccs_is_correct_path - Validate a pathname.
282     * @filename: The pathname to check.
283     * @start_type: Should the pathname start with '/'?
284     * 1 = must / -1 = must not / 0 = don't care
285     * @pattern_type: Can the pathname contain a wildcard?
286     * 1 = must / -1 = must not / 0 = don't care
287     * @end_type: Should the pathname end with '/'?
288     * 1 = must / -1 = must not / 0 = don't care
289 kumaneko 1052 *
290 kumaneko 1054 * Check whether the given filename follows the naming rules.
291 kumaneko 1052 * Returns true if @filename follows the naming rules, false otherwise.
292 kumaneko 111 */
293 kumaneko 1052 bool ccs_is_correct_path(const char *filename, const s8 start_type,
294 kumaneko 2577 const s8 pattern_type, const s8 end_type)
295 kumaneko 111 {
296 kumaneko 1006 bool contains_pattern = false;
297 kumaneko 1064 unsigned char c;
298     unsigned char d;
299     unsigned char e;
300 kumaneko 111 const char *original_filename = filename;
301 kumaneko 1052 if (!filename)
302     goto out;
303 kumaneko 111 c = *filename;
304     if (start_type == 1) { /* Must start with '/' */
305 kumaneko 1052 if (c != '/')
306     goto out;
307 kumaneko 111 } else if (start_type == -1) { /* Must not start with '/' */
308 kumaneko 1052 if (c == '/')
309     goto out;
310 kumaneko 111 }
311 kumaneko 1052 if (c)
312 kumaneko 1795 c = *(filename + strlen(filename) - 1);
313 kumaneko 111 if (end_type == 1) { /* Must end with '/' */
314 kumaneko 1052 if (c != '/')
315     goto out;
316 kumaneko 111 } else if (end_type == -1) { /* Must not end with '/' */
317 kumaneko 1052 if (c == '/')
318     goto out;
319 kumaneko 111 }
320 kumaneko 1747 while (1) {
321     c = *filename++;
322     if (!c)
323     break;
324 kumaneko 111 if (c == '\\') {
325 kumaneko 1747 c = *filename++;
326     switch (c) {
327 kumaneko 111 case '\\': /* "\\" */
328     continue;
329     case '$': /* "\$" */
330     case '+': /* "\+" */
331     case '?': /* "\?" */
332     case '*': /* "\*" */
333     case '@': /* "\@" */
334     case 'x': /* "\x" */
335     case 'X': /* "\X" */
336     case 'a': /* "\a" */
337     case 'A': /* "\A" */
338 kumaneko 206 case '-': /* "\-" */
339 kumaneko 1052 if (pattern_type == -1)
340     break; /* Must not contain pattern */
341 kumaneko 1006 contains_pattern = true;
342 kumaneko 111 continue;
343     case '0': /* "\ooo" */
344     case '1':
345     case '2':
346     case '3':
347 kumaneko 1052 d = *filename++;
348     if (d < '0' || d > '7')
349     break;
350     e = *filename++;
351     if (e < '0' || e > '7')
352     break;
353 kumaneko 2002 c = ccs_make_byte(c, d, e);
354 kumaneko 1052 if (c && (c <= ' ' || c >= 127))
355     continue; /* pattern is not \000 */
356 kumaneko 111 }
357     goto out;
358     } else if (c <= ' ' || c >= 127) {
359     goto out;
360     }
361     }
362     if (pattern_type == 1) { /* Must contain pattern */
363 kumaneko 1052 if (!contains_pattern)
364     goto out;
365 kumaneko 111 }
366 kumaneko 1006 return true;
367 kumaneko 111 out:
368 kumaneko 2577 printk(KERN_DEBUG "Invalid pathname '%s'\n", original_filename);
369 kumaneko 1006 return false;
370 kumaneko 111 }
371    
372 kumaneko 1052 /**
373 kumaneko 1054 * ccs_is_correct_domain - Check whether the given domainname follows the naming rules.
374     * @domainname: The domainname to check.
375 kumaneko 1052 *
376     * Returns true if @domainname follows the naming rules, false otherwise.
377 kumaneko 111 */
378 kumaneko 2577 bool ccs_is_correct_domain(const unsigned char *domainname)
379 kumaneko 111 {
380 kumaneko 1064 unsigned char c;
381     unsigned char d;
382     unsigned char e;
383 kumaneko 111 const char *org_domainname = domainname;
384 kumaneko 1052 if (!domainname || strncmp(domainname, ROOT_NAME, ROOT_NAME_LEN))
385     goto out;
386 kumaneko 111 domainname += ROOT_NAME_LEN;
387 kumaneko 1052 if (!*domainname)
388     return true;
389 kumaneko 111 do {
390 kumaneko 1052 if (*domainname++ != ' ')
391     goto out;
392     if (*domainname++ != '/')
393     goto out;
394 kumaneko 1747 while (1) {
395     c = *domainname;
396     if (!c || c == ' ')
397     break;
398 kumaneko 111 domainname++;
399     if (c == '\\') {
400 kumaneko 1052 c = *domainname++;
401     switch ((c)) {
402 kumaneko 111 case '\\': /* "\\" */
403     continue;
404     case '0': /* "\ooo" */
405     case '1':
406     case '2':
407     case '3':
408 kumaneko 1052 d = *domainname++;
409     if (d < '0' || d > '7')
410     break;
411     e = *domainname++;
412     if (e < '0' || e > '7')
413     break;
414 kumaneko 2002 c = ccs_make_byte(c, d, e);
415 kumaneko 1052 if (c && (c <= ' ' || c >= 127))
416     /* pattern is not \000 */
417     continue;
418 kumaneko 111 }
419     goto out;
420     } else if (c < ' ' || c >= 127) {
421     goto out;
422     }
423     }
424     } while (*domainname);
425 kumaneko 1006 return true;
426 kumaneko 111 out:
427 kumaneko 2577 printk(KERN_DEBUG "Invalid domainname '%s'\n", org_domainname);
428 kumaneko 1006 return false;
429 kumaneko 111 }
430    
431 kumaneko 1052 /**
432     * ccs_is_domain_def - Check whether the given token can be a domainname.
433     *
434     * @buffer: The token to check.
435     *
436     * Returns true if @buffer possibly be a domainname, false otherwise.
437     */
438     bool ccs_is_domain_def(const unsigned char *buffer)
439 kumaneko 461 {
440 kumaneko 1052 return !strncmp(buffer, ROOT_NAME, ROOT_NAME_LEN);
441 kumaneko 461 }
442    
443 kumaneko 1052 /**
444     * ccs_find_domain - Find a domain by the given name.
445     *
446 kumaneko 1054 * @domainname: The domainname to find.
447 kumaneko 1052 *
448 kumaneko 2690 * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise.
449     *
450     * Caller holds srcu_read_lock(&ccs_ss).
451 kumaneko 1052 */
452 kumaneko 2690 struct ccs_domain_info *ccs_find_domain(const char *domainname)
453 kumaneko 461 {
454 kumaneko 2282 struct ccs_domain_info *domain;
455 kumaneko 2002 struct ccs_path_info name;
456 kumaneko 1052 name.name = domainname;
457     ccs_fill_path_info(&name);
458 kumaneko 2690 list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
459 kumaneko 2692 if (!domain->is_deleted &&
460     !ccs_pathcmp(&name, domain->domainname))
461     return domain;
462 kumaneko 461 }
463 kumaneko 2692 return NULL;
464 kumaneko 461 }
465    
466 kumaneko 1052 /**
467 kumaneko 2002 * ccs_path_depth - Evaluate the number of '/' in a string.
468 kumaneko 1052 *
469     * @pathname: The string to evaluate.
470     *
471     * Returns path depth of the string.
472     *
473     * I score 2 for each of the '/' in the @pathname
474     * and score 1 if the @pathname ends with '/'.
475     */
476 kumaneko 2002 static int ccs_path_depth(const char *pathname)
477 kumaneko 111 {
478     int i = 0;
479     if (pathname) {
480 kumaneko 1795 const char *ep = pathname + strlen(pathname);
481 kumaneko 111 if (pathname < ep--) {
482 kumaneko 1052 if (*ep != '/')
483     i++;
484     while (pathname <= ep)
485     if (*ep-- == '/')
486     i += 2;
487 kumaneko 111 }
488     }
489     return i;
490     }
491    
492 kumaneko 1052 /**
493 kumaneko 2002 * ccs_const_part_length - Evaluate the initial length without a pattern in a token.
494 kumaneko 1052 *
495     * @filename: The string to evaluate.
496     *
497 kumaneko 1064 * Returns the initial length without a pattern in @filename.
498 kumaneko 1052 */
499 kumaneko 2002 static int ccs_const_part_length(const char *filename)
500 kumaneko 111 {
501 kumaneko 1052 char c;
502 kumaneko 111 int len = 0;
503 kumaneko 1052 if (!filename)
504     return 0;
505 kumaneko 1747 while (1) {
506     c = *filename++;
507     if (!c)
508     break;
509 kumaneko 1052 if (c != '\\') {
510     len++;
511     continue;
512 kumaneko 111 }
513 kumaneko 1052 c = *filename++;
514     switch (c) {
515     case '\\': /* "\\" */
516     len += 2;
517     continue;
518     case '0': /* "\ooo" */
519     case '1':
520     case '2':
521     case '3':
522     c = *filename++;
523     if (c < '0' || c > '7')
524     break;
525     c = *filename++;
526     if (c < '0' || c > '7')
527     break;
528     len += 4;
529     continue;
530     }
531     break;
532 kumaneko 111 }
533     return len;
534     }
535    
536 kumaneko 1052 /**
537 kumaneko 2002 * ccs_fill_path_info - Fill in "struct ccs_path_info" members.
538 kumaneko 1052 *
539 kumaneko 2002 * @ptr: Pointer to "struct ccs_path_info" to fill in.
540 kumaneko 1052 *
541 kumaneko 2002 * The caller sets "struct ccs_path_info"->name.
542 kumaneko 1052 */
543 kumaneko 2002 void ccs_fill_path_info(struct ccs_path_info *ptr)
544 kumaneko 111 {
545     const char *name = ptr->name;
546     const int len = strlen(name);
547     ptr->total_len = len;
548 kumaneko 2002 ptr->const_len = ccs_const_part_length(name);
549 kumaneko 111 ptr->is_dir = len && (name[len - 1] == '/');
550     ptr->is_patterned = (ptr->const_len < len);
551     ptr->hash = full_name_hash(name, len);
552 kumaneko 2002 ptr->depth = ccs_path_depth(name);
553 kumaneko 111 }
554    
555 kumaneko 1052 /**
556 kumaneko 2039 * ccs_file_matches_pattern2 - Pattern matching without '/' character
557 kumaneko 1052 * and "\-" pattern.
558     *
559     * @filename: The start of string to check.
560     * @filename_end: The end of string to check.
561     * @pattern: The start of pattern to compare.
562     * @pattern_end: The end of pattern to compare.
563     *
564     * Returns true if @filename matches @pattern, false otherwise.
565     */
566 kumaneko 2039 static bool ccs_file_matches_pattern2(const char *filename,
567     const char *filename_end,
568     const char *pattern,
569     const char *pattern_end)
570 kumaneko 111 {
571     while (filename < filename_end && pattern < pattern_end) {
572 kumaneko 1052 char c;
573 kumaneko 111 if (*pattern != '\\') {
574 kumaneko 1052 if (*filename++ != *pattern++)
575     return false;
576     continue;
577     }
578     c = *filename;
579     pattern++;
580     switch (*pattern) {
581 kumaneko 1064 int i;
582     int j;
583 kumaneko 1052 case '?':
584     if (c == '/') {
585     return false;
586     } else if (c == '\\') {
587     if (filename[1] == '\\')
588     filename++;
589 kumaneko 2002 else if (ccs_is_byte_range(filename + 1))
590 kumaneko 1052 filename += 3;
591     else
592 kumaneko 1006 return false;
593 kumaneko 1052 }
594     break;
595     case '\\':
596     if (c != '\\')
597     return false;
598     if (*++filename != '\\')
599     return false;
600     break;
601     case '+':
602 kumaneko 2002 if (!ccs_is_decimal(c))
603 kumaneko 1052 return false;
604     break;
605     case 'x':
606 kumaneko 2002 if (!ccs_is_hexadecimal(c))
607 kumaneko 1052 return false;
608     break;
609     case 'a':
610 kumaneko 2002 if (!ccs_is_alphabet_char(c))
611 kumaneko 1052 return false;
612     break;
613     case '0':
614     case '1':
615     case '2':
616     case '3':
617 kumaneko 2002 if (c == '\\' && ccs_is_byte_range(filename + 1)
618 kumaneko 1052 && strncmp(filename + 1, pattern, 3) == 0) {
619     filename += 3;
620     pattern += 2;
621 kumaneko 111 break;
622 kumaneko 1052 }
623     return false; /* Not matched. */
624     case '*':
625     case '@':
626     for (i = 0; i <= filename_end - filename; i++) {
627 kumaneko 2039 if (ccs_file_matches_pattern2(filename + i,
628     filename_end,
629     pattern + 1,
630     pattern_end))
631 kumaneko 1052 return true;
632     c = filename[i];
633     if (c == '.' && *pattern == '@')
634 kumaneko 111 break;
635 kumaneko 1052 if (c != '\\')
636     continue;
637     if (filename[i + 1] == '\\')
638     i++;
639 kumaneko 2002 else if (ccs_is_byte_range(filename + i + 1))
640 kumaneko 1052 i += 3;
641     else
642     break; /* Bad pattern. */
643 kumaneko 111 }
644 kumaneko 1052 return false; /* Not matched. */
645     default:
646     j = 0;
647     c = *pattern;
648     if (c == '$') {
649 kumaneko 2002 while (ccs_is_decimal(filename[j]))
650 kumaneko 1052 j++;
651     } else if (c == 'X') {
652 kumaneko 2002 while (ccs_is_hexadecimal(filename[j]))
653 kumaneko 1052 j++;
654     } else if (c == 'A') {
655 kumaneko 2002 while (ccs_is_alphabet_char(filename[j]))
656 kumaneko 1052 j++;
657     }
658     for (i = 1; i <= j; i++) {
659 kumaneko 2039 if (ccs_file_matches_pattern2(filename + i,
660     filename_end,
661     pattern + 1,
662     pattern_end))
663 kumaneko 1052 return true;
664     }
665     return false; /* Not matched or bad pattern. */
666 kumaneko 111 }
667 kumaneko 1052 filename++;
668     pattern++;
669 kumaneko 111 }
670 kumaneko 1052 while (*pattern == '\\' &&
671     (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
672     pattern += 2;
673 kumaneko 1468 return filename == filename_end && pattern == pattern_end;
674 kumaneko 111 }
675    
676 kumaneko 1052 /**
677 kumaneko 2039 * ccs_file_matches_pattern - Pattern matching without without '/' character.
678 kumaneko 1052 *
679     * @filename: The start of string to check.
680     * @filename_end: The end of string to check.
681     * @pattern: The start of pattern to compare.
682     * @pattern_end: The end of pattern to compare.
683     *
684     * Returns true if @filename matches @pattern, false otherwise.
685     */
686 kumaneko 2039 static bool ccs_file_matches_pattern(const char *filename,
687     const char *filename_end,
688     const char *pattern,
689     const char *pattern_end)
690 kumaneko 206 {
691     const char *pattern_start = pattern;
692 kumaneko 1006 bool first = true;
693     bool result;
694 kumaneko 206 while (pattern < pattern_end - 1) {
695 kumaneko 1052 /* Split at "\-" pattern. */
696     if (*pattern++ != '\\' || *pattern++ != '-')
697     continue;
698 kumaneko 2039 result = ccs_file_matches_pattern2(filename, filename_end,
699 kumaneko 2040 pattern_start, pattern - 2);
700 kumaneko 1052 if (first)
701     result = !result;
702     if (result)
703     return false;
704 kumaneko 1006 first = false;
705 kumaneko 206 pattern_start = pattern;
706     }
707 kumaneko 2039 result = ccs_file_matches_pattern2(filename, filename_end,
708     pattern_start, pattern_end);
709 kumaneko 206 return first ? result : !result;
710     }
711    
712 kumaneko 1052 /**
713 kumaneko 1054 * ccs_path_matches_pattern - Check whether the given filename matches the given pattern.
714 kumaneko 1052 * @filename: The filename to check.
715     * @pattern: The pattern to compare.
716 kumaneko 111 *
717 kumaneko 1052 * Returns true if matches, false otherwise.
718     *
719     * The following patterns are available.
720     * \\ \ itself.
721     * \ooo Octal representation of a byte.
722     * \* More than or equals to 0 character other than '/'.
723     * \@ More than or equals to 0 character other than '/' or '.'.
724     * \? 1 byte character other than '/'.
725     * \$ More than or equals to 1 decimal digit.
726     * \+ 1 decimal digit.
727     * \X More than or equals to 1 hexadecimal digit.
728     * \x 1 hexadecimal digit.
729     * \A More than or equals to 1 alphabet character.
730     * \a 1 alphabet character.
731     * \- Subtraction operator.
732 kumaneko 111 */
733 kumaneko 2002 bool ccs_path_matches_pattern(const struct ccs_path_info *filename,
734     const struct ccs_path_info *pattern)
735 kumaneko 111 {
736 kumaneko 1052 /*
737     if (!filename || !pattern)
738     return false;
739     */
740     const char *f = filename->name;
741     const char *p = pattern->name;
742     const int len = pattern->const_len;
743     /* If @pattern doesn't contain pattern, I can use strcmp(). */
744     if (!pattern->is_patterned)
745     return !ccs_pathcmp(filename, pattern);
746     /* Dont compare if the number of '/' differs. */
747     if (filename->depth != pattern->depth)
748     return false;
749     /* Compare the initial length without patterns. */
750     if (strncmp(f, p, len))
751     return false;
752     f += len;
753     p += len;
754     /* Main loop. Compare each directory component. */
755     while (*f && *p) {
756     const char *f_delimiter = strchr(f, '/');
757     const char *p_delimiter = strchr(p, '/');
758     if (!f_delimiter)
759 kumaneko 1795 f_delimiter = f + strlen(f);
760 kumaneko 1052 if (!p_delimiter)
761 kumaneko 1795 p_delimiter = p + strlen(p);
762 kumaneko 2040 if (!ccs_file_matches_pattern(f, f_delimiter, p, p_delimiter))
763 kumaneko 1052 return false;
764     f = f_delimiter;
765     if (*f)
766     f++;
767     p = p_delimiter;
768     if (*p)
769     p++;
770 kumaneko 111 }
771 kumaneko 1052 /* Ignore trailing "\*" and "\@" in @pattern. */
772     while (*p == '\\' &&
773     (*(p + 1) == '*' || *(p + 1) == '@'))
774     p += 2;
775 kumaneko 1468 return !*f && !*p;
776 kumaneko 111 }
777    
778 kumaneko 1052 /**
779     * ccs_io_printf - Transactional printf() to "struct ccs_io_buffer" structure.
780     *
781     * @head: Pointer to "struct ccs_io_buffer".
782     * @fmt: The printf()'s format string, followed by parameters.
783     *
784     * Returns true on success, false otherwise.
785     *
786     * The snprintf() will truncate, but ccs_io_printf() won't.
787 kumaneko 111 */
788 kumaneko 1052 bool ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
789 kumaneko 111 {
790     va_list args;
791 kumaneko 1064 int len;
792     int pos = head->read_avail;
793     int size = head->readbuf_size - pos;
794 kumaneko 1052 if (size <= 0)
795     return false;
796 kumaneko 111 va_start(args, fmt);
797     len = vsnprintf(head->read_buf + pos, size, fmt, args);
798     va_end(args);
799 kumaneko 1052 if (pos + len >= head->readbuf_size)
800     return false;
801 kumaneko 111 head->read_avail += len;
802 kumaneko 1052 return true;
803 kumaneko 111 }
804    
805 kumaneko 1052 /**
806     * ccs_get_exe - Get ccs_realpath() of current process.
807     *
808     * Returns the ccs_realpath() of current process on success, NULL otherwise.
809     *
810     * This function uses ccs_alloc(), so the caller must ccs_free()
811     * if this function didn't return NULL.
812 kumaneko 111 */
813 kumaneko 1052 const char *ccs_get_exe(void)
814 kumaneko 111 {
815 kumaneko 737 struct mm_struct *mm = current->mm;
816     struct vm_area_struct *vma;
817     const char *cp = NULL;
818 kumaneko 1052 if (!mm)
819     return NULL;
820 kumaneko 737 down_read(&mm->mmap_sem);
821     for (vma = mm->mmap; vma; vma = vma->vm_next) {
822     if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
823 kumaneko 1052 cp = ccs_realpath_from_dentry(vma->vm_file->f_dentry,
824     vma->vm_file->f_vfsmnt);
825 kumaneko 737 break;
826 kumaneko 111 }
827     }
828 kumaneko 737 up_read(&mm->mmap_sem);
829     return cp;
830 kumaneko 111 }
831    
832 kumaneko 1052 /**
833     * ccs_get_msg - Get warning message.
834     *
835     * @is_enforce: Is it enforcing mode?
836     *
837     * Returns "ERROR" or "WARNING".
838     */
839     const char *ccs_get_msg(const bool is_enforce)
840 kumaneko 111 {
841 kumaneko 1052 if (is_enforce)
842     return "ERROR";
843     else
844     return "WARNING";
845 kumaneko 111 }
846    
847 kumaneko 1052 /**
848 kumaneko 1657 * ccs_can_sleep - Check whether it is permitted to do operations that may sleep.
849 kumaneko 1052 *
850     * Returns true if it is permitted to do operations that may sleep,
851     * false otherwise.
852     *
853     * TOMOYO Linux supports interactive enforcement that lets processes
854     * wait for the administrator's decision.
855     * All hooks but the one for ccs_may_autobind() are inserted where
856     * it is permitted to do operations that may sleep.
857     * Thus, this warning should not happen.
858     */
859 kumaneko 1657 bool ccs_can_sleep(void)
860 kumaneko 899 {
861 kumaneko 1052 static u8 count = 20;
862     if (likely(!in_interrupt()))
863     return true;
864     if (count) {
865     count--;
866     printk(KERN_ERR "BUG: sleeping function called "
867     "from invalid context.\n");
868     dump_stack();
869 kumaneko 899 }
870 kumaneko 1052 return false;
871 kumaneko 899 }
872    
873 kumaneko 1052 /**
874     * ccs_check_flags - Check mode for specified functionality.
875     *
876 kumaneko 2282 * @domain: Pointer to "struct ccs_domain_info". NULL for ccs_current_domain().
877 kumaneko 1657 * @index: The functionality to check mode.
878 kumaneko 1052 *
879     * Returns the mode of specified functionality.
880     */
881 kumaneko 2282 unsigned int ccs_check_flags(const struct ccs_domain_info *domain,
882     const u8 index)
883 kumaneko 1015 {
884 kumaneko 1657 u8 profile;
885     if (!domain)
886 kumaneko 2282 domain = ccs_current_domain();
887 kumaneko 1657 profile = domain->profile;
888 kumaneko 2040 return ccs_policy_loaded && index < CCS_MAX_CONTROL_INDEX
889 kumaneko 1657 #if MAX_PROFILES != 256
890     && profile < MAX_PROFILES
891     #endif
892 kumaneko 2002 && ccs_profile_ptr[profile] ?
893     ccs_profile_ptr[profile]->value[index] : 0;
894 kumaneko 1015 }
895    
896 kumaneko 1052 /**
897     * ccs_check_capability_flags - Check mode for specified capability.
898     *
899 kumaneko 2282 * @domain: Pointer to "struct ccs_domain_info". NULL for ccs_current_domain().
900 kumaneko 1657 * @index: The capability to check mode.
901 kumaneko 1052 *
902     * Returns the mode of specified capability.
903     */
904 kumaneko 2282 static u8 ccs_check_capability_flags(const struct ccs_domain_info *domain,
905 kumaneko 1657 const u8 index)
906 kumaneko 1015 {
907 kumaneko 1657 const u8 profile = domain ? domain->profile :
908 kumaneko 2282 ccs_current_domain()->profile;
909     return ccs_policy_loaded && index < CCS_MAX_CAPABILITY_INDEX
910 kumaneko 1015 #if MAX_PROFILES != 256
911     && profile < MAX_PROFILES
912     #endif
913 kumaneko 2002 && ccs_profile_ptr[profile] ?
914     ccs_profile_ptr[profile]->capability_value[index] : 0;
915 kumaneko 1015 }
916    
917 kumaneko 1052 /**
918     * ccs_cap2keyword - Convert capability operation to capability name.
919     *
920     * @operation: The capability index.
921     *
922     * Returns the name of the specified capability's name.
923     */
924     const char *ccs_cap2keyword(const u8 operation)
925 kumaneko 1015 {
926 kumaneko 2282 return operation < CCS_MAX_CAPABILITY_INDEX
927 kumaneko 2002 ? ccs_capability_control_keyword[operation] : NULL;
928 kumaneko 1015 }
929    
930 kumaneko 1052 /**
931 kumaneko 1657 * ccs_init_request_info - Initialize "struct ccs_request_info" members.
932     *
933     * @r: Pointer to "struct ccs_request_info" to initialize.
934 kumaneko 2282 * @domain: Pointer to "struct ccs_domain_info". NULL for ccs_current_domain().
935 kumaneko 1657 * @index: Index number of functionality.
936     */
937     void ccs_init_request_info(struct ccs_request_info *r,
938 kumaneko 2282 struct ccs_domain_info *domain, const u8 index)
939 kumaneko 1657 {
940     memset(r, 0, sizeof(*r));
941     if (!domain)
942 kumaneko 2282 domain = ccs_current_domain();
943 kumaneko 2690 r->domain = domain;
944 kumaneko 1657 r->profile = domain->profile;
945     if (index < CCS_MAX_CONTROL_INDEX)
946     r->mode = ccs_check_flags(domain, index);
947     else
948     r->mode = ccs_check_capability_flags(domain, index
949     - CCS_MAX_CONTROL_INDEX);
950     }
951    
952     /**
953 kumaneko 1052 * ccs_verbose_mode - Check whether TOMOYO is verbose mode.
954     *
955 kumaneko 2282 * @domain: Pointer to "struct ccs_domain_info". NULL for ccs_current_domain().
956 kumaneko 1657 *
957 kumaneko 1052 * Returns true if domain policy violation warning should be printed to
958     * console.
959     */
960 kumaneko 2282 bool ccs_verbose_mode(const struct ccs_domain_info *domain)
961 kumaneko 111 {
962 kumaneko 2282 return ccs_check_flags(domain, CCS_VERBOSE) != 0;
963 kumaneko 111 }
964    
965 kumaneko 1052 /**
966 kumaneko 2209 * ccs_domain_quota_ok - Check for domain's quota.
967 kumaneko 1052 *
968 kumaneko 2282 * @domain: Pointer to "struct ccs_domain_info".
969 kumaneko 1052 *
970     * Returns true if the domain is not exceeded quota, false otherwise.
971 kumaneko 2690 *
972     * Caller holds srcu_read_lock(&ccs_ss).
973 kumaneko 1052 */
974 kumaneko 2282 bool ccs_domain_quota_ok(struct ccs_domain_info * const domain)
975 kumaneko 512 {
976     unsigned int count = 0;
977 kumaneko 2002 struct ccs_acl_info *ptr;
978 kumaneko 1052 if (!domain)
979     return true;
980 kumaneko 2690 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
981 kumaneko 1064 if (ptr->type & ACL_DELETED)
982     continue;
983 kumaneko 2692 switch (ccs_acl_type2(ptr)) {
984 kumaneko 2002 struct ccs_single_path_acl_record *acl1;
985     struct ccs_double_path_acl_record *acl2;
986 kumaneko 1064 u16 perm;
987     case TYPE_SINGLE_PATH_ACL:
988 kumaneko 2002 acl1 = container_of(ptr,
989     struct ccs_single_path_acl_record,
990 kumaneko 1064 head);
991     perm = acl1->perm;
992     if (perm & (1 << TYPE_EXECUTE_ACL))
993     count++;
994     if (perm &
995     ((1 << TYPE_READ_ACL) | (1 << TYPE_WRITE_ACL)))
996     count++;
997     if (perm & (1 << TYPE_CREATE_ACL))
998     count++;
999     if (perm & (1 << TYPE_UNLINK_ACL))
1000     count++;
1001     if (perm & (1 << TYPE_MKDIR_ACL))
1002     count++;
1003     if (perm & (1 << TYPE_RMDIR_ACL))
1004     count++;
1005     if (perm & (1 << TYPE_MKFIFO_ACL))
1006     count++;
1007     if (perm & (1 << TYPE_MKSOCK_ACL))
1008     count++;
1009     if (perm & (1 << TYPE_MKBLOCK_ACL))
1010     count++;
1011     if (perm & (1 << TYPE_MKCHAR_ACL))
1012     count++;
1013     if (perm & (1 << TYPE_TRUNCATE_ACL))
1014     count++;
1015     if (perm & (1 << TYPE_SYMLINK_ACL))
1016     count++;
1017     if (perm & (1 << TYPE_REWRITE_ACL))
1018     count++;
1019     break;
1020     case TYPE_DOUBLE_PATH_ACL:
1021 kumaneko 2002 acl2 = container_of(ptr,
1022     struct ccs_double_path_acl_record,
1023 kumaneko 1064 head);
1024     perm = acl2->perm;
1025     if (perm & (1 << TYPE_LINK_ACL))
1026     count++;
1027     if (perm & (1 << TYPE_RENAME_ACL))
1028     count++;
1029     break;
1030     case TYPE_EXECUTE_HANDLER:
1031     case TYPE_DENIED_EXECUTE_HANDLER:
1032     break;
1033     default:
1034 kumaneko 1052 count++;
1035 kumaneko 1064 }
1036 kumaneko 512 }
1037 kumaneko 2282 if (count < ccs_check_flags(domain, CCS_MAX_ACCEPT_ENTRY))
1038 kumaneko 2692 return true;
1039     if (!domain->quota_warned) {
1040 kumaneko 1006 domain->quota_warned = true;
1041 kumaneko 1052 printk(KERN_WARNING "TOMOYO-WARNING: "
1042     "Domain '%s' has so many ACLs to hold. "
1043     "Stopped learning mode.\n", domain->domainname->name);
1044 kumaneko 512 }
1045 kumaneko 2692 return false;
1046 kumaneko 512 }
1047    
1048 kumaneko 1052 /**
1049     * ccs_find_or_assign_new_profile - Create a new profile.
1050     *
1051     * @profile: Profile number to create.
1052     *
1053 kumaneko 2002 * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
1054 kumaneko 1052 */
1055 kumaneko 2002 static struct ccs_profile *ccs_find_or_assign_new_profile(const unsigned int
1056     profile)
1057 kumaneko 111 {
1058 kumaneko 2540 struct ccs_profile *ptr;
1059     struct ccs_profile *entry;
1060     int i;
1061     if (profile >= MAX_PROFILES)
1062     return NULL;
1063 kumaneko 2692 ptr = ccs_profile_ptr[profile];
1064     if (ptr)
1065     return ptr;
1066 kumaneko 2540 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
1067 kumaneko 2690 mutex_lock(&ccs_policy_lock);
1068 kumaneko 2540 ptr = ccs_profile_ptr[profile];
1069     if (!ptr && ccs_memory_ok(entry)) {
1070     ptr = entry;
1071     for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++)
1072     ptr->value[i] = ccs_control_array[i].current_value;
1073     /*
1074     * Needn't to initialize "ptr->capability_value"
1075     * because they are always 0.
1076     */
1077     mb(); /* Avoid out-of-order execution. */
1078     ccs_profile_ptr[profile] = ptr;
1079     entry = NULL;
1080 kumaneko 111 }
1081 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
1082 kumaneko 2540 kfree(entry);
1083 kumaneko 111 return ptr;
1084     }
1085    
1086 kumaneko 1052 /**
1087 kumaneko 2002 * ccs_write_profile - Write profile table.
1088 kumaneko 1052 *
1089 kumaneko 1657 * @head: Pointer to "struct ccs_io_buffer".
1090 kumaneko 1052 *
1091     * Returns 0 on success, negative value otherwise.
1092     */
1093 kumaneko 2002 static int ccs_write_profile(struct ccs_io_buffer *head)
1094 kumaneko 111 {
1095     char *data = head->write_buf;
1096 kumaneko 1064 unsigned int i;
1097     unsigned int value;
1098 kumaneko 111 char *cp;
1099 kumaneko 2002 struct ccs_profile *ccs_profile;
1100 kumaneko 111 i = simple_strtoul(data, &cp, 10);
1101     if (data != cp) {
1102 kumaneko 1052 if (*cp != '-')
1103     return -EINVAL;
1104     data = cp + 1;
1105 kumaneko 111 }
1106 kumaneko 2002 ccs_profile = ccs_find_or_assign_new_profile(i);
1107     if (!ccs_profile)
1108 kumaneko 1052 return -EINVAL;
1109 kumaneko 111 cp = strchr(data, '=');
1110 kumaneko 1052 if (!cp)
1111     return -EINVAL;
1112 kumaneko 111 *cp = '\0';
1113 kumaneko 1052 if (!strcmp(data, "COMMENT")) {
1114 kumaneko 2540 ccs_profile->comment = ccs_get_name(cp + 1);
1115 kumaneko 2254 ccs_profile_entry_used[0] = true;
1116 kumaneko 111 return 0;
1117     }
1118 kumaneko 2002 if (ccs_str_starts(&data, KEYWORD_MAC_FOR_CAPABILITY)) {
1119 kumaneko 1014 if (sscanf(cp + 1, "%u", &value) != 1) {
1120 kumaneko 1015 for (i = 0; i < 4; i++) {
1121 kumaneko 2002 if (strcmp(cp + 1, ccs_mode_4[i]))
1122 kumaneko 1052 continue;
1123 kumaneko 1015 value = i;
1124 kumaneko 1014 break;
1125     }
1126 kumaneko 1052 if (i == 4)
1127     return -EINVAL;
1128 kumaneko 1014 }
1129 kumaneko 1052 if (value > 3)
1130     value = 3;
1131 kumaneko 2282 for (i = 0; i < CCS_MAX_CAPABILITY_INDEX; i++) {
1132 kumaneko 2002 if (strcmp(data, ccs_capability_control_keyword[i]))
1133 kumaneko 1052 continue;
1134 kumaneko 2002 ccs_profile->capability_value[i] = value;
1135 kumaneko 2254 ccs_profile_entry_used[i + 1 + CCS_MAX_CONTROL_INDEX]
1136     = true;
1137 kumaneko 1015 return 0;
1138     }
1139     return -EINVAL;
1140 kumaneko 111 }
1141     for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++) {
1142 kumaneko 1052 if (strcmp(data, ccs_control_array[i].keyword))
1143     continue;
1144 kumaneko 1014 if (sscanf(cp + 1, "%u", &value) != 1) {
1145     int j;
1146     const char **modes;
1147     switch (i) {
1148 kumaneko 2282 case CCS_RESTRICT_AUTOBIND:
1149     case CCS_VERBOSE:
1150 kumaneko 2002 modes = ccs_mode_2;
1151 kumaneko 1014 break;
1152     default:
1153 kumaneko 2002 modes = ccs_mode_4;
1154 kumaneko 1014 break;
1155     }
1156     for (j = 0; j < 4; j++) {
1157 kumaneko 1052 if (strcmp(cp + 1, modes[j]))
1158     continue;
1159 kumaneko 1014 value = j;
1160     break;
1161     }
1162 kumaneko 1052 if (j == 4)
1163     return -EINVAL;
1164 kumaneko 1014 } else if (value > ccs_control_array[i].max_value) {
1165     value = ccs_control_array[i].max_value;
1166     }
1167 kumaneko 2002 ccs_profile->value[i] = value;
1168 kumaneko 2254 ccs_profile_entry_used[i + 1] = true;
1169 kumaneko 111 return 0;
1170     }
1171     return -EINVAL;
1172     }
1173    
1174 kumaneko 1052 /**
1175 kumaneko 2002 * ccs_read_profile - Read profile table.
1176 kumaneko 1052 *
1177 kumaneko 1657 * @head: Pointer to "struct ccs_io_buffer".
1178 kumaneko 1052 *
1179     * Returns 0.
1180     */
1181 kumaneko 2002 static int ccs_read_profile(struct ccs_io_buffer *head)
1182 kumaneko 111 {
1183 kumaneko 2002 static const int ccs_total
1184 kumaneko 2282 = CCS_MAX_CONTROL_INDEX + CCS_MAX_CAPABILITY_INDEX + 1;
1185 kumaneko 1006 int step;
1186 kumaneko 1052 if (head->read_eof)
1187     return 0;
1188 kumaneko 2002 for (step = head->read_step; step < MAX_PROFILES * ccs_total; step++) {
1189     const u8 index = step / ccs_total;
1190     u8 type = step % ccs_total;
1191     const struct ccs_profile *ccs_profile = ccs_profile_ptr[index];
1192 kumaneko 1006 head->read_step = step;
1193 kumaneko 2002 if (!ccs_profile)
1194 kumaneko 1052 continue;
1195 kumaneko 2254 if (!ccs_profile_entry_used[type])
1196     continue;
1197 kumaneko 1052 if (!type) { /* Print profile' comment tag. */
1198     if (!ccs_io_printf(head, "%u-COMMENT=%s\n",
1199 kumaneko 2002 index, ccs_profile->comment ?
1200     ccs_profile->comment->name : ""))
1201 kumaneko 1052 break;
1202     continue;
1203     }
1204     type--;
1205     if (type >= CCS_MAX_CONTROL_INDEX) {
1206     const int i = type - CCS_MAX_CONTROL_INDEX;
1207 kumaneko 2002 const u8 value = ccs_profile->capability_value[i];
1208 kumaneko 1052 if (!ccs_io_printf(head,
1209     "%u-" KEYWORD_MAC_FOR_CAPABILITY
1210     "%s=%s\n", index,
1211 kumaneko 2002 ccs_capability_control_keyword[i],
1212     ccs_mode_4[value]))
1213 kumaneko 1052 break;
1214 kumaneko 1006 } else {
1215 kumaneko 2002 const unsigned int value = ccs_profile->value[type];
1216 kumaneko 1014 const char **modes = NULL;
1217 kumaneko 1052 const char *keyword = ccs_control_array[type].keyword;
1218     switch (ccs_control_array[type].max_value) {
1219 kumaneko 1014 case 3:
1220 kumaneko 2002 modes = ccs_mode_4;
1221 kumaneko 1014 break;
1222     case 1:
1223 kumaneko 2002 modes = ccs_mode_2;
1224 kumaneko 1014 break;
1225     }
1226     if (modes) {
1227 kumaneko 1052 if (!ccs_io_printf(head, "%u-%s=%s\n", index,
1228     keyword, modes[value]))
1229     break;
1230 kumaneko 1014 } else {
1231 kumaneko 1052 if (!ccs_io_printf(head, "%u-%s=%u\n", index,
1232     keyword, value))
1233     break;
1234 kumaneko 1014 }
1235 kumaneko 1006 }
1236     }
1237 kumaneko 2002 if (step == MAX_PROFILES * ccs_total)
1238 kumaneko 1052 head->read_eof = true;
1239 kumaneko 111 return 0;
1240     }
1241    
1242 kumaneko 2002 /* The list for "struct ccs_policy_manager_entry". */
1243 kumaneko 2540 LIST_HEAD(ccs_policy_manager_list);
1244 kumaneko 111
1245 kumaneko 1052 /**
1246 kumaneko 2002 * ccs_update_manager_entry - Add a manager entry.
1247 kumaneko 1052 *
1248     * @manager: The path to manager or the domainnamme.
1249     * @is_delete: True if it is a delete request.
1250     *
1251     * Returns 0 on success, negative value otherwise.
1252     */
1253 kumaneko 2002 static int ccs_update_manager_entry(const char *manager, const bool is_delete)
1254 kumaneko 111 {
1255 kumaneko 2540 struct ccs_policy_manager_entry *entry = NULL;
1256 kumaneko 2002 struct ccs_policy_manager_entry *ptr;
1257     const struct ccs_path_info *saved_manager;
1258 kumaneko 2540 int error = is_delete ? -ENOENT : -ENOMEM;
1259 kumaneko 1006 bool is_domain = false;
1260 kumaneko 1052 if (ccs_is_domain_def(manager)) {
1261 kumaneko 2577 if (!ccs_is_correct_domain(manager))
1262 kumaneko 1052 return -EINVAL;
1263 kumaneko 1006 is_domain = true;
1264 kumaneko 111 } else {
1265 kumaneko 2577 if (!ccs_is_correct_path(manager, 1, -1, -1))
1266 kumaneko 1052 return -EINVAL;
1267 kumaneko 111 }
1268 kumaneko 2540 saved_manager = ccs_get_name(manager);
1269 kumaneko 1052 if (!saved_manager)
1270     return -ENOMEM;
1271 kumaneko 2540 if (!is_delete)
1272     entry = kzalloc(sizeof(*entry), GFP_KERNEL);
1273 kumaneko 2690 mutex_lock(&ccs_policy_lock);
1274     list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
1275 kumaneko 1064 if (ptr->manager != saved_manager)
1276     continue;
1277     ptr->is_deleted = is_delete;
1278     error = 0;
1279 kumaneko 2540 break;
1280 kumaneko 111 }
1281 kumaneko 2540 if (!is_delete && error && ccs_memory_ok(entry)) {
1282     entry->manager = saved_manager;
1283     saved_manager = NULL;
1284     entry->is_domain = is_domain;
1285 kumaneko 2690 list_add_tail_rcu(&entry->list, &ccs_policy_manager_list);
1286 kumaneko 2540 entry = NULL;
1287     error = 0;
1288 kumaneko 111 }
1289 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
1290 kumaneko 2540 ccs_put_name(saved_manager);
1291     kfree(entry);
1292 kumaneko 111 return error;
1293     }
1294    
1295 kumaneko 1052 /**
1296 kumaneko 2002 * ccs_write_manager_policy - Write manager policy.
1297 kumaneko 1052 *
1298 kumaneko 1657 * @head: Pointer to "struct ccs_io_buffer".
1299 kumaneko 1052 *
1300     * Returns 0 on success, negative value otherwise.
1301     */
1302 kumaneko 2002 static int ccs_write_manager_policy(struct ccs_io_buffer *head)
1303 kumaneko 111 {
1304 kumaneko 1052 char *data = head->write_buf;
1305 kumaneko 2002 bool is_delete = ccs_str_starts(&data, KEYWORD_DELETE);
1306 kumaneko 1064 if (!strcmp(data, "manage_by_non_root")) {
1307 kumaneko 2002 ccs_manage_by_non_root = !is_delete;
1308 kumaneko 1006 return 0;
1309     }
1310 kumaneko 2002 return ccs_update_manager_entry(data, is_delete);
1311 kumaneko 111 }
1312    
1313 kumaneko 1052 /**
1314 kumaneko 2002 * ccs_read_manager_policy - Read manager policy.
1315 kumaneko 1052 *
1316 kumaneko 1657 * @head: Pointer to "struct ccs_io_buffer".
1317 kumaneko 1052 *
1318     * Returns 0.
1319 kumaneko 2690 *
1320     * Caller holds srcu_read_lock(&ccs_ss).
1321 kumaneko 1052 */
1322 kumaneko 2002 static int ccs_read_manager_policy(struct ccs_io_buffer *head)
1323 kumaneko 111 {
1324 kumaneko 2540 struct list_head *pos;
1325 kumaneko 1052 if (head->read_eof)
1326     return 0;
1327 kumaneko 2690 list_for_each_cookie(pos, head->read_var2, &ccs_policy_manager_list) {
1328 kumaneko 2002 struct ccs_policy_manager_entry *ptr;
1329 kumaneko 2540 ptr = list_entry(pos, struct ccs_policy_manager_entry, list);
1330 kumaneko 1052 if (ptr->is_deleted)
1331     continue;
1332 kumaneko 2692 if (!ccs_io_printf(head, "%s\n", ptr->manager->name))
1333     return 0;
1334 kumaneko 111 }
1335 kumaneko 2692 head->read_eof = true;
1336 kumaneko 111 return 0;
1337     }
1338    
1339 kumaneko 1052 /**
1340 kumaneko 2002 * ccs_is_policy_manager - Check whether the current process is a policy manager.
1341 kumaneko 1052 *
1342     * Returns true if the current process is permitted to modify policy
1343     * via /proc/ccs/ interface.
1344 kumaneko 2701 *
1345     * Caller holds srcu_read_lock(&ccs_ss).
1346 kumaneko 1052 */
1347 kumaneko 2002 static bool ccs_is_policy_manager(void)
1348 kumaneko 111 {
1349 kumaneko 2002 struct ccs_policy_manager_entry *ptr;
1350 kumaneko 111 const char *exe;
1351 kumaneko 1578 struct task_struct *task = current;
1352 kumaneko 2282 const struct ccs_path_info *domainname
1353     = ccs_current_domain()->domainname;
1354 kumaneko 1006 bool found = false;
1355 kumaneko 2040 if (!ccs_policy_loaded)
1356 kumaneko 1052 return true;
1357 kumaneko 2282 if (task->ccs_flags & CCS_TASK_IS_POLICY_MANAGER)
1358 kumaneko 1578 return true;
1359 kumaneko 2016 if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
1360 kumaneko 1052 return false;
1361 kumaneko 2690 list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
1362 kumaneko 1052 if (!ptr->is_deleted && ptr->is_domain
1363 kumaneko 1578 && !ccs_pathcmp(domainname, ptr->manager)) {
1364     /* Set manager flag. */
1365 kumaneko 2282 task->ccs_flags |= CCS_TASK_IS_POLICY_MANAGER;
1366 kumaneko 1052 return true;
1367 kumaneko 1578 }
1368 kumaneko 111 }
1369 kumaneko 1052 exe = ccs_get_exe();
1370     if (!exe)
1371     return false;
1372 kumaneko 2690 list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
1373 kumaneko 1052 if (!ptr->is_deleted && !ptr->is_domain
1374     && !strcmp(exe, ptr->manager->name)) {
1375 kumaneko 1006 found = true;
1376 kumaneko 1578 /* Set manager flag. */
1377 kumaneko 2282 task->ccs_flags |= CCS_TASK_IS_POLICY_MANAGER;
1378 kumaneko 708 break;
1379     }
1380 kumaneko 111 }
1381 kumaneko 708 if (!found) { /* Reduce error messages. */
1382 kumaneko 2002 static pid_t ccs_last_pid;
1383 kumaneko 111 const pid_t pid = current->pid;
1384 kumaneko 2002 if (ccs_last_pid != pid) {
1385 kumaneko 1052 printk(KERN_WARNING "%s ( %s ) is not permitted to "
1386     "update policies.\n", domainname->name, exe);
1387 kumaneko 2002 ccs_last_pid = pid;
1388 kumaneko 111 }
1389     }
1390     ccs_free(exe);
1391 kumaneko 708 return found;
1392 kumaneko 111 }
1393    
1394 kumaneko 1052 /**
1395     * ccs_find_condition_part - Find condition part from the statement.
1396     *
1397     * @data: String to parse.
1398     *
1399     * Returns pointer to the condition part if it was found in the statement,
1400     * NULL otherwise.
1401     */
1402     static char *ccs_find_condition_part(char *data)
1403 kumaneko 581 {
1404 kumaneko 1064 char *cp = strstr(data, " if ");
1405 kumaneko 581 if (cp) {
1406 kumaneko 1747 while (1) {
1407     char *cp2 = strstr(cp + 3, " if ");
1408     if (!cp2)
1409     break;
1410 kumaneko 1064 cp = cp2;
1411 kumaneko 1747 }
1412 kumaneko 581 *cp++ = '\0';
1413 kumaneko 1052 } else {
1414     cp = strstr(data, " ; set ");
1415     if (cp)
1416     *cp++ = '\0';
1417 kumaneko 581 }
1418     return cp;
1419     }
1420    
1421 kumaneko 1052 /**
1422 kumaneko 2002 * ccs_is_select_one - Parse select command.
1423 kumaneko 1609 *
1424     * @head: Pointer to "struct ccs_io_buffer".
1425     * @data: String to parse.
1426     *
1427     * Returns true on success, false otherwise.
1428 kumaneko 2690 *
1429     * Caller holds srcu_read_lock(&ccs_ss).
1430 kumaneko 1609 */
1431 kumaneko 2002 static bool ccs_is_select_one(struct ccs_io_buffer *head, const char *data)
1432 kumaneko 1609 {
1433     unsigned int pid;
1434 kumaneko 2692 struct ccs_domain_info *domain = NULL;
1435 kumaneko 1926 if (!strcmp(data, "allow_execute")) {
1436     head->read_execute_only = true;
1437     return true;
1438     }
1439 kumaneko 1609 if (sscanf(data, "pid=%u", &pid) == 1) {
1440     struct task_struct *p;
1441     /***** CRITICAL SECTION START *****/
1442     read_lock(&tasklist_lock);
1443     p = find_task_by_pid(pid);
1444     if (p)
1445 kumaneko 2690 domain = ccs_task_domain(p);
1446 kumaneko 1609 read_unlock(&tasklist_lock);
1447     /***** CRITICAL SECTION END *****/
1448     } else if (!strncmp(data, "domain=", 7)) {
1449 kumaneko 2544 if (ccs_is_domain_def(data + 7))
1450 kumaneko 2690 domain = ccs_find_domain(data + 7);
1451 kumaneko 1609 } else
1452     return false;
1453 kumaneko 2690 head->write_var1 = domain;
1454 kumaneko 1810 /* Accessing read_buf is safe because head->io_sem is held. */
1455 kumaneko 1809 if (!head->read_buf)
1456     return true; /* Do nothing if open(O_WRONLY). */
1457 kumaneko 1609 head->read_avail = 0;
1458     ccs_io_printf(head, "# select %s\n", data);
1459     head->read_single_domain = true;
1460 kumaneko 2690 head->read_eof = !domain;
1461 kumaneko 2692 if (domain) {
1462     struct ccs_domain_info *d;
1463     head->read_var1 = NULL;
1464     list_for_each_entry_rcu(d, &ccs_domain_list, list) {
1465     if (d == domain)
1466     break;
1467     head->read_var1 = &d->list;
1468     }
1469     head->read_var2 = NULL;
1470     head->read_bit = 0;
1471     head->read_step = 0;
1472     if (domain->is_deleted)
1473     ccs_io_printf(head, "# This is a deleted domain.\n");
1474     }
1475 kumaneko 1609 return true;
1476     }
1477    
1478     /**
1479 kumaneko 2002 * ccs_write_domain_policy - Write domain policy.
1480 kumaneko 1052 *
1481     * @head: Pointer to "struct ccs_io_buffer".
1482     *
1483     * Returns 0 on success, negative value otherwise.
1484     */
1485 kumaneko 2002 static int ccs_write_domain_policy(struct ccs_io_buffer *head)
1486 kumaneko 111 {
1487     char *data = head->write_buf;
1488 kumaneko 2690 struct ccs_domain_info *domain = head->write_var1;
1489 kumaneko 1064 bool is_delete = false;
1490     bool is_select = false;
1491 kumaneko 111 unsigned int profile;
1492 kumaneko 2576 struct ccs_condition *cond = NULL;
1493 kumaneko 906 char *cp;
1494 kumaneko 2553 int error;
1495 kumaneko 2002 if (ccs_str_starts(&data, KEYWORD_DELETE))
1496 kumaneko 1006 is_delete = true;
1497 kumaneko 2002 else if (ccs_str_starts(&data, KEYWORD_SELECT))
1498 kumaneko 1006 is_select = true;
1499 kumaneko 2002 if (is_select && ccs_is_select_one(head, data))
1500 kumaneko 1609 return 0;
1501 kumaneko 1606 /* Don't allow updating policies by non manager programs. */
1502 kumaneko 2002 if (!ccs_is_policy_manager())
1503 kumaneko 1606 return -EPERM;
1504 kumaneko 1052 if (ccs_is_domain_def(data)) {
1505 kumaneko 2690 domain = NULL;
1506 kumaneko 2692 if (is_delete)
1507 kumaneko 1052 ccs_delete_domain(data);
1508 kumaneko 2692 else if (is_select)
1509 kumaneko 2690 domain = ccs_find_domain(data);
1510 kumaneko 2544 else
1511 kumaneko 2690 domain = ccs_find_or_assign_new_domain(data, 0);
1512 kumaneko 2692 head->write_var1 = domain;
1513 kumaneko 111 return 0;
1514     }
1515 kumaneko 2690 if (!domain)
1516 kumaneko 1052 return -EINVAL;
1517 kumaneko 581
1518 kumaneko 1052 if (sscanf(data, KEYWORD_USE_PROFILE "%u", &profile) == 1
1519     && profile < MAX_PROFILES) {
1520 kumaneko 2040 if (ccs_profile_ptr[profile] || !ccs_policy_loaded)
1521 kumaneko 2690 domain->profile = (u8) profile;
1522 kumaneko 581 return 0;
1523     }
1524 kumaneko 1052 if (!strcmp(data, KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
1525 kumaneko 2690 domain->ignore_global_allow_read = !is_delete;
1526 kumaneko 1007 return 0;
1527     }
1528 kumaneko 1052 if (!strcmp(data, KEYWORD_IGNORE_GLOBAL_ALLOW_ENV)) {
1529 kumaneko 2690 domain->ignore_global_allow_env = !is_delete;
1530 kumaneko 1007 return 0;
1531     }
1532 kumaneko 1052 cp = ccs_find_condition_part(data);
1533     if (cp) {
1534 kumaneko 2553 cond = ccs_get_condition(cp);
1535 kumaneko 1052 if (!cond)
1536     return -EINVAL;
1537 kumaneko 111 }
1538 kumaneko 2002 if (ccs_str_starts(&data, KEYWORD_ALLOW_CAPABILITY))
1539 kumaneko 2690 error = ccs_write_capability_policy(data, domain, cond,
1540     is_delete);
1541 kumaneko 2002 else if (ccs_str_starts(&data, KEYWORD_ALLOW_NETWORK))
1542 kumaneko 2690 error = ccs_write_network_policy(data, domain, cond, is_delete);
1543 kumaneko 2553 else if (ccs_str_starts(&data, KEYWORD_ALLOW_SIGNAL))
1544 kumaneko 2690 error = ccs_write_signal_policy(data, domain, cond, is_delete);
1545 kumaneko 2553 else if (ccs_str_starts(&data, KEYWORD_ALLOW_ARGV0))
1546 kumaneko 2690 error = ccs_write_argv0_policy(data, domain, cond, is_delete);
1547 kumaneko 2002 else if (ccs_str_starts(&data, KEYWORD_ALLOW_ENV))
1548 kumaneko 2690 error = ccs_write_env_policy(data, domain, cond, is_delete);
1549 kumaneko 2271 else if (ccs_str_starts(&data, KEYWORD_ALLOW_IOCTL))
1550 kumaneko 2690 error = ccs_write_ioctl_policy(data, domain, cond, is_delete);
1551 kumaneko 2707 else if (ccs_str_starts(&data, KEYWORD_ALLOW_MOUNT))
1552     error = ccs_write_mount_policy(data, domain, cond, is_delete);
1553 kumaneko 2708 else if (ccs_str_starts(&data, KEYWORD_ALLOW_UNMOUNT))
1554     error = ccs_write_umount_policy(data, domain, cond, is_delete);
1555 kumaneko 2707 else if (ccs_str_starts(&data, KEYWORD_ALLOW_CHROOT))
1556     error = ccs_write_chroot_policy(data, domain, cond, is_delete);
1557     else if (ccs_str_starts(&data, KEYWORD_ALLOW_PIVOT_ROOT))
1558     error = ccs_write_pivot_root_policy(data, domain, cond,
1559     is_delete);
1560 kumaneko 2553 else
1561 kumaneko 2690 error = ccs_write_file_policy(data, domain, cond, is_delete);
1562 kumaneko 2553 if (cond)
1563     ccs_put_condition(cond);
1564     return error;
1565 kumaneko 111 }
1566    
1567 kumaneko 1052 /**
1568 kumaneko 2002 * ccs_print_single_path_acl - Print a single path ACL entry.
1569 kumaneko 1052 *
1570     * @head: Pointer to "struct ccs_io_buffer".
1571 kumaneko 2002 * @ptr: Pointer to "struct ccs_single_path_acl_record".
1572 kumaneko 2576 * @cond: Pointer to "struct ccs_condition". May be NULL.
1573 kumaneko 1052 *
1574     * Returns true on success, false otherwise.
1575     */
1576 kumaneko 2002 static bool ccs_print_single_path_acl(struct ccs_io_buffer *head,
1577     struct ccs_single_path_acl_record *ptr,
1578 kumaneko 2576 const struct ccs_condition *cond)
1579 kumaneko 856 {
1580     int pos;
1581     u8 bit;
1582 kumaneko 1052 const char *atmark = "";
1583     const char *filename;
1584 kumaneko 856 const u16 perm = ptr->perm;
1585 kumaneko 1052 if (ptr->u_is_group) {
1586     atmark = "@";
1587     filename = ptr->u.group->group_name->name;
1588     } else {
1589     filename = ptr->u.filename->name;
1590     }
1591 kumaneko 856 for (bit = head->read_bit; bit < MAX_SINGLE_PATH_OPERATION; bit++) {
1592     const char *msg;
1593 kumaneko 1052 if (!(perm & (1 << bit)))
1594     continue;
1595 kumaneko 1926 if (head->read_execute_only && bit != TYPE_EXECUTE_ACL)
1596     continue;
1597 kumaneko 856 /* Print "read/write" instead of "read" and "write". */
1598 kumaneko 1052 if ((bit == TYPE_READ_ACL || bit == TYPE_WRITE_ACL)
1599     && (perm & (1 << TYPE_READ_WRITE_ACL)))
1600     continue;
1601     msg = ccs_sp2keyword(bit);
1602 kumaneko 856 pos = head->read_avail;
1603 kumaneko 1052 if (!ccs_io_printf(head, "allow_%s %s%s", msg,
1604     atmark, filename) ||
1605 kumaneko 1054 !ccs_print_condition(head, cond))
1606 kumaneko 1052 goto out;
1607 kumaneko 856 }
1608     head->read_bit = 0;
1609 kumaneko 1006 return true;
1610 kumaneko 856 out:
1611     head->read_bit = bit;
1612     head->read_avail = pos;
1613 kumaneko 1006 return false;
1614 kumaneko 856 }
1615    
1616 kumaneko 1052 /**
1617 kumaneko 2002 * ccs_print_double_path_acl - Print a double path ACL entry.
1618 kumaneko 1052 *
1619     * @head: Pointer to "struct ccs_io_buffer".
1620 kumaneko 2002 * @ptr: Pointer to "struct ccs_double_path_acl_record".
1621 kumaneko 2576 * @cond: Pointer to "struct ccs_condition". May be NULL.
1622 kumaneko 1052 *
1623     * Returns true on success, false otherwise.
1624     */
1625 kumaneko 2002 static bool ccs_print_double_path_acl(struct ccs_io_buffer *head,
1626     struct ccs_double_path_acl_record *ptr,
1627 kumaneko 2576 const struct ccs_condition *cond)
1628 kumaneko 856 {
1629     int pos;
1630 kumaneko 1052 const char *atmark1 = "";
1631     const char *atmark2 = "";
1632     const char *filename1;
1633     const char *filename2;
1634 kumaneko 856 const u8 perm = ptr->perm;
1635     u8 bit;
1636 kumaneko 1052 if (ptr->u1_is_group) {
1637     atmark1 = "@";
1638     filename1 = ptr->u1.group1->group_name->name;
1639     } else {
1640     filename1 = ptr->u1.filename1->name;
1641     }
1642     if (ptr->u2_is_group) {
1643     atmark2 = "@";
1644     filename2 = ptr->u2.group2->group_name->name;
1645     } else {
1646     filename2 = ptr->u2.filename2->name;
1647     }
1648 kumaneko 856 for (bit = head->read_bit; bit < MAX_DOUBLE_PATH_OPERATION; bit++) {
1649     const char *msg;
1650 kumaneko 1052 if (!(perm & (1 << bit)))
1651     continue;
1652     msg = ccs_dp2keyword(bit);
1653 kumaneko 856 pos = head->read_avail;
1654 kumaneko 1052 if (!ccs_io_printf(head, "allow_%s %s%s %s%s", msg,
1655 kumaneko 1064 atmark1, filename1, atmark2, filename2) ||
1656 kumaneko 1054 !ccs_print_condition(head, cond))
1657 kumaneko 1052 goto out;
1658 kumaneko 856 }
1659 kumaneko 1032 head->read_bit = 0;
1660 kumaneko 1006 return true;
1661 kumaneko 856 out:
1662     head->read_bit = bit;
1663     head->read_avail = pos;
1664 kumaneko 1006 return false;
1665 kumaneko 856 }
1666    
1667 kumaneko 1052 /**
1668 kumaneko 2271 * ccs_print_ioctl_acl - Print an ioctl ACL entry.
1669     *
1670     * @head: Pointer to "struct ccs_io_buffer".
1671     * @ptr: Pointer to "struct ccs_ioctl_acl_record".
1672 kumaneko 2576 * @cond: Pointer to "struct ccs_condition". May be NULL.
1673 kumaneko 2271 *
1674     * Returns true on success, false otherwise.
1675     */
1676     static bool ccs_print_ioctl_acl(struct ccs_io_buffer *head,
1677     struct ccs_ioctl_acl_record *ptr,
1678 kumaneko 2576 const struct ccs_condition *cond)
1679 kumaneko 2271 {
1680     int pos = head->read_avail;
1681     const char *atmark = "";
1682     const char *filename;
1683     const unsigned int cmd_min = ptr->cmd_min;
1684     const unsigned int cmd_max = ptr->cmd_max;
1685     if (ptr->u_is_group) {
1686     atmark = "@";
1687     filename = ptr->u.group->group_name->name;
1688     } else {
1689     filename = ptr->u.filename->name;
1690     }
1691     if (!ccs_io_printf(head, KEYWORD_ALLOW_IOCTL "%s%s ", atmark, filename))
1692     goto out;
1693     if (!ccs_io_printf(head, "%u", cmd_min))
1694     goto out;
1695     if (cmd_min != cmd_max && !ccs_io_printf(head, "-%u", cmd_max))
1696     goto out;
1697     if (!ccs_print_condition(head, cond))
1698     goto out;
1699     return true;
1700     out:
1701     head->read_avail = pos;
1702     return false;
1703     }
1704    
1705     /**
1706 kumaneko 2002 * ccs_print_argv0_acl - Print an argv[0] ACL entry.
1707 kumaneko 1052 *
1708     * @head: Pointer to "struct ccs_io_buffer".
1709 kumaneko 2002 * @ptr: Pointer to "struct ccs_argv0_acl_record".
1710 kumaneko 2576 * @cond: Pointer to "struct ccs_condition". May be NULL.
1711 kumaneko 1052 *
1712     * Returns true on success, false otherwise.
1713     */
1714 kumaneko 2002 static bool ccs_print_argv0_acl(struct ccs_io_buffer *head,
1715     struct ccs_argv0_acl_record *ptr,
1716 kumaneko 2576 const struct ccs_condition *cond)
1717 kumaneko 856 {
1718     int pos = head->read_avail;
1719 kumaneko 1052 if (!ccs_io_printf(head, KEYWORD_ALLOW_ARGV0 "%s %s",
1720     ptr->filename->name, ptr->argv0->name))
1721     goto out;
1722 kumaneko 1054 if (!ccs_print_condition(head, cond))
1723 kumaneko 1052 goto out;
1724 kumaneko 1006 return true;
1725 kumaneko 856 out:
1726     head->read_avail = pos;
1727 kumaneko 1006 return false;
1728 kumaneko 856 }
1729    
1730 kumaneko 1052 /**
1731 kumaneko 2002 * ccs_print_env_acl - Print an evironment variable name's ACL entry.
1732 kumaneko 1052 *
1733     * @head: Pointer to "struct ccs_io_buffer".
1734 kumaneko 2002 * @ptr: Pointer to "struct ccs_env_acl_record".
1735 kumaneko 2576 * @cond: Pointer to "struct ccs_condition". May be NULL.
1736 kumaneko 1052 *
1737     * Returns true on success, false otherwise.
1738     */
1739 kumaneko 2002 static bool ccs_print_env_acl(struct ccs_io_buffer *head,
1740     struct ccs_env_acl_record *ptr,
1741 kumaneko 2576 const struct ccs_condition *cond)
1742 kumaneko 856 {
1743     int pos = head->read_avail;
1744 kumaneko 1052 if (!ccs_io_printf(head, KEYWORD_ALLOW_ENV "%s", ptr->env->name))
1745     goto out;
1746 kumaneko 1054 if (!ccs_print_condition(head, cond))
1747 kumaneko 1052 goto out;
1748 kumaneko 1006 return true;
1749 kumaneko 856 out:
1750     head->read_avail = pos;
1751 kumaneko 1006 return false;
1752 kumaneko 856 }
1753    
1754 kumaneko 1052 /**
1755 kumaneko 2002 * ccs_print_capability_acl - Print a capability ACL entry.
1756 kumaneko 1052 *
1757     * @head: Pointer to "struct ccs_io_buffer".
1758 kumaneko 2002 * @ptr: Pointer to "struct ccs_capability_acl_record".
1759 kumaneko 2576 * @cond: Pointer to "struct ccs_condition". May be NULL.
1760 kumaneko 1052 *
1761     * Returns true on success, false otherwise.
1762     */
1763 kumaneko 2002 static bool ccs_print_capability_acl(struct ccs_io_buffer *head,
1764     struct ccs_capability_acl_record *ptr,
1765 kumaneko 2576 const struct ccs_condition *cond)
1766 kumaneko 856 {
1767 kumaneko 860 int pos = head->read_avail;
1768 kumaneko 1052 if (!ccs_io_printf(head, KEYWORD_ALLOW_CAPABILITY "%s",
1769     ccs_cap2keyword(ptr->operation)))
1770     goto out;
1771 kumaneko 1054 if (!ccs_print_condition(head, cond))
1772 kumaneko 1052 goto out;
1773 kumaneko 1006 return true;
1774 kumaneko 856 out:
1775     head->read_avail = pos;
1776 kumaneko 1006 return false;
1777 kumaneko 856 }
1778    
1779 kumaneko 1052 /**
1780 kumaneko 2002 * ccs_print_ipv4_entry - Print IPv4 address of a network ACL entry.
1781 kumaneko 1052 *
1782     * @head: Pointer to "struct ccs_io_buffer".
1783 kumaneko 2002 * @ptr: Pointer to "struct ccs_ip_network_acl_record".
1784 kumaneko 1052 *
1785     * Returns true on success, false otherwise.
1786     */
1787 kumaneko 2002 static bool ccs_print_ipv4_entry(struct ccs_io_buffer *head,
1788     struct ccs_ip_network_acl_record *ptr)
1789 kumaneko 856 {
1790 kumaneko 1052 const u32 min_address = ptr->u.ipv4.min;
1791     const u32 max_address = ptr->u.ipv4.max;
1792     if (!ccs_io_printf(head, "%u.%u.%u.%u", HIPQUAD(min_address)))
1793     return false;
1794     if (min_address != max_address
1795     && !ccs_io_printf(head, "-%u.%u.%u.%u", HIPQUAD(max_address)))
1796     return false;
1797     return true;
1798     }
1799    
1800     /**
1801 kumaneko 2002 * ccs_print_ipv6_entry - Print IPv6 address of a network ACL entry.
1802 kumaneko 1052 *
1803     * @head: Pointer to "struct ccs_io_buffer".
1804 kumaneko 2002 * @ptr: Pointer to "struct ccs_ip_network_acl_record".
1805 kumaneko 1052 *
1806     * Returns true on success, false otherwise.
1807     */
1808 kumaneko 2002 static bool ccs_print_ipv6_entry(struct ccs_io_buffer *head,
1809     struct ccs_ip_network_acl_record *ptr)
1810 kumaneko 1052 {
1811     char buf[64];
1812     const struct in6_addr *min_address = ptr->u.ipv6.min;
1813     const struct in6_addr *max_address = ptr->u.ipv6.max;
1814     ccs_print_ipv6(buf, sizeof(buf), min_address);
1815     if (!ccs_io_printf(head, "%s", buf))
1816     return false;
1817     if (min_address != max_address) {
1818     ccs_print_ipv6(buf, sizeof(buf), max_address);
1819     if (!ccs_io_printf(head, "-%s", buf))
1820     return false;
1821     }
1822     return true;
1823     }
1824    
1825     /**
1826 kumaneko 2002 * ccs_print_port_entry - Print port number of a network ACL entry.
1827 kumaneko 1052 *
1828     * @head: Pointer to "struct ccs_io_buffer".
1829 kumaneko 2002 * @ptr: Pointer to "struct ccs_ip_network_acl_record".
1830 kumaneko 1052 *
1831     * Returns true on success, false otherwise.
1832     */
1833 kumaneko 2002 static bool ccs_print_port_entry(struct ccs_io_buffer *head,
1834     struct ccs_ip_network_acl_record *ptr)
1835 kumaneko 1052 {
1836 kumaneko 2046 const u16 min_port = ptr->min_port;
1837     const u16 max_port = ptr->max_port;
1838 kumaneko 1052 if (!ccs_io_printf(head, " %u", min_port))
1839     return false;
1840     if (min_port != max_port && !ccs_io_printf(head, "-%u", max_port))
1841     return false;
1842     return true;
1843     }
1844    
1845     /**
1846 kumaneko 2002 * ccs_print_network_acl - Print a network ACL entry.
1847 kumaneko 1052 *
1848     * @head: Pointer to "struct ccs_io_buffer".
1849 kumaneko 2002 * @ptr: Pointer to "struct ccs_ip_network_acl_record".
1850 kumaneko 2576 * @cond: Pointer to "struct ccs_condition". May be NULL.
1851 kumaneko 1052 *
1852     * Returns true on success, false otherwise.
1853     */
1854 kumaneko 2002 static bool ccs_print_network_acl(struct ccs_io_buffer *head,
1855     struct ccs_ip_network_acl_record *ptr,
1856 kumaneko 2576 const struct ccs_condition *cond)
1857 kumaneko 1052 {
1858 kumaneko 856 int pos = head->read_avail;
1859 kumaneko 1052 if (!ccs_io_printf(head, KEYWORD_ALLOW_NETWORK "%s ",
1860     ccs_net2keyword(ptr->operation_type)))
1861     goto out;
1862 kumaneko 856 switch (ptr->record_type) {
1863     case IP_RECORD_TYPE_ADDRESS_GROUP:
1864 kumaneko 1052 if (!ccs_io_printf(head, "@%s", ptr->u.group->group_name->name))
1865     goto out;
1866 kumaneko 856 break;
1867     case IP_RECORD_TYPE_IPv4:
1868 kumaneko 2002 if (!ccs_print_ipv4_entry(head, ptr))
1869 kumaneko 1052 goto out;
1870 kumaneko 856 break;
1871     case IP_RECORD_TYPE_IPv6:
1872 kumaneko 2002 if (!ccs_print_ipv6_entry(head, ptr))
1873 kumaneko 1052 goto out;
1874 kumaneko 856 break;
1875     }
1876 kumaneko 2002 if (!ccs_print_port_entry(head, ptr))
1877 kumaneko 1052 goto out;
1878 kumaneko 1054 if (!ccs_print_condition(head, cond))
1879 kumaneko 1052 goto out;
1880 kumaneko 1006 return true;
1881 kumaneko 856 out:
1882     head->read_avail = pos;
1883 kumaneko 1006 return false;
1884 kumaneko 856 }
1885    
1886 kumaneko 1052 /**
1887 kumaneko 2002 * ccs_print_signal_acl - Print a signal ACL entry.
1888 kumaneko 1052 *
1889     * @head: Pointer to "struct ccs_io_buffer".
1890     * @ptr: Pointer to "struct signale_acl_record".
1891 kumaneko 2576 * @cond: Pointer to "struct ccs_condition". May be NULL.
1892 kumaneko 1052 *
1893     * Returns true on success, false otherwise.
1894     */
1895 kumaneko 2002 static bool ccs_print_signal_acl(struct ccs_io_buffer *head,
1896     struct ccs_signal_acl_record *ptr,
1897 kumaneko 2576 const struct ccs_condition *cond)
1898 kumaneko 856 {
1899     int pos = head->read_avail;
1900 kumaneko 1052 if (!ccs_io_printf(head, KEYWORD_ALLOW_SIGNAL "%u %s",
1901     ptr->sig, ptr->domainname->name))
1902     goto out;
1903 kumaneko 1054 if (!ccs_print_condition(head, cond))
1904 kumaneko 1052 goto out;
1905 kumaneko 1006 return true;
1906 kumaneko 856 out:
1907     head->read_avail = pos;
1908 kumaneko 1006 return false;
1909 kumaneko 856 }
1910    
1911 kumaneko 1052 /**
1912 kumaneko 2002 * ccs_print_execute_handler_record - Print an execute handler ACL entry.
1913 kumaneko 1052 *
1914     * @head: Pointer to "struct ccs_io_buffer".
1915     * @keyword: Name of the keyword.
1916 kumaneko 2002 * @ptr: Pointer to "struct ccs_execute_handler_record".
1917 kumaneko 1052 *
1918     * Returns true on success, false otherwise.
1919     */
1920 kumaneko 2002 static bool ccs_print_execute_handler_record(struct ccs_io_buffer *head,
1921     const char *keyword,
1922     struct ccs_execute_handler_record *
1923     ptr)
1924 kumaneko 1029 {
1925 kumaneko 1052 return ccs_io_printf(head, "%s %s\n", keyword, ptr->handler->name);
1926 kumaneko 1029 }
1927    
1928 kumaneko 1052 /**
1929 kumaneko 2708 * ccs_print_mount_acl - Print a mount ACL entry.
1930     *
1931     * @head: Pointer to "struct ccs_io_buffer".
1932     * @ptr: Pointer to "struct ccs_mount_acl_record".
1933     * @cond: Pointer to "struct ccs_condition". May be NULL.
1934     *
1935     * Returns true on success, false otherwise.
1936     */
1937     static bool ccs_print_mount_acl(struct ccs_io_buffer *head,
1938     struct ccs_mount_acl_record *ptr,
1939     const struct ccs_condition *cond)
1940     {
1941     int pos = head->read_avail;
1942     if (!ccs_io_printf(head, KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n",
1943     ptr->dev_name->name, ptr->dir_name->name,
1944     ptr->fs_type->name, ptr->flags))
1945     goto out;
1946     if (!ccs_print_condition(head, cond))
1947     goto out;
1948     return true;
1949     out:
1950     head->read_avail = pos;
1951     return false;
1952     }
1953    
1954     /**
1955     * ccs_print_umount_acl - Print a mount ACL entry.
1956     *
1957     * @head: Pointer to "struct ccs_io_buffer".
1958     * @ptr: Pointer to "struct ccs_umount_acl_record".
1959     * @cond: Pointer to "struct ccs_condition". May be NULL.
1960     *
1961     * Returns true on success, false otherwise.
1962     */
1963     static bool ccs_print_umount_acl(struct ccs_io_buffer *head,
1964     struct ccs_umount_acl_record *ptr,
1965     const struct ccs_condition *cond)
1966     {
1967     int pos = head->read_avail;
1968     if (!ccs_io_printf(head, KEYWORD_ALLOW_UNMOUNT "%s\n",
1969     ptr->dir->name))
1970     goto out;
1971     if (!ccs_print_condition(head, cond))
1972     goto out;
1973     return true;
1974     out:
1975     head->read_avail = pos;
1976     return false;
1977     }
1978    
1979     /**
1980     * ccs_print_chroot_acl - Print a chroot ACL entry.
1981     *
1982     * @head: Pointer to "struct ccs_io_buffer".
1983     * @ptr: Pointer to "struct ccs_chroot_acl_record".
1984     * @cond: Pointer to "struct ccs_condition". May be NULL.
1985     *
1986     * Returns true on success, false otherwise.
1987     */
1988     static bool ccs_print_chroot_acl(struct ccs_io_buffer *head,
1989     struct ccs_chroot_acl_record *ptr,
1990     const struct ccs_condition *cond)
1991     {
1992     int pos = head->read_avail;
1993     if (!ccs_io_printf(head, KEYWORD_ALLOW_CHROOT "%s\n",
1994     ptr->dir->name))
1995     goto out;
1996     if (!ccs_print_condition(head, cond))
1997     goto out;
1998     return true;
1999     out:
2000     head->read_avail = pos;
2001     return false;
2002     }
2003    
2004     /**
2005     * ccs_print_pivot_root_acl - Print a pivot_root ACL entry.
2006     *
2007     * @head: Pointer to "struct ccs_io_buffer".
2008     * @ptr: Pointer to "struct ccs_pivot_root_acl_record".
2009     * @cond: Pointer to "struct ccs_condition". May be NULL.
2010     *
2011     * Returns true on success, false otherwise.
2012     */
2013     static bool ccs_print_pivot_root_acl(struct ccs_io_buffer *head,
2014     struct ccs_pivot_root_acl_record *ptr,
2015     const struct ccs_condition *cond)
2016     {
2017     int pos = head->read_avail;
2018     if (!ccs_io_printf(head, KEYWORD_ALLOW_PIVOT_ROOT "%s %s\n",
2019     ptr->new_root->name, ptr->old_root->name))
2020     goto out;
2021     if (!ccs_print_condition(head, cond))
2022     goto out;
2023     return true;
2024     out:
2025     head->read_avail = pos;
2026     return false;
2027     }
2028    
2029     /**
2030 kumaneko 2002 * ccs_print_entry - Print an ACL entry.
2031 kumaneko 1052 *
2032     * @head: Pointer to "struct ccs_io_buffer".
2033     * @ptr: Pointer to an ACL entry.
2034     *
2035     * Returns true on success, false otherwise.
2036     */
2037 kumaneko 2002 static bool ccs_print_entry(struct ccs_io_buffer *head,
2038     struct ccs_acl_info *ptr)
2039 kumaneko 111 {
2040 kumaneko 2576 const struct ccs_condition *cond = ptr->cond;
2041 kumaneko 2692 const u8 acl_type = ccs_acl_type2(ptr);
2042 kumaneko 1052 if (acl_type & ACL_DELETED)
2043     return true;
2044     if (acl_type == TYPE_SINGLE_PATH_ACL) {
2045 kumaneko 2002 struct ccs_single_path_acl_record *acl
2046     = container_of(ptr, struct ccs_single_path_acl_record,
2047 kumaneko 1052 head);
2048 kumaneko 2002 return ccs_print_single_path_acl(head, acl, cond);
2049 kumaneko 1052 }
2050 kumaneko 1926 if (acl_type == TYPE_EXECUTE_HANDLER) {
2051 kumaneko 2002 struct ccs_execute_handler_record *acl
2052     = container_of(ptr, struct ccs_execute_handler_record,
2053 kumaneko 1926 head);
2054     const char *keyword = KEYWORD_EXECUTE_HANDLER;
2055 kumaneko 2002 return ccs_print_execute_handler_record(head, keyword, acl);
2056 kumaneko 1926 }
2057     if (acl_type == TYPE_DENIED_EXECUTE_HANDLER) {
2058 kumaneko 2002 struct ccs_execute_handler_record *acl
2059     = container_of(ptr, struct ccs_execute_handler_record,
2060 kumaneko 1926 head);
2061     const char *keyword = KEYWORD_DENIED_EXECUTE_HANDLER;
2062 kumaneko 2002 return ccs_print_execute_handler_record(head, keyword, acl);
2063 kumaneko 1926 }
2064     if (head->read_execute_only)
2065     return true;
2066 kumaneko 1052 if (acl_type == TYPE_DOUBLE_PATH_ACL) {
2067 kumaneko 2002 struct ccs_double_path_acl_record *acl
2068     = container_of(ptr, struct ccs_double_path_acl_record,
2069 kumaneko 1052 head);
2070 kumaneko 2002 return ccs_print_double_path_acl(head, acl, cond);
2071 kumaneko 1052 }
2072 kumaneko 2271 if (acl_type == TYPE_IOCTL_ACL) {
2073     struct ccs_ioctl_acl_record *acl
2074     = container_of(ptr, struct ccs_ioctl_acl_record, head);
2075     return ccs_print_ioctl_acl(head, acl, cond);
2076     }
2077 kumaneko 1052 if (acl_type == TYPE_ARGV0_ACL) {
2078 kumaneko 2002 struct ccs_argv0_acl_record *acl
2079     = container_of(ptr, struct ccs_argv0_acl_record, head);
2080     return ccs_print_argv0_acl(head, acl, cond);
2081 kumaneko 1052 }
2082     if (acl_type == TYPE_ENV_ACL) {
2083 kumaneko 2002 struct ccs_env_acl_record *acl
2084     = container_of(ptr, struct ccs_env_acl_record, head);
2085     return ccs_print_env_acl(head, acl, cond);
2086 kumaneko 1052 }
2087     if (acl_type == TYPE_CAPABILITY_ACL) {
2088 kumaneko 2002 struct ccs_capability_acl_record *acl
2089     = container_of(ptr, struct ccs_capability_acl_record,
2090     head);
2091     return ccs_print_capability_acl(head, acl, cond);
2092 kumaneko 1052 }
2093     if (acl_type == TYPE_IP_NETWORK_ACL) {
2094 kumaneko 2002 struct ccs_ip_network_acl_record *acl
2095     = container_of(ptr, struct ccs_ip_network_acl_record,
2096     head);
2097     return ccs_print_network_acl(head, acl, cond);
2098 kumaneko 1052 }
2099     if (acl_type == TYPE_SIGNAL_ACL) {
2100 kumaneko 2002 struct ccs_signal_acl_record *acl
2101     = container_of(ptr, struct ccs_signal_acl_record, head);
2102     return ccs_print_signal_acl(head, acl, cond);
2103 kumaneko 1052 }
2104 kumaneko 2708 if (acl_type == TYPE_MOUNT_ACL) {
2105     struct ccs_mount_acl_record *acl
2106     = container_of(ptr, struct ccs_mount_acl_record, head);
2107     return ccs_print_mount_acl(head, acl, cond);
2108     }
2109     if (acl_type == TYPE_UMOUNT_ACL) {
2110     struct ccs_umount_acl_record *acl
2111     = container_of(ptr, struct ccs_umount_acl_record, head);
2112     return ccs_print_umount_acl(head, acl, cond);
2113     }
2114     if (acl_type == TYPE_CHROOT_ACL) {
2115     struct ccs_chroot_acl_record *acl
2116     = container_of(ptr, struct ccs_chroot_acl_record, head);
2117     return ccs_print_chroot_acl(head, acl, cond);
2118     }
2119     if (acl_type == TYPE_PIVOT_ROOT_ACL) {
2120     struct ccs_pivot_root_acl_record *acl
2121     = container_of(ptr, struct ccs_pivot_root_acl_record,
2122     head);
2123     return ccs_print_pivot_root_acl(head, acl, cond);
2124     }
2125 kumaneko 1120 /* Workaround for gcc 3.2.2's inline bug. */
2126     if (acl_type & ACL_DELETED)
2127     return true;
2128 kumaneko 1052 BUG(); /* This must not happen. */
2129     return false;
2130     }
2131    
2132     /**
2133 kumaneko 2002 * ccs_read_domain_policy - Read domain policy.
2134 kumaneko 1052 *
2135     * @head: Pointer to "struct ccs_io_buffer".
2136     *
2137     * Returns 0.
2138 kumaneko 2701 *
2139     * Caller holds srcu_read_lock(&ccs_ss).
2140 kumaneko 1052 */
2141 kumaneko 2002 static int ccs_read_domain_policy(struct ccs_io_buffer *head)
2142 kumaneko 1052 {
2143 kumaneko 2540 struct list_head *dpos;
2144     struct list_head *apos;
2145 kumaneko 1052 if (head->read_eof)
2146     return 0;
2147     if (head->read_step == 0)
2148     head->read_step = 1;
2149 kumaneko 2690 list_for_each_cookie(dpos, head->read_var1, &ccs_domain_list) {
2150 kumaneko 2282 struct ccs_domain_info *domain;
2151 kumaneko 1052 const char *quota_exceeded = "";
2152 kumaneko 1180 const char *transition_failed = "";
2153 kumaneko 1052 const char *ignore_global_allow_read = "";
2154     const char *ignore_global_allow_env = "";
2155 kumaneko 2540 domain = list_entry(dpos, struct ccs_domain_info, list);
2156 kumaneko 1052 if (head->read_step != 1)
2157     goto acl_loop;
2158 kumaneko 1609 if (domain->is_deleted && !head->read_single_domain)
2159     continue;
2160 kumaneko 1054 /* Print domainname and flags. */
2161 kumaneko 1052 if (domain->quota_warned)
2162     quota_exceeded = "quota_exceeded\n";
2163 kumaneko 2540 if (domain->domain_transition_failed)
2164 kumaneko 1180 transition_failed = "transition_failed\n";
2165 kumaneko 2540 if (domain->ignore_global_allow_read)
2166 kumaneko 1052 ignore_global_allow_read
2167     = KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
2168 kumaneko 2540 if (domain->ignore_global_allow_env)
2169 kumaneko 1052 ignore_global_allow_env
2170     = KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n";
2171 kumaneko 1609 if (!ccs_io_printf(head, "%s\n" KEYWORD_USE_PROFILE "%u\n"
2172     "%s%s%s%s\n", domain->domainname->name,
2173     domain->profile, quota_exceeded,
2174     transition_failed,
2175 kumaneko 1052 ignore_global_allow_read,
2176     ignore_global_allow_env))
2177     return 0;
2178 kumaneko 708 head->read_step = 2;
2179 kumaneko 2041 acl_loop:
2180 kumaneko 1052 if (head->read_step == 3)
2181     goto tail_mark;
2182 kumaneko 1054 /* Print ACL entries in the domain. */
2183 kumaneko 2690 list_for_each_cookie(apos, head->read_var2,
2184     &domain->acl_info_list) {
2185 kumaneko 2002 struct ccs_acl_info *ptr
2186 kumaneko 2540 = list_entry(apos, struct ccs_acl_info, list);
2187 kumaneko 2002 if (!ccs_print_entry(head, ptr))
2188 kumaneko 1052 return 0;
2189 kumaneko 111 }
2190 kumaneko 708 head->read_step = 3;
2191 kumaneko 2041 tail_mark:
2192 kumaneko 1052 if (!ccs_io_printf(head, "\n"))
2193     return 0;
2194 kumaneko 708 head->read_step = 1;
2195 kumaneko 1606 if (head->read_single_domain)
2196     break;
2197 kumaneko 111 }
2198 kumaneko 1006 head->read_eof = true;
2199 kumaneko 111 return 0;
2200     }
2201    
2202 kumaneko 1052 /**
2203 kumaneko 2002 * ccs_write_domain_profile - Assign profile for specified domain.
2204 kumaneko 1052 *
2205     * @head: Pointer to "struct ccs_io_buffer".
2206     *
2207     * Returns 0 on success, -EINVAL otherwise.
2208 kumaneko 2692 *
2209     * This is equivalent to doing
2210     *
2211     * ( echo "select " $domainname; echo "use_profile " $profile ) |
2212     * /usr/lib/ccs/loadpolicy -d
2213 kumaneko 2701 *
2214     * Caller holds srcu_read_lock(&ccs_ss).
2215 kumaneko 1052 */
2216 kumaneko 2002 static int ccs_write_domain_profile(struct ccs_io_buffer *head)
2217 kumaneko 461 {
2218     char *data = head->write_buf;
2219     char *cp = strchr(data, ' ');
2220 kumaneko 2690 struct ccs_domain_info *domain;
2221 kumaneko 461 unsigned int profile;
2222 kumaneko 1052 if (!cp)
2223     return -EINVAL;
2224 kumaneko 461 *cp = '\0';
2225     profile = simple_strtoul(data, NULL, 10);
2226 kumaneko 2540 if (profile >= MAX_PROFILES)
2227     return -EINVAL;
2228 kumaneko 2690 domain = ccs_find_domain(cp + 1);
2229     if (domain && (ccs_profile_ptr[profile] || !ccs_policy_loaded))
2230     domain->profile = (u8) profile;
2231 kumaneko 461 return 0;
2232     }
2233    
2234 kumaneko 1052 /**
2235 kumaneko 2002 * ccs_read_domain_profile - Read only domainname and profile.
2236 kumaneko 1052 *
2237     * @head: Pointer to "struct ccs_io_buffer".
2238     *
2239     * Returns list of profile number and domainname pairs.
2240 kumaneko 2692 *
2241     * This is equivalent to doing
2242     *
2243     * grep -A 1 '^<kernel>' /proc/ccs/domain_policy |
2244     * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
2245     * domainname = $0; } else if ( $1 == "use_profile" ) {
2246     * print $2 " " domainname; domainname = ""; } } ; '
2247 kumaneko 2701 *
2248     * Caller holds srcu_read_lock(&ccs_ss).
2249 kumaneko 1052 */
2250 kumaneko 2002 static int ccs_read_domain_profile(struct ccs_io_buffer *head)
2251 kumaneko 111 {
2252 kumaneko 2540 struct list_head *pos;
2253 kumaneko 1052 if (head->read_eof)
2254     return 0;
2255 kumaneko 2690 list_for_each_cookie(pos, head->read_var1, &ccs_domain_list) {
2256 kumaneko 2282 struct ccs_domain_info *domain;
2257 kumaneko 2540 domain = list_entry(pos, struct ccs_domain_info, list);
2258 kumaneko 1052 if (