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

Subversion リポジトリの参照

Annotation of /trunk/1.8.x/ccs-patch/security/ccsecurity/policy_io.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4073 - (hide annotations) (download) (as text)
Wed Oct 20 13:53:35 2010 UTC (13 years, 7 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 75344 byte(s)


<
1 kumaneko 2863 /*
2 kumaneko 2864 * security/ccsecurity/policy_io.c
3 kumaneko 2863 *
4 kumaneko 3441 * Copyright (C) 2005-2010 NTT DATA CORPORATION
5 kumaneko 2863 *
6 kumaneko 4068 * Version: 1.8.0-pre 2010/10/18
7 kumaneko 2863 *
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     #include "internal.h"
14    
15 kumaneko 3945 /* Profile version. Currently only 20100903 is defined. */
16 kumaneko 3158 static unsigned int ccs_profile_version;
17    
18 kumaneko 2958 /* Profile table. Memory is allocated as needed. */
19     static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES];
20    
21 kumaneko 4063 /* String table for operation mode. */
22 kumaneko 3968 const char * const ccs_mode[CCS_CONFIG_MAX_MODE] = {
23     [CCS_CONFIG_DISABLED] = "disabled",
24     [CCS_CONFIG_LEARNING] = "learning",
25 kumaneko 3748 [CCS_CONFIG_PERMISSIVE] = "permissive",
26 kumaneko 3968 [CCS_CONFIG_ENFORCING] = "enforcing"
27 kumaneko 2863 };
28 kumaneko 2915
29 kumaneko 4063 /* String table for /proc/ccs/profile interface. */
30 kumaneko 3968 const char * const ccs_mac_keywords[CCS_MAX_MAC_INDEX
31     + CCS_MAX_MAC_CATEGORY_INDEX] = {
32 kumaneko 4063 /* CONFIG::file group */
33 kumaneko 3968 [CCS_MAC_FILE_EXECUTE] = "execute",
34     [CCS_MAC_FILE_OPEN] = "open",
35     [CCS_MAC_FILE_CREATE] = "create",
36     [CCS_MAC_FILE_UNLINK] = "unlink",
37     [CCS_MAC_FILE_MKDIR] = "mkdir",
38     [CCS_MAC_FILE_RMDIR] = "rmdir",
39     [CCS_MAC_FILE_MKFIFO] = "mkfifo",
40     [CCS_MAC_FILE_MKSOCK] = "mksock",
41     [CCS_MAC_FILE_TRUNCATE] = "truncate",
42     [CCS_MAC_FILE_SYMLINK] = "symlink",
43     [CCS_MAC_FILE_MKBLOCK] = "mkblock",
44     [CCS_MAC_FILE_MKCHAR] = "mkchar",
45     [CCS_MAC_FILE_LINK] = "link",
46     [CCS_MAC_FILE_RENAME] = "rename",
47     [CCS_MAC_FILE_CHMOD] = "chmod",
48 kumaneko 4049 [CCS_MAC_FILE_CHOWN] = "chown",
49 kumaneko 3968 [CCS_MAC_FILE_CHGRP] = "chgrp",
50     [CCS_MAC_FILE_IOCTL] = "ioctl",
51     [CCS_MAC_FILE_CHROOT] = "chroot",
52     [CCS_MAC_FILE_MOUNT] = "mount",
53     [CCS_MAC_FILE_UMOUNT] = "unmount",
54     [CCS_MAC_FILE_PIVOT_ROOT] = "pivot_root",
55 kumaneko 4063 /* CONFIG::misc group */
56 kumaneko 3968 [CCS_MAC_ENVIRON] = "env",
57 kumaneko 4063 /* CONFIG::network group */
58 kumaneko 3968 [CCS_MAC_NETWORK_INET_STREAM_BIND] = "inet_stream_bind",
59     [CCS_MAC_NETWORK_INET_STREAM_LISTEN] = "inet_stream_listen",
60     [CCS_MAC_NETWORK_INET_STREAM_CONNECT] = "inet_stream_connect",
61     [CCS_MAC_NETWORK_INET_STREAM_ACCEPT] = "inet_stream_accept",
62     [CCS_MAC_NETWORK_INET_DGRAM_BIND] = "inet_dgram_bind",
63     [CCS_MAC_NETWORK_INET_DGRAM_SEND] = "inet_dgram_send",
64     [CCS_MAC_NETWORK_INET_DGRAM_RECV] = "inet_dgram_recv",
65     [CCS_MAC_NETWORK_INET_RAW_BIND] = "inet_raw_bind",
66     [CCS_MAC_NETWORK_INET_RAW_SEND] = "inet_raw_send",
67     [CCS_MAC_NETWORK_INET_RAW_RECV] = "inet_raw_recv",
68     [CCS_MAC_NETWORK_UNIX_STREAM_BIND] = "unix_stream_bind",
69     [CCS_MAC_NETWORK_UNIX_STREAM_LISTEN] = "unix_stream_listen",
70     [CCS_MAC_NETWORK_UNIX_STREAM_CONNECT] = "unix_stream_connect",
71     [CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT] = "unix_stream_accept",
72     [CCS_MAC_NETWORK_UNIX_DGRAM_BIND] = "unix_dgram_bind",
73     [CCS_MAC_NETWORK_UNIX_DGRAM_SEND] = "unix_dgram_send",
74     [CCS_MAC_NETWORK_UNIX_DGRAM_RECV] = "unix_dgram_recv",
75     [CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND] = "unix_seqpacket_bind",
76     [CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] = "unix_seqpacket_listen",
77     [CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = "unix_seqpacket_connect",
78     [CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT] = "unix_seqpacket_accept",
79 kumaneko 4063 /* CONFIG::ipc group */
80 kumaneko 3968 [CCS_MAC_SIGNAL] = "signal",
81 kumaneko 4063 /* CONFIG::capability group */
82 kumaneko 3968 [CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET] = "use_route",
83     [CCS_MAC_CAPABILITY_USE_PACKET_SOCKET] = "use_packet",
84     [CCS_MAC_CAPABILITY_SYS_REBOOT] = "SYS_REBOOT",
85     [CCS_MAC_CAPABILITY_SYS_VHANGUP] = "SYS_VHANGUP",
86     [CCS_MAC_CAPABILITY_SYS_SETTIME] = "SYS_TIME",
87     [CCS_MAC_CAPABILITY_SYS_NICE] = "SYS_NICE",
88     [CCS_MAC_CAPABILITY_SYS_SETHOSTNAME] = "SYS_SETHOSTNAME",
89     [CCS_MAC_CAPABILITY_USE_KERNEL_MODULE] = "use_kernel_module",
90     [CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD] = "SYS_KEXEC_LOAD",
91     [CCS_MAC_CAPABILITY_SYS_PTRACE] = "SYS_PTRACE",
92 kumaneko 4063 /* CONFIG group */
93 kumaneko 3968 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_FILE] = "file",
94     [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_NETWORK] = "network",
95     [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_MISC] = "misc",
96     [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_IPC] = "ipc",
97     [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_CAPABILITY] = "capability",
98 kumaneko 2915 };
99    
100 kumaneko 4063 /* String table for path operation. */
101 kumaneko 3968 const char * const ccs_path_keyword[CCS_MAX_PATH_OPERATION] = {
102     [CCS_TYPE_EXECUTE] = "execute",
103     [CCS_TYPE_READ] = "read",
104     [CCS_TYPE_WRITE] = "write",
105     [CCS_TYPE_APPEND] = "append",
106     [CCS_TYPE_UNLINK] = "unlink",
107     [CCS_TYPE_RMDIR] = "rmdir",
108     [CCS_TYPE_TRUNCATE] = "truncate",
109     [CCS_TYPE_SYMLINK] = "symlink",
110     [CCS_TYPE_CHROOT] = "chroot",
111     [CCS_TYPE_UMOUNT] = "unmount",
112     };
113    
114 kumaneko 4063 /* String table for categories. */
115 kumaneko 3968 static const char * const ccs_category_keywords[CCS_MAX_MAC_CATEGORY_INDEX] = {
116     [CCS_MAC_CATEGORY_FILE] = "file",
117     [CCS_MAC_CATEGORY_NETWORK] = "network",
118     [CCS_MAC_CATEGORY_MISC] = "misc",
119     [CCS_MAC_CATEGORY_IPC] = "ipc",
120     [CCS_MAC_CATEGORY_CAPABILITY] = "capability",
121     };
122    
123 kumaneko 4063 /* String table for conditions. */
124 kumaneko 3968 const char * const ccs_condition_keyword[CCS_MAX_CONDITION_KEYWORD] = {
125     [CCS_TASK_UID] = "task.uid",
126     [CCS_TASK_EUID] = "task.euid",
127     [CCS_TASK_SUID] = "task.suid",
128     [CCS_TASK_FSUID] = "task.fsuid",
129     [CCS_TASK_GID] = "task.gid",
130     [CCS_TASK_EGID] = "task.egid",
131     [CCS_TASK_SGID] = "task.sgid",
132     [CCS_TASK_FSGID] = "task.fsgid",
133     [CCS_TASK_PID] = "task.pid",
134     [CCS_TASK_PPID] = "task.ppid",
135     [CCS_EXEC_ARGC] = "exec.argc",
136     [CCS_EXEC_ENVC] = "exec.envc",
137     [CCS_TYPE_IS_SOCKET] = "socket",
138     [CCS_TYPE_IS_SYMLINK] = "symlink",
139     [CCS_TYPE_IS_FILE] = "file",
140     [CCS_TYPE_IS_BLOCK_DEV] = "block",
141     [CCS_TYPE_IS_DIRECTORY] = "directory",
142     [CCS_TYPE_IS_CHAR_DEV] = "char",
143     [CCS_TYPE_IS_FIFO] = "fifo",
144     [CCS_MODE_SETUID] = "setuid",
145     [CCS_MODE_SETGID] = "setgid",
146     [CCS_MODE_STICKY] = "sticky",
147     [CCS_MODE_OWNER_READ] = "owner_read",
148     [CCS_MODE_OWNER_WRITE] = "owner_write",
149     [CCS_MODE_OWNER_EXECUTE] = "owner_execute",
150     [CCS_MODE_GROUP_READ] = "group_read",
151     [CCS_MODE_GROUP_WRITE] = "group_write",
152     [CCS_MODE_GROUP_EXECUTE] = "group_execute",
153     [CCS_MODE_OTHERS_READ] = "others_read",
154     [CCS_MODE_OTHERS_WRITE] = "others_write",
155     [CCS_MODE_OTHERS_EXECUTE] = "others_execute",
156     [CCS_TASK_TYPE] = "task.type",
157     [CCS_TASK_EXECUTE_HANDLER] = "execute_handler",
158     [CCS_EXEC_REALPATH] = "exec.realpath",
159     [CCS_SYMLINK_TARGET] = "symlink.target",
160     [CCS_PATH1_UID] = "path1.uid",
161     [CCS_PATH1_GID] = "path1.gid",
162     [CCS_PATH1_INO] = "path1.ino",
163     [CCS_PATH1_MAJOR] = "path1.major",
164     [CCS_PATH1_MINOR] = "path1.minor",
165     [CCS_PATH1_PERM] = "path1.perm",
166     [CCS_PATH1_TYPE] = "path1.type",
167     [CCS_PATH1_DEV_MAJOR] = "path1.dev_major",
168     [CCS_PATH1_DEV_MINOR] = "path1.dev_minor",
169     [CCS_PATH2_UID] = "path2.uid",
170     [CCS_PATH2_GID] = "path2.gid",
171     [CCS_PATH2_INO] = "path2.ino",
172     [CCS_PATH2_MAJOR] = "path2.major",
173     [CCS_PATH2_MINOR] = "path2.minor",
174     [CCS_PATH2_PERM] = "path2.perm",
175     [CCS_PATH2_TYPE] = "path2.type",
176     [CCS_PATH2_DEV_MAJOR] = "path2.dev_major",
177     [CCS_PATH2_DEV_MINOR] = "path2.dev_minor",
178     [CCS_PATH1_PARENT_UID] = "path1.parent.uid",
179     [CCS_PATH1_PARENT_GID] = "path1.parent.gid",
180     [CCS_PATH1_PARENT_INO] = "path1.parent.ino",
181     [CCS_PATH1_PARENT_PERM] = "path1.parent.perm",
182     [CCS_PATH2_PARENT_UID] = "path2.parent.uid",
183     [CCS_PATH2_PARENT_GID] = "path2.parent.gid",
184     [CCS_PATH2_PARENT_INO] = "path2.parent.ino",
185     [CCS_PATH2_PARENT_PERM] = "path2.parent.perm",
186     };
187    
188 kumaneko 4063 /* String table for PREFERENCE keyword. */
189 kumaneko 4049 static const char * const ccs_pref_keywords[CCS_MAX_PREF] = {
190     [CCS_PREF_MAX_GRANT_LOG] = "max_grant_log",
191     [CCS_PREF_MAX_REJECT_LOG] = "max_reject_log",
192     [CCS_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry",
193     [CCS_PREF_ENFORCING_PENALTY] = "enforcing_penalty",
194     };
195    
196 kumaneko 2863 /* Permit policy management by non-root user? */
197     static bool ccs_manage_by_non_root;
198    
199     /**
200 kumaneko 2958 * ccs_yesno - Return "yes" or "no".
201 kumaneko 2863 *
202 kumaneko 2958 * @value: Bool value.
203 kumaneko 4063 *
204     * Returns "yes" if @value is not 0, "no" otherwise.
205 kumaneko 2863 */
206 kumaneko 2958 static const char *ccs_yesno(const unsigned int value)
207 kumaneko 2863 {
208 kumaneko 2958 return value ? "yes" : "no";
209 kumaneko 2863 }
210    
211 kumaneko 4063 /* Prototype fpr ccs_addprintf(). */
212 kumaneko 3780 static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
213 kumaneko 4063 __attribute__ ((format(printf, 3, 4)));
214 kumaneko 4049
215 kumaneko 4063 /**
216     * ccs_addprintf - snprint()-like-strncat().
217     *
218     * @buffer: Buffer to write to. Must be '\0'-terminated.
219     * @len: Size of @buffer.
220     * @fmt: The printf()'s format string, followed by parameters.
221     *
222     * Returns nothing.
223     */
224 kumaneko 4049 static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
225 kumaneko 3780 {
226     va_list args;
227     const int pos = strlen(buffer);
228     va_start(args, fmt);
229     vsnprintf(buffer + pos, len - pos - 1, fmt, args);
230     va_end(args);
231     }
232    
233 kumaneko 2863 /**
234 kumaneko 3780 * ccs_flush - Flush queued string to userspace's buffer.
235 kumaneko 2863 *
236 kumaneko 4063 * @head: Pointer to "struct ccs_io_buffer".
237 kumaneko 2863 *
238 kumaneko 3780 * Returns true if all data was flushed, false otherwise.
239     */
240     static bool ccs_flush(struct ccs_io_buffer *head)
241     {
242     while (head->r.w_pos) {
243     const char *w = head->r.w[0];
244     int len = strlen(w);
245     if (len) {
246     if (len > head->read_user_buf_avail)
247     len = head->read_user_buf_avail;
248     if (!len)
249     return false;
250     if (copy_to_user(head->read_user_buf, w, len))
251     return false;
252     head->read_user_buf_avail -= len;
253     head->read_user_buf += len;
254     w += len;
255     }
256     if (*w) {
257     head->r.w[0] = w;
258     return false;
259     }
260     /* Add '\0' for audit logs and query. */
261     if (head->poll) {
262     if (!head->read_user_buf_avail ||
263     copy_to_user(head->read_user_buf, "", 1))
264     return false;
265     head->read_user_buf_avail--;
266     head->read_user_buf++;
267     }
268     head->r.w_pos--;
269     for (len = 0; len < head->r.w_pos; len++)
270     head->r.w[len] = head->r.w[len + 1];
271     }
272     head->r.avail = 0;
273     return true;
274     }
275    
276     /**
277     * ccs_set_string - Queue string to "struct ccs_io_buffer" structure.
278 kumaneko 2863 *
279 kumaneko 3780 * @head: Pointer to "struct ccs_io_buffer".
280     * @string: String to print.
281     *
282     * Note that @string has to be kept valid until @head is kfree()d.
283     * This means that char[] allocated on stack memory cannot be passed to
284     * this function. Use ccs_io_printf() for char[] allocated on stack memory.
285 kumaneko 4063 *
286     * Returns nothing.
287 kumaneko 2863 */
288 kumaneko 3780 static void ccs_set_string(struct ccs_io_buffer *head, const char *string)
289 kumaneko 2863 {
290 kumaneko 3780 if (head->r.w_pos < CCS_MAX_IO_READ_QUEUE) {
291     head->r.w[head->r.w_pos++] = string;
292     ccs_flush(head);
293     } else
294 kumaneko 3829 printk(KERN_WARNING "Too many words in a line.\n");
295 kumaneko 3780 }
296    
297     /**
298     * ccs_io_printf - printf() to "struct ccs_io_buffer" structure.
299     *
300     * @head: Pointer to "struct ccs_io_buffer".
301     * @fmt: The printf()'s format string, followed by parameters.
302 kumaneko 4063 *
303     * Returns nothing.
304 kumaneko 3780 */
305     void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
306     {
307 kumaneko 2863 va_list args;
308     int len;
309 kumaneko 3780 int pos = head->r.avail;
310 kumaneko 2863 int size = head->readbuf_size - pos;
311     if (size <= 0)
312 kumaneko 3780 return;
313 kumaneko 2863 va_start(args, fmt);
314 kumaneko 3780 len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1;
315 kumaneko 2863 va_end(args);
316 kumaneko 3780 if (pos + len >= head->readbuf_size) {
317 kumaneko 3829 printk(KERN_WARNING "Too many words in a line.\n");
318 kumaneko 3780 return;
319     }
320     head->r.avail += len;
321     ccs_set_string(head, head->read_buf + pos);
322 kumaneko 2863 }
323    
324 kumaneko 4063 /**
325     * ccs_set_space - Put a space to "struct ccs_io_buffer" structure.
326     *
327     * @head: Pointer to "struct ccs_io_buffer".
328     *
329     * Returns nothing.
330     */
331 kumaneko 3780 static void ccs_set_space(struct ccs_io_buffer *head)
332     {
333     ccs_set_string(head, " ");
334     }
335    
336 kumaneko 4063 /**
337     * ccs_set_lf - Put a line feed to "struct ccs_io_buffer" structure.
338     *
339     * @head: Pointer to "struct ccs_io_buffer".
340     *
341     * Returns nothing.
342     */
343 kumaneko 3780 static bool ccs_set_lf(struct ccs_io_buffer *head)
344     {
345     ccs_set_string(head, "\n");
346     return !head->r.w_pos;
347     }
348    
349 kumaneko 2863 /**
350 kumaneko 3694 * ccs_assign_profile - Create a new profile.
351 kumaneko 2863 *
352     * @profile: Profile number to create.
353     *
354     * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
355     */
356 kumaneko 3694 static struct ccs_profile *ccs_assign_profile(const unsigned int profile)
357 kumaneko 2863 {
358     struct ccs_profile *ptr;
359     struct ccs_profile *entry;
360 kumaneko 2892 if (profile >= CCS_MAX_PROFILES)
361 kumaneko 2863 return NULL;
362     ptr = ccs_profile_ptr[profile];
363     if (ptr)
364     return ptr;
365 kumaneko 3512 entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
366 kumaneko 3534 if (mutex_lock_interruptible(&ccs_policy_lock))
367     goto out;
368 kumaneko 2863 ptr = ccs_profile_ptr[profile];
369     if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
370     ptr = entry;
371 kumaneko 2958 ptr->default_config = CCS_CONFIG_DISABLED |
372     CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;
373     memset(ptr->config, CCS_CONFIG_USE_DEFAULT,
374 kumaneko 2943 sizeof(ptr->config));
375 kumaneko 4049 ptr->pref[CCS_PREF_MAX_GRANT_LOG] =
376     CONFIG_CCSECURITY_MAX_GRANT_LOG;
377     ptr->pref[CCS_PREF_MAX_REJECT_LOG] =
378     CONFIG_CCSECURITY_MAX_REJECT_LOG;
379     ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =
380     CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;
381 kumaneko 2863 mb(); /* Avoid out-of-order execution. */
382     ccs_profile_ptr[profile] = ptr;
383     entry = NULL;
384     }
385     mutex_unlock(&ccs_policy_lock);
386 kumaneko 4049 out:
387 kumaneko 2863 kfree(entry);
388     return ptr;
389     }
390    
391     /**
392 kumaneko 2991 * ccs_check_profile - Check all profiles currently assigned to domains are defined.
393 kumaneko 4063 *
394     * Returns nothing.
395 kumaneko 2991 */
396 kumaneko 3502 static void ccs_check_profile(void)
397 kumaneko 2991 {
398     struct ccs_domain_info *domain;
399 kumaneko 3535 const int idx = ccs_read_lock();
400 kumaneko 2991 ccs_policy_loaded = true;
401 kumaneko 4049 list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
402 kumaneko 2991 const u8 profile = domain->profile;
403     if (ccs_profile_ptr[profile])
404     continue;
405 kumaneko 4053 printk(KERN_ERR "You need to define profile %u before using it.\n",
406     profile);
407     printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/1.8/ "
408     "for more information.\n");
409 kumaneko 2991 panic("Profile %u (used by '%s') not defined.\n",
410     profile, domain->domainname->name);
411     }
412 kumaneko 3535 ccs_read_unlock(idx);
413 kumaneko 4053 if (ccs_profile_version != 20100903) {
414     printk(KERN_ERR "You need to install userland programs for "
415     "TOMOYO 1.8 and initialize policy configuration.\n");
416     printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/1.8/ "
417     "for more information.\n");
418 kumaneko 3158 panic("Profile version %u is not supported.\n",
419     ccs_profile_version);
420 kumaneko 4053 }
421 kumaneko 4068 printk(KERN_INFO "CCSecurity: 1.8.0-pre 2010/10/18\n");
422 kumaneko 3502 printk(KERN_INFO "Mandatory Access Control activated.\n");
423 kumaneko 2991 }
424    
425     /**
426 kumaneko 2958 * ccs_profile - Find a profile.
427     *
428     * @profile: Profile number to find.
429     *
430 kumaneko 2991 * Returns pointer to "struct ccs_profile".
431 kumaneko 2958 */
432     struct ccs_profile *ccs_profile(const u8 profile)
433     {
434 kumaneko 3961 static struct ccs_profile ccs_null_profile;
435 kumaneko 2974 struct ccs_profile *ptr = ccs_profile_ptr[profile];
436 kumaneko 3961 if (!ptr)
437     ptr = &ccs_null_profile;
438 kumaneko 2974 return ptr;
439 kumaneko 2958 }
440    
441 kumaneko 4063 /**
442     * ccs_find_yesno - Find values for specified keyword.
443     *
444     * @string: String to check.
445     * @find: Name of keyword.
446     *
447     * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise.
448     */
449 kumaneko 3747 static s8 ccs_find_yesno(const char *string, const char *find)
450 kumaneko 2863 {
451 kumaneko 3747 const char *cp = strstr(string, find);
452     if (cp) {
453     cp += strlen(find);
454 kumaneko 3758 if (!strncmp(cp, "=yes", 4))
455 kumaneko 3747 return 1;
456 kumaneko 3758 else if (!strncmp(cp, "=no", 3))
457 kumaneko 3747 return 0;
458 kumaneko 2863 }
459 kumaneko 3747 return -1;
460     }
461    
462 kumaneko 4063 /**
463     * ccs_set_uint - Set value for specified preference.
464     *
465     * @i: Pointer to "unsigned int".
466     * @string: String to check.
467     * @find: Name of keyword.
468     *
469     * Returns nothing.
470     */
471 kumaneko 3747 static void ccs_set_uint(unsigned int *i, const char *string, const char *find)
472     {
473     const char *cp = strstr(string, find);
474     if (cp)
475     sscanf(cp + strlen(find), "=%u", i);
476     }
477    
478 kumaneko 4063 /**
479     * ccs_set_mode - Set mode for specified profile.
480     *
481     * @name: Name of functionality.
482     * @value: Mode for @name.
483     * @profile: Pointer to "struct ccs_profile".
484     *
485     * Returns 0 on success, negative value otherwise.
486     */
487 kumaneko 3870 static int ccs_set_mode(char *name, const char *value,
488 kumaneko 3758 struct ccs_profile *profile)
489 kumaneko 3747 {
490     u8 i;
491     u8 config;
492 kumaneko 3758 if (!strcmp(name, "CONFIG")) {
493 kumaneko 3968 i = CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX;
494 kumaneko 2958 config = profile->default_config;
495 kumaneko 3758 } else if (ccs_str_starts(&name, "CONFIG::")) {
496 kumaneko 2958 config = 0;
497 kumaneko 3968 for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX;
498     i++) {
499     int len = 0;
500     if (i < CCS_MAX_MAC_INDEX) {
501     const u8 c = ccs_index2category[i];
502 kumaneko 4049 const char *category =
503     ccs_category_keywords[c];
504 kumaneko 3968 len = strlen(category);
505     if (strncmp(name, category, len) ||
506     name[len++] != ':' || name[len++] != ':')
507     continue;
508     }
509     if (strcmp(name + len, ccs_mac_keywords[i]))
510 kumaneko 2943 continue;
511 kumaneko 2958 config = profile->config[i];
512 kumaneko 2943 break;
513     }
514 kumaneko 3968 if (i == CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)
515 kumaneko 2958 return -EINVAL;
516     } else {
517     return -EINVAL;
518     }
519 kumaneko 3870 if (strstr(value, "use_default")) {
520 kumaneko 2958 config = CCS_CONFIG_USE_DEFAULT;
521     } else {
522 kumaneko 3747 u8 mode;
523 kumaneko 3758 for (mode = 0; mode < CCS_CONFIG_MAX_MODE; mode++)
524     if (strstr(value, ccs_mode[mode]))
525 kumaneko 2958 /*
526     * Update lower 3 bits in order to distinguish
527     * 'config' from 'CCS_CONFIG_USE_DEAFULT'.
528     */
529     config = (config & ~7) | mode;
530 kumaneko 3870 if (config != CCS_CONFIG_USE_DEFAULT) {
531 kumaneko 3758 switch (ccs_find_yesno(value, "grant_log")) {
532 kumaneko 3747 case 1:
533 kumaneko 2958 config |= CCS_CONFIG_WANT_GRANT_LOG;
534 kumaneko 3747 break;
535     case 0:
536 kumaneko 2958 config &= ~CCS_CONFIG_WANT_GRANT_LOG;
537 kumaneko 3747 break;
538     }
539 kumaneko 3758 switch (ccs_find_yesno(value, "reject_log")) {
540 kumaneko 3747 case 1:
541 kumaneko 2958 config |= CCS_CONFIG_WANT_REJECT_LOG;
542 kumaneko 3747 break;
543     case 0:
544 kumaneko 2958 config &= ~CCS_CONFIG_WANT_REJECT_LOG;
545 kumaneko 3747 break;
546     }
547 kumaneko 3968 }
548 kumaneko 2958 }
549 kumaneko 3968 if (i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)
550 kumaneko 2958 profile->config[i] = config;
551     else if (config != CCS_CONFIG_USE_DEFAULT)
552     profile->default_config = config;
553 kumaneko 2943 return 0;
554 kumaneko 2863 }
555    
556 kumaneko 3747 /**
557     * ccs_write_profile - Write profile table.
558     *
559     * @head: Pointer to "struct ccs_io_buffer".
560     *
561     * Returns 0 on success, negative value otherwise.
562     */
563     static int ccs_write_profile(struct ccs_io_buffer *head)
564     {
565     char *data = head->write_buf;
566 kumaneko 3781 unsigned int i;
567 kumaneko 3747 char *cp;
568     struct ccs_profile *profile;
569     if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1)
570     return 0;
571     i = simple_strtoul(data, &cp, 10);
572 kumaneko 3870 if (*cp != '-')
573     return -EINVAL;
574     data = cp + 1;
575     profile = ccs_assign_profile(i);
576     if (!profile)
577     return -EINVAL;
578 kumaneko 3747 cp = strchr(data, '=');
579     if (!cp)
580     return -EINVAL;
581     *cp++ = '\0';
582     if (!strcmp(data, "COMMENT")) {
583     const struct ccs_path_info *old_comment = profile->comment;
584     profile->comment = ccs_get_name(cp);
585     ccs_put_name(old_comment);
586     return 0;
587     }
588 kumaneko 4049 if (!strcmp(data, "PREFERENCE")) {
589     for (i = 0; i < CCS_MAX_PREF; i++)
590     ccs_set_uint(&profile->pref[i], cp,
591     ccs_pref_keywords[i]);
592     return 0;
593     }
594 kumaneko 3870 return ccs_set_mode(data, cp, profile);
595 kumaneko 3747 }
596    
597 kumaneko 4063 /**
598     * ccs_print_config - Print mode for specified functionality.
599     *
600     * @head: Pointer to "struct ccs_io_buffer".
601     * @config: Mode for that functionality.
602     *
603     * Returns nothing.
604     *
605     * Caller prints functionality's name.
606     */
607 kumaneko 3780 static void ccs_print_config(struct ccs_io_buffer *head, const u8 config)
608     {
609 kumaneko 4049 ccs_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n",
610     ccs_mode[config & 3],
611 kumaneko 3780 ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG),
612     ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG));
613     }
614    
615 kumaneko 2863 /**
616     * ccs_read_profile - Read profile table.
617     *
618     * @head: Pointer to "struct ccs_io_buffer".
619     */
620 kumaneko 2943 static void ccs_read_profile(struct ccs_io_buffer *head)
621 kumaneko 2863 {
622 kumaneko 3780 u8 index;
623     const struct ccs_profile *profile;
624 kumaneko 4049 next:
625 kumaneko 3780 index = head->r.index;
626     profile = ccs_profile_ptr[index];
627     switch (head->r.step) {
628     case 0:
629 kumaneko 3945 ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20100903");
630 kumaneko 3780 head->r.step++;
631     break;
632     case 1:
633     for ( ; head->r.index < CCS_MAX_PROFILES;
634     head->r.index++)
635     if (ccs_profile_ptr[head->r.index])
636     break;
637     if (head->r.index == CCS_MAX_PROFILES)
638     return;
639     head->r.step++;
640     break;
641     case 2:
642     {
643 kumaneko 4049 u8 i;
644 kumaneko 3780 const struct ccs_path_info *comment = profile->comment;
645     ccs_io_printf(head, "%u-COMMENT=", index);
646     ccs_set_string(head, comment ? comment->name : "");
647     ccs_set_lf(head);
648 kumaneko 4049 ccs_io_printf(head, "%u-PREFERENCE={ ", index);
649     for (i = 0; i < CCS_MAX_PREF; i++)
650     ccs_io_printf(head, "%s=%u ",
651     ccs_pref_keywords[i],
652     profile->pref[i]);
653     ccs_set_string(head, " }\n");
654 kumaneko 3780 head->r.step++;
655     }
656     break;
657     case 3:
658     {
659     ccs_io_printf(head, "%u-%s", index, "CONFIG");
660     ccs_print_config(head, profile->default_config);
661     head->r.bit = 0;
662     head->r.step++;
663     }
664     break;
665     case 4:
666     for ( ; head->r.bit < CCS_MAX_MAC_INDEX
667     + CCS_MAX_MAC_CATEGORY_INDEX; head->r.bit++) {
668     const u8 i = head->r.bit;
669     const u8 config = profile->config[i];
670 kumaneko 2958 if (config == CCS_CONFIG_USE_DEFAULT)
671     continue;
672 kumaneko 3968 if (i < CCS_MAX_MAC_INDEX)
673     ccs_io_printf(head, "%u-CONFIG::%s::%s", index,
674     ccs_category_keywords
675     [ccs_index2category[i]],
676     ccs_mac_keywords[i]);
677     else
678     ccs_io_printf(head, "%u-CONFIG::%s", index,
679     ccs_mac_keywords[i]);
680 kumaneko 3780 ccs_print_config(head, config);
681     head->r.bit++;
682     break;
683 kumaneko 2908 }
684 kumaneko 3780 if (head->r.bit == CCS_MAX_MAC_INDEX
685     + CCS_MAX_MAC_CATEGORY_INDEX) {
686     head->r.index++;
687     head->r.step = 1;
688     }
689 kumaneko 2958 break;
690 kumaneko 2863 }
691 kumaneko 3780 if (ccs_flush(head))
692     goto next;
693 kumaneko 2863 }
694    
695 kumaneko 4057 /**
696     * ccs_same_manager - Check for duplicated "struct ccs_manager" entry.
697     *
698     * @a: Pointer to "struct ccs_acl_head".
699     * @b: Pointer to "struct ccs_acl_head".
700     *
701     * Returns true if @a and @b are duplicated, false otherwise.
702     */
703 kumaneko 3781 static bool ccs_same_manager(const struct ccs_acl_head *a,
704     const struct ccs_acl_head *b)
705 kumaneko 3689 {
706 kumaneko 3693 return container_of(a, struct ccs_manager, head)->manager
707     == container_of(b, struct ccs_manager, head)->manager;
708 kumaneko 3689 }
709 kumaneko 2863
710     /**
711     * ccs_update_manager_entry - Add a manager entry.
712     *
713     * @manager: The path to manager or the domainnamme.
714     * @is_delete: True if it is a delete request.
715     *
716     * Returns 0 on success, negative value otherwise.
717     */
718     static int ccs_update_manager_entry(const char *manager, const bool is_delete)
719     {
720 kumaneko 3693 struct ccs_manager e = { };
721 kumaneko 2863 int error = is_delete ? -ENOENT : -ENOMEM;
722 kumaneko 3693 if (ccs_domain_def(manager)) {
723     if (!ccs_correct_domain(manager))
724 kumaneko 2863 return -EINVAL;
725 kumaneko 2900 e.is_domain = true;
726 kumaneko 2863 } else {
727 kumaneko 3707 if (!ccs_correct_path(manager))
728 kumaneko 2863 return -EINVAL;
729     }
730 kumaneko 2900 e.manager = ccs_get_name(manager);
731     if (!e.manager)
732 kumaneko 3689 return error;
733     error = ccs_update_policy(&e.head, sizeof(e), is_delete,
734 kumaneko 3754 &ccs_policy_list[CCS_ID_MANAGER],
735 kumaneko 3781 ccs_same_manager);
736 kumaneko 2900 ccs_put_name(e.manager);
737 kumaneko 2863 return error;
738     }
739    
740     /**
741 kumaneko 3693 * ccs_write_manager - Write manager policy.
742 kumaneko 2863 *
743     * @head: Pointer to "struct ccs_io_buffer".
744     *
745     * Returns 0 on success, negative value otherwise.
746     */
747 kumaneko 3693 static int ccs_write_manager(struct ccs_io_buffer *head)
748 kumaneko 2863 {
749     char *data = head->write_buf;
750 kumaneko 3968 bool is_delete = ccs_str_starts(&data, "delete ");
751 kumaneko 2863 if (!strcmp(data, "manage_by_non_root")) {
752     ccs_manage_by_non_root = !is_delete;
753     return 0;
754     }
755     return ccs_update_manager_entry(data, is_delete);
756     }
757    
758     /**
759 kumaneko 3693 * ccs_read_manager - Read manager policy.
760 kumaneko 2863 *
761     * @head: Pointer to "struct ccs_io_buffer".
762     *
763     * Caller holds ccs_read_lock().
764     */
765 kumaneko 3693 static void ccs_read_manager(struct ccs_io_buffer *head)
766 kumaneko 2863 {
767 kumaneko 3780 if (head->r.eof)
768 kumaneko 2943 return;
769 kumaneko 3780 list_for_each_cookie(head->r.acl, &ccs_policy_list[CCS_ID_MANAGER]) {
770     struct ccs_manager *ptr =
771     list_entry(head->r.acl, typeof(*ptr), head.list);
772 kumaneko 3689 if (ptr->head.is_deleted)
773 kumaneko 2863 continue;
774 kumaneko 3780 if (!ccs_flush(head))
775 kumaneko 2943 return;
776 kumaneko 3780 ccs_set_string(head, ptr->manager->name);
777     ccs_set_lf(head);
778 kumaneko 2863 }
779 kumaneko 3780 head->r.eof = true;
780 kumaneko 2863 }
781    
782     /**
783 kumaneko 3693 * ccs_manager - Check whether the current process is a policy manager.
784 kumaneko 2863 *
785     * Returns true if the current process is permitted to modify policy
786     * via /proc/ccs/ interface.
787     *
788     * Caller holds ccs_read_lock().
789     */
790 kumaneko 3693 static bool ccs_manager(void)
791 kumaneko 2863 {
792 kumaneko 3693 struct ccs_manager *ptr;
793 kumaneko 2863 const char *exe;
794 kumaneko 4049 struct ccs_security *task = ccs_current_security();
795 kumaneko 2863 const struct ccs_path_info *domainname
796     = ccs_current_domain()->domainname;
797     bool found = false;
798     if (!ccs_policy_loaded)
799     return true;
800 kumaneko 3693 if (task->ccs_flags & CCS_TASK_IS_MANAGER)
801 kumaneko 2863 return true;
802     if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
803     return false;
804     exe = ccs_get_exe();
805 kumaneko 4049 list_for_each_entry_srcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],
806     head.list, &ccs_ss) {
807 kumaneko 3697 if (ptr->head.is_deleted)
808     continue;
809     if (ptr->is_domain) {
810     if (ccs_pathcmp(domainname, ptr->manager))
811     continue;
812     } else {
813     if (!exe || strcmp(exe, ptr->manager->name))
814     continue;
815 kumaneko 2863 }
816 kumaneko 3697 /* Set manager flag. */
817     task->ccs_flags |= CCS_TASK_IS_MANAGER;
818     found = true;
819     break;
820 kumaneko 2863 }
821     if (!found) { /* Reduce error messages. */
822     static pid_t ccs_last_pid;
823     const pid_t pid = current->pid;
824     if (ccs_last_pid != pid) {
825     printk(KERN_WARNING "%s ( %s ) is not permitted to "
826     "update policies.\n", domainname->name, exe);
827     ccs_last_pid = pid;
828     }
829     }
830     kfree(exe);
831     return found;
832     }
833    
834     /**
835 kumaneko 3693 * ccs_select_one - Parse select command.
836 kumaneko 2863 *
837     * @head: Pointer to "struct ccs_io_buffer".
838     * @data: String to parse.
839     *
840     * Returns true on success, false otherwise.
841     *
842     * Caller holds ccs_read_lock().
843     */
844 kumaneko 3693 static bool ccs_select_one(struct ccs_io_buffer *head, const char *data)
845 kumaneko 2863 {
846     unsigned int pid;
847     struct ccs_domain_info *domain = NULL;
848 kumaneko 2970 bool global_pid = false;
849 kumaneko 3808 if (!strcmp(data, "execute")) {
850 kumaneko 3780 head->r.print_execute_only = true;
851 kumaneko 2863 return true;
852     }
853 kumaneko 2970 if (sscanf(data, "pid=%u", &pid) == 1 ||
854     (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
855 kumaneko 2863 struct task_struct *p;
856 kumaneko 3248 ccs_tasklist_lock();
857 kumaneko 2970 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
858     if (global_pid)
859 kumaneko 3502 p = ccsecurity_exports.find_task_by_pid_ns(pid,
860     &init_pid_ns);
861 kumaneko 2970 else
862 kumaneko 3502 p = ccsecurity_exports.find_task_by_vpid(pid);
863 kumaneko 2970 #else
864 kumaneko 2863 p = find_task_by_pid(pid);
865 kumaneko 2970 #endif
866 kumaneko 2863 if (p)
867     domain = ccs_task_domain(p);
868 kumaneko 3248 ccs_tasklist_unlock();
869 kumaneko 2863 } else if (!strncmp(data, "domain=", 7)) {
870 kumaneko 3693 if (ccs_domain_def(data + 7))
871 kumaneko 2863 domain = ccs_find_domain(data + 7);
872     } else
873     return false;
874 kumaneko 3780 head->w.domain = domain;
875 kumaneko 2863 /* Accessing read_buf is safe because head->io_sem is held. */
876     if (!head->read_buf)
877     return true; /* Do nothing if open(O_WRONLY). */
878 kumaneko 3780 memset(&head->r, 0, sizeof(head->r));
879     head->r.print_this_domain_only = true;
880 kumaneko 3892 if (domain)
881     head->r.domain = &domain->list;
882     else
883     head->r.eof = true;
884 kumaneko 2863 ccs_io_printf(head, "# select %s\n", data);
885 kumaneko 3772 if (domain && domain->is_deleted)
886 kumaneko 3780 ccs_set_string(head, "# This is a deleted domain.\n");
887 kumaneko 2863 return true;
888     }
889    
890 kumaneko 4057 /**
891     * ccs_same_handler_acl - Check for duplicated "struct ccs_handler_acl" entry.
892     *
893     * @a: Pointer to "struct ccs_acl_info".
894     * @b: Pointer to "struct ccs_acl_info".
895     *
896     * Returns true if @a and @b are duplicated, false otherwise.
897     */
898 kumaneko 3924 static bool ccs_same_handler_acl(const struct ccs_acl_info *a,
899     const struct ccs_acl_info *b)
900     {
901     const struct ccs_handler_acl *p1 = container_of(a, typeof(*p1), head);
902     const struct ccs_handler_acl *p2 = container_of(b, typeof(*p2), head);
903 kumaneko 3949 return p1->handler == p2->handler;
904 kumaneko 3924 }
905    
906 kumaneko 4057 /**
907     * ccs_same_task_acl - Check for duplicated "struct ccs_task_acl" entry.
908     *
909     * @a: Pointer to "struct ccs_acl_info".
910     * @b: Pointer to "struct ccs_acl_info".
911     *
912     * Returns true if @a and @b are duplicated, false otherwise.
913     */
914 kumaneko 3924 static bool ccs_same_task_acl(const struct ccs_acl_info *a,
915     const struct ccs_acl_info *b)
916     {
917     const struct ccs_task_acl *p1 = container_of(a, typeof(*p1), head);
918     const struct ccs_task_acl *p2 = container_of(b, typeof(*p2), head);
919 kumaneko 3949 return p1->domainname == p2->domainname;
920 kumaneko 3924 }
921    
922     /**
923     * ccs_write_task - Update task related list.
924     *
925 kumaneko 3949 * @param: Pointer to "struct ccs_acl_param".
926 kumaneko 3924 *
927     * Returns 0 on success, negative value otherwise.
928     */
929 kumaneko 3952 static int ccs_write_task(struct ccs_acl_param *param)
930 kumaneko 3924 {
931     int error;
932 kumaneko 3952 const bool is_auto = ccs_str_starts(&param->data,
933     "auto_domain_transition ");
934     if (!is_auto && !ccs_str_starts(&param->data,
935     "manual_domain_transition ")) {
936 kumaneko 3949 struct ccs_handler_acl e = { };
937 kumaneko 3952 char *handler;
938     if (ccs_str_starts(&param->data, "auto_execute_handler "))
939 kumaneko 3924 e.head.type = CCS_TYPE_AUTO_EXECUTE_HANDLER;
940 kumaneko 3952 else if (ccs_str_starts(&param->data,
941     "denied_execute_handler "))
942 kumaneko 3924 e.head.type = CCS_TYPE_DENIED_EXECUTE_HANDLER;
943     else
944     return -EINVAL;
945 kumaneko 3952 handler = ccs_read_token(param);
946     if (!ccs_correct_path(handler))
947 kumaneko 3924 return -EINVAL;
948 kumaneko 3952 e.handler = ccs_get_name(handler);
949 kumaneko 3924 if (!e.handler)
950     return -ENOMEM;
951     if (e.handler->is_patterned)
952     error = -EINVAL; /* No patterns allowed. */
953     else
954 kumaneko 3949 error = ccs_update_domain(&e.head, sizeof(e), param,
955 kumaneko 3924 ccs_same_handler_acl, NULL);
956     ccs_put_name(e.handler);
957     } else {
958     struct ccs_task_acl e = {
959     .head.type = is_auto ?
960 kumaneko 3952 CCS_TYPE_AUTO_TASK_ACL : CCS_TYPE_MANUAL_TASK_ACL,
961     .domainname = ccs_get_domainname(param),
962 kumaneko 3924 };
963     if (!e.domainname)
964 kumaneko 3952 error = -EINVAL;
965     else
966     error = ccs_update_domain(&e.head, sizeof(e), param,
967     ccs_same_task_acl, NULL);
968 kumaneko 3924 ccs_put_name(e.domainname);
969     }
970     return error;
971     }
972    
973 kumaneko 4063 /**
974     * ccs_write_domain2 - Write domain policy.
975     *
976     * @data: Policy to be interpreted.
977     * @domain: Pointer to "struct ccs_domain_info".
978     * @is_delete: True if it is a delete request.
979     *
980     * Returns 0 on success, negative value otherwise.
981     */
982 kumaneko 3693 static int ccs_write_domain2(char *data, struct ccs_domain_info *domain,
983 kumaneko 3746 const bool is_delete)
984 kumaneko 2897 {
985 kumaneko 3949 struct ccs_acl_param param = {
986 kumaneko 3952 .data = data,
987 kumaneko 3949 .domain = domain,
988     .is_delete = is_delete,
989     };
990 kumaneko 3692 static const struct {
991     const char *keyword;
992 kumaneko 3952 int (*write) (struct ccs_acl_param *);
993 kumaneko 3924 } ccs_callback[7] = {
994     { "file ", ccs_write_file },
995 kumaneko 3911 { "network inet ", ccs_write_inet_network },
996     { "network unix ", ccs_write_unix_network },
997 kumaneko 3808 { "misc ", ccs_write_misc },
998     { "capability ", ccs_write_capability },
999     { "ipc ", ccs_write_ipc },
1000 kumaneko 3924 { "task ", ccs_write_task },
1001 kumaneko 3692 };
1002 kumaneko 3746 u8 i;
1003 kumaneko 3924 for (i = 0; i < 7; i++) {
1004 kumaneko 3952 if (!ccs_str_starts(&param.data, ccs_callback[i].keyword))
1005 kumaneko 3692 continue;
1006 kumaneko 3952 return ccs_callback[i].write(&param);
1007 kumaneko 3692 }
1008 kumaneko 3952 return -EINVAL;
1009 kumaneko 2897 }
1010    
1011 kumaneko 4063 /* String table for domain flags. */
1012 kumaneko 3968 const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {
1013     [CCS_DIF_QUOTA_WARNED] = "quota_exceeded\n",
1014     [CCS_DIF_TRANSITION_FAILED] = "transition_failed\n",
1015 kumaneko 3747 };
1016 kumaneko 3968
1017 kumaneko 2863 /**
1018 kumaneko 3693 * ccs_write_domain - Write domain policy.
1019 kumaneko 2863 *
1020     * @head: Pointer to "struct ccs_io_buffer".
1021     *
1022     * Returns 0 on success, negative value otherwise.
1023     */
1024 kumaneko 3693 static int ccs_write_domain(struct ccs_io_buffer *head)
1025 kumaneko 2863 {
1026     char *data = head->write_buf;
1027 kumaneko 3780 struct ccs_domain_info *domain = head->w.domain;
1028 kumaneko 2863 bool is_delete = false;
1029     bool is_select = false;
1030     unsigned int profile;
1031 kumaneko 3968 if (ccs_str_starts(&data, "delete "))
1032 kumaneko 2863 is_delete = true;
1033 kumaneko 3968 else if (ccs_str_starts(&data, "select "))
1034 kumaneko 2863 is_select = true;
1035 kumaneko 3693 if (is_select && ccs_select_one(head, data))
1036 kumaneko 2863 return 0;
1037     /* Don't allow updating policies by non manager programs. */
1038 kumaneko 3693 if (!ccs_manager())
1039 kumaneko 2863 return -EPERM;
1040 kumaneko 3693 if (ccs_domain_def(data)) {
1041 kumaneko 2863 domain = NULL;
1042     if (is_delete)
1043     ccs_delete_domain(data);
1044     else if (is_select)
1045     domain = ccs_find_domain(data);
1046     else
1047 kumaneko 3905 domain = ccs_assign_domain(data, 0, 0, false);
1048 kumaneko 3780 head->w.domain = domain;
1049 kumaneko 2863 return 0;
1050     }
1051     if (!domain)
1052     return -EINVAL;
1053    
1054 kumaneko 3968 if (sscanf(data, "use_profile %u\n", &profile) == 1
1055 kumaneko 2892 && profile < CCS_MAX_PROFILES) {
1056 kumaneko 2991 if (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile])
1057 kumaneko 2863 domain->profile = (u8) profile;
1058     return 0;
1059     }
1060 kumaneko 3968 if (sscanf(data, "use_group %u\n", &profile) == 1
1061 kumaneko 3821 && profile < CCS_MAX_ACL_GROUPS) {
1062     domain->group = (u8) profile;
1063     return 0;
1064     }
1065 kumaneko 3747 for (profile = 0; profile < CCS_MAX_DOMAIN_INFO_FLAGS; profile++) {
1066     const char *cp = ccs_dif[profile];
1067     if (strncmp(data, cp, strlen(cp) - 1))
1068     continue;
1069     domain->flags[profile] = !is_delete;
1070 kumaneko 3702 return 0;
1071     }
1072 kumaneko 3746 return ccs_write_domain2(data, domain, is_delete);
1073 kumaneko 2863 }
1074    
1075 kumaneko 2948 /**
1076     * ccs_print_name_union - Print a ccs_name_union.
1077     *
1078     * @head: Pointer to "struct ccs_io_buffer".
1079     * @ptr: Pointer to "struct ccs_name_union".
1080 kumaneko 4063 *
1081     * Returns nothing.
1082 kumaneko 2948 */
1083 kumaneko 3780 static void ccs_print_name_union(struct ccs_io_buffer *head,
1084 kumaneko 2894 const struct ccs_name_union *ptr)
1085 kumaneko 2863 {
1086 kumaneko 3780 const bool cond = head->r.print_cond_part;
1087     if (!cond)
1088     ccs_set_space(head);
1089     if (ptr->is_group) {
1090     ccs_set_string(head, "@");
1091     ccs_set_string(head, ptr->group->group_name->name);
1092     } else {
1093     if (cond)
1094     ccs_set_string(head, "\"");
1095     ccs_set_string(head, ptr->filename->name);
1096     if (cond)
1097     ccs_set_string(head, "\"");
1098     }
1099 kumaneko 2863 }
1100    
1101 kumaneko 2948 /**
1102 kumaneko 3780 * ccs_print_number_union - Print a ccs_number_union.
1103 kumaneko 2948 *
1104     * @head: Pointer to "struct ccs_io_buffer".
1105 kumaneko 3780 * @ptr: Pointer to "struct ccs_number_union".
1106 kumaneko 4063 *
1107     * Returns nothing.
1108 kumaneko 2948 */
1109 kumaneko 3780 static void ccs_print_number_union(struct ccs_io_buffer *head,
1110     const struct ccs_number_union *ptr)
1111 kumaneko 2863 {
1112 kumaneko 3780 if (!head->r.print_cond_part)
1113     ccs_set_space(head);
1114     if (ptr->is_group) {
1115     ccs_set_string(head, "@");
1116     ccs_set_string(head, ptr->group->group_name->name);
1117     } else {
1118     int i;
1119     unsigned long min = ptr->values[0];
1120     const unsigned long max = ptr->values[1];
1121     u8 min_type = ptr->value_type[0];
1122     const u8 max_type = ptr->value_type[1];
1123     char buffer[128];
1124     buffer[0] = '\0';
1125     for (i = 0; i < 2; i++) {
1126     switch (min_type) {
1127     case CCS_VALUE_TYPE_HEXADECIMAL:
1128     ccs_addprintf(buffer, sizeof(buffer), "0x%lX",
1129     min);
1130     break;
1131     case CCS_VALUE_TYPE_OCTAL:
1132     ccs_addprintf(buffer, sizeof(buffer), "0%lo",
1133     min);
1134     break;
1135     default:
1136     ccs_addprintf(buffer, sizeof(buffer), "%lu",
1137     min);
1138     break;
1139     }
1140     if (min == max && min_type == max_type)
1141     break;
1142     ccs_addprintf(buffer, sizeof(buffer), "-");
1143     min_type = max_type;
1144     min = max;
1145 kumaneko 3690 }
1146 kumaneko 3780 ccs_io_printf(head, "%s", buffer);
1147 kumaneko 3690 }
1148     }
1149    
1150 kumaneko 2948 /**
1151 kumaneko 2894 * ccs_print_condition - Print condition part.
1152     *
1153     * @head: Pointer to "struct ccs_io_buffer".
1154 kumaneko 3780 * @cond: Pointer to "struct ccs_condition".
1155 kumaneko 2894 *
1156     * Returns true on success, false otherwise.
1157     */
1158     static bool ccs_print_condition(struct ccs_io_buffer *head,
1159     const struct ccs_condition *cond)
1160     {
1161 kumaneko 3780 switch (head->r.cond_step) {
1162     case 0:
1163 kumaneko 3952 head->r.cond_index = 0;
1164     head->r.cond_step++;
1165 kumaneko 3780 /* fall through */
1166     case 1:
1167     {
1168     const u16 condc = cond->condc;
1169     const struct ccs_condition_element *condp =
1170     (typeof(condp)) (cond + 1);
1171     const struct ccs_number_union *numbers_p =
1172     (typeof(numbers_p)) (condp + condc);
1173     const struct ccs_name_union *names_p =
1174     (typeof(names_p))
1175     (numbers_p + cond->numbers_count);
1176     const struct ccs_argv *argv =
1177     (typeof(argv)) (names_p + cond->names_count);
1178     const struct ccs_envp *envp =
1179     (typeof(envp)) (argv + cond->argc);
1180     u16 skip;
1181     for (skip = 0; skip < head->r.cond_index; skip++) {
1182     const u8 left = condp->left;
1183     const u8 right = condp->right;
1184     condp++;
1185     switch (left) {
1186     case CCS_ARGV_ENTRY:
1187     argv++;
1188     continue;
1189     case CCS_ENVP_ENTRY:
1190     envp++;
1191     continue;
1192     case CCS_NUMBER_UNION:
1193     numbers_p++;
1194     break;
1195     }
1196     switch (right) {
1197     case CCS_NAME_UNION:
1198     names_p++;
1199     break;
1200     case CCS_NUMBER_UNION:
1201     numbers_p++;
1202     break;
1203     }
1204 kumaneko 2894 }
1205 kumaneko 3780 while (head->r.cond_index < condc) {
1206     const u8 match = condp->equals;
1207     const u8 left = condp->left;
1208     const u8 right = condp->right;
1209     if (!ccs_flush(head))
1210     return false;
1211     condp++;
1212     head->r.cond_index++;
1213     ccs_set_space(head);
1214     switch (left) {
1215     case CCS_ARGV_ENTRY:
1216     ccs_io_printf(head,
1217     "exec.argv[%u]%s\"%s\"",
1218     argv->index,
1219     argv->is_not ?
1220     "!=" : "=",
1221     argv->value->name);
1222     argv++;
1223     continue;
1224     case CCS_ENVP_ENTRY:
1225     ccs_io_printf(head,
1226     "exec.envp[\"%s\"]%s",
1227     envp->name->name,
1228     envp->is_not ?
1229     "!=" : "=");
1230     if (envp->value) {
1231     ccs_set_string(head, "\"");
1232     ccs_set_string(head, envp->
1233     value->name);
1234     ccs_set_string(head, "\"");
1235     } else {
1236     ccs_set_string(head, "NULL");
1237     }
1238     envp++;
1239     continue;
1240     case CCS_NUMBER_UNION:
1241     ccs_print_number_union(head,
1242     numbers_p++);
1243     break;
1244     default:
1245     ccs_set_string(head,
1246     ccs_condition_keyword[left]);
1247     break;
1248     }
1249     ccs_set_string(head, match ? "=" : "!=");
1250     switch (right) {
1251     case CCS_NAME_UNION:
1252     ccs_print_name_union(head, names_p++);
1253     break;
1254     case CCS_NUMBER_UNION:
1255     ccs_print_number_union(head,
1256     numbers_p++);
1257     break;
1258     default:
1259     ccs_set_string(head,
1260     ccs_condition_keyword[right]);
1261     break;
1262     }
1263     }
1264 kumaneko 2894 }
1265 kumaneko 3780 head->r.cond_step++;
1266     /* fall through */
1267     case 2:
1268     if (!ccs_flush(head))
1269 kumaneko 2894 break;
1270 kumaneko 3780 head->r.cond_step++;
1271     /* fall through */
1272     case 3:
1273 kumaneko 4057 if (cond->grant_log != CCS_GRANTLOG_AUTO)
1274 kumaneko 3963 ccs_io_printf(head, " grant_log=%s",
1275 kumaneko 4057 ccs_yesno(cond->grant_log ==
1276     CCS_GRANTLOG_YES));
1277 kumaneko 3924 if (cond->transit) {
1278     ccs_set_string(head, " auto_domain_transitition=\"");
1279     ccs_set_string(head, cond->transit->name);
1280     ccs_set_string(head, "\"");
1281 kumaneko 2894 }
1282 kumaneko 3780 ccs_set_lf(head);
1283     return true;
1284 kumaneko 2894 }
1285     return false;
1286     }
1287    
1288 kumaneko 3872 /**
1289     * ccs_fns - Find next set bit.
1290     *
1291     * @perm: 8 bits value.
1292     * @bit: First bit to find.
1293     *
1294     * Returns next set bit on success, 8 otherwise.
1295     */
1296     static u8 ccs_fns(const u8 perm, u8 bit)
1297     {
1298     for ( ; bit < 8; bit++)
1299     if (perm & (1 << bit))
1300     break;
1301     return bit;
1302     }
1303    
1304 kumaneko 4063 /**
1305     * ccs_set_group - Print "acl_group " header keyword.
1306     *
1307     * @head: Pointer to "struct ccs_io_buffer".
1308     *
1309     * Returns nothing.
1310     */
1311 kumaneko 3821 static void ccs_set_group(struct ccs_io_buffer *head)
1312     {
1313     if (head->type == CCS_EXCEPTIONPOLICY)
1314     ccs_io_printf(head, "acl_group %u ", head->r.group_index);
1315     }
1316    
1317 kumaneko 3780 /**
1318 kumaneko 3772 * ccs_print_entry - Print an ACL entry.
1319 kumaneko 2863 *
1320     * @head: Pointer to "struct ccs_io_buffer".
1321 kumaneko 3780 * @acl: Pointer to an ACL entry.
1322 kumaneko 2863 *
1323     * Returns true on success, false otherwise.
1324     */
1325 kumaneko 3772 static bool ccs_print_entry(struct ccs_io_buffer *head,
1326     const struct ccs_acl_info *acl)
1327 kumaneko 2863 {
1328 kumaneko 3772 const u8 acl_type = acl->type;
1329 kumaneko 3872 u8 bit;
1330 kumaneko 3780 if (head->r.print_cond_part)
1331     goto print_cond_part;
1332 kumaneko 3772 if (acl->is_deleted)
1333     return true;
1334 kumaneko 4049 next:
1335 kumaneko 3872 bit = head->r.bit;
1336 kumaneko 3780 if (!ccs_flush(head))
1337     return false;
1338     else if (acl_type == CCS_TYPE_PATH_ACL) {
1339 kumaneko 3772 struct ccs_path_acl *ptr
1340     = container_of(acl, typeof(*ptr), head);
1341 kumaneko 3872 const u16 perm = ptr->perm;
1342     for ( ; bit < CCS_MAX_PATH_OPERATION; bit++) {
1343     if (!(perm & (1 << bit)))
1344     continue;
1345     if (head->r.print_execute_only &&
1346 kumaneko 3924 bit != CCS_TYPE_EXECUTE
1347     /* && bit != CCS_TYPE_TRANSIT */)
1348 kumaneko 3872 continue;
1349     break;
1350     }
1351     if (bit >= CCS_MAX_PATH_OPERATION)
1352 kumaneko 3772 goto done;
1353 kumaneko 3872 ccs_set_group(head);
1354     ccs_set_string(head, "file ");
1355     ccs_set_string(head, ccs_path_keyword[bit]);
1356 kumaneko 3780 ccs_print_name_union(head, &ptr->name);
1357 kumaneko 3924 } else if (acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER ||
1358 kumaneko 3772 acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
1359 kumaneko 3924 struct ccs_handler_acl *ptr
1360 kumaneko 3772 = container_of(acl, typeof(*ptr), head);
1361 kumaneko 3821 ccs_set_group(head);
1362 kumaneko 3924 ccs_set_string(head, "task ");
1363     ccs_set_string(head, acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER
1364     ? "auto_execute_handler " :
1365     "denied_execute_handler ");
1366 kumaneko 3780 ccs_set_string(head, ptr->handler->name);
1367 kumaneko 3924 } else if (acl_type == CCS_TYPE_AUTO_TASK_ACL ||
1368     acl_type == CCS_TYPE_MANUAL_TASK_ACL) {
1369     struct ccs_task_acl *ptr =
1370     container_of(acl, typeof(*ptr), head);
1371     ccs_set_group(head);
1372     ccs_set_string(head, "task ");
1373     ccs_set_string(head, acl_type == CCS_TYPE_AUTO_TASK_ACL ?
1374     "auto_domain_transition " :
1375     "manual_domain_transition ");
1376     ccs_set_string(head, ptr->domainname->name);
1377 kumaneko 3780 } else if (head->r.print_execute_only) {
1378 kumaneko 3772 return true;
1379     } else if (acl_type == CCS_TYPE_MKDEV_ACL) {
1380 kumaneko 3780 struct ccs_mkdev_acl *ptr =
1381     container_of(acl, typeof(*ptr), head);
1382 kumaneko 3872 bit = ccs_fns(ptr->perm, bit);
1383     if (bit >= CCS_MAX_MKDEV_OPERATION)
1384 kumaneko 3772 goto done;
1385 kumaneko 3872 ccs_set_group(head);
1386     ccs_set_string(head, "file ");
1387 kumaneko 3968 ccs_set_string(head, ccs_mac_keywords[ccs_pnnn2mac[bit]]);
1388 kumaneko 3780 ccs_print_name_union(head, &ptr->name);
1389     ccs_print_number_union(head, &ptr->mode);
1390     ccs_print_number_union(head, &ptr->major);
1391     ccs_print_number_union(head, &ptr->minor);
1392 kumaneko 3772 } else if (acl_type == CCS_TYPE_PATH2_ACL) {
1393 kumaneko 3780 struct ccs_path2_acl *ptr =
1394     container_of(acl, typeof(*ptr), head);
1395 kumaneko 3872 bit = ccs_fns(ptr->perm, bit);
1396     if (bit >= CCS_MAX_PATH2_OPERATION)
1397 kumaneko 3772 goto done;
1398 kumaneko 3872 ccs_set_group(head);
1399     ccs_set_string(head, "file ");
1400 kumaneko 3968 ccs_set_string(head, ccs_mac_keywords[ccs_pp2mac[bit]]);
1401 kumaneko 3780 ccs_print_name_union(head, &ptr->name1);
1402     ccs_print_name_union(head, &ptr->name2);
1403 kumaneko 3772 } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
1404 kumaneko 3780 struct ccs_path_number_acl *ptr =
1405     container_of(acl, typeof(*ptr), head);
1406 kumaneko 3872 bit = ccs_fns(ptr->perm, bit);
1407     if (bit >= CCS_MAX_PATH_NUMBER_OPERATION)
1408 kumaneko 3772 goto done;
1409 kumaneko 3872 ccs_set_group(head);
1410     ccs_set_string(head, "file ");
1411 kumaneko 3968 ccs_set_string(head, ccs_mac_keywords[ccs_pn2mac[bit]]);
1412 kumaneko 3780 ccs_print_name_union(head, &ptr->name);
1413     ccs_print_number_union(head, &ptr->number);
1414 kumaneko 3772 } else if (acl_type == CCS_TYPE_ENV_ACL) {
1415 kumaneko 3780 struct ccs_env_acl *ptr =
1416     container_of(acl, typeof(*ptr), head);
1417 kumaneko 3821 ccs_set_group(head);
1418 kumaneko 3808 ccs_set_string(head, "misc env ");
1419 kumaneko 3780 ccs_set_string(head, ptr->env->name);
1420 kumaneko 3772 } else if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
1421 kumaneko 3780 struct ccs_capability_acl *ptr =
1422     container_of(acl, typeof(*ptr), head);
1423 kumaneko 3821 ccs_set_group(head);
1424 kumaneko 3808 ccs_set_string(head, "capability ");
1425 kumaneko 3968 ccs_set_string(head,
1426     ccs_mac_keywords[ccs_c2mac[ptr->operation]]);
1427 kumaneko 3911 } else if (acl_type == CCS_TYPE_INET_ACL) {
1428     struct ccs_inet_acl *ptr =
1429 kumaneko 3780 container_of(acl, typeof(*ptr), head);
1430 kumaneko 3872 bit = ccs_fns(ptr->perm, bit);
1431     if (bit >= CCS_MAX_NETWORK_OPERATION)
1432 kumaneko 3772 goto done;
1433 kumaneko 3872 ccs_set_group(head);
1434 kumaneko 3911 ccs_set_string(head, "network inet ");
1435 kumaneko 3927 ccs_set_string(head, ccs_proto_keyword[ptr->protocol]);
1436 kumaneko 3843 ccs_set_space(head);
1437 kumaneko 3927 ccs_set_string(head, ccs_socket_keyword[bit]);
1438 kumaneko 3872 ccs_set_space(head);
1439 kumaneko 2916 switch (ptr->address_type) {
1440 kumaneko 3780 char buf[128];
1441 kumaneko 2916 case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:
1442 kumaneko 3780 ccs_set_string(head, "@");
1443     ccs_set_string(head,
1444     ptr->address.group->group_name->name);
1445 kumaneko 2916 break;
1446     case CCS_IP_ADDRESS_TYPE_IPv4:
1447 kumaneko 3690 ccs_print_ipv4(buf, sizeof(buf), ptr->address.ipv4.min,
1448     ptr->address.ipv4.max);
1449 kumaneko 3780 ccs_io_printf(head, "%s", buf);
1450 kumaneko 2916 break;
1451     case CCS_IP_ADDRESS_TYPE_IPv6:
1452 kumaneko 3690 ccs_print_ipv6(buf, sizeof(buf), ptr->address.ipv6.min,
1453     ptr->address.ipv6.max);
1454 kumaneko 3780 ccs_io_printf(head, "%s", buf);
1455 kumaneko 2916 break;
1456     }
1457 kumaneko 3780 ccs_print_number_union(head, &ptr->port);
1458 kumaneko 3911 } else if (acl_type == CCS_TYPE_UNIX_ACL) {
1459     struct ccs_unix_acl *ptr =
1460     container_of(acl, typeof(*ptr), head);
1461     bit = ccs_fns(ptr->perm, bit);
1462     if (bit >= CCS_MAX_NETWORK_OPERATION)
1463     goto done;
1464     ccs_set_group(head);
1465     ccs_set_string(head, "network unix ");
1466 kumaneko 3927 ccs_set_string(head, ccs_proto_keyword[ptr->protocol]);
1467 kumaneko 3911 ccs_set_space(head);
1468 kumaneko 3927 ccs_set_string(head, ccs_socket_keyword[bit]);
1469 kumaneko 3911 ccs_print_name_union(head, &ptr->name);
1470 kumaneko 3772 } else if (acl_type == CCS_TYPE_SIGNAL_ACL) {
1471 kumaneko 3780 struct ccs_signal_acl *ptr =
1472     container_of(acl, typeof(*ptr), head);
1473 kumaneko 3821 ccs_set_group(head);
1474 kumaneko 3808 ccs_set_string(head, "ipc signal ");
1475     ccs_io_printf(head, "%u ", ptr->sig);
1476 kumaneko 3780 ccs_set_string(head, ptr->domainname->name);
1477 kumaneko 3772 } else if (acl_type == CCS_TYPE_MOUNT_ACL) {
1478 kumaneko 3780 struct ccs_mount_acl *ptr =
1479     container_of(acl, typeof(*ptr), head);
1480 kumaneko 3821 ccs_set_group(head);
1481 kumaneko 3808 ccs_io_printf(head, "file mount");
1482 kumaneko 3780 ccs_print_name_union(head, &ptr->dev_name);
1483     ccs_print_name_union(head, &ptr->dir_name);
1484     ccs_print_name_union(head, &ptr->fs_type);
1485     ccs_print_number_union(head, &ptr->flags);
1486 kumaneko 2863 }
1487 kumaneko 3872 head->r.bit = bit + 1;
1488 kumaneko 3780 if (acl->cond) {
1489     head->r.print_cond_part = true;
1490     head->r.cond_step = 0;
1491     if (!ccs_flush(head))
1492     return false;
1493 kumaneko 4049 print_cond_part:
1494 kumaneko 3780 if (!ccs_print_condition(head, acl->cond))
1495     return false;
1496     head->r.print_cond_part = false;
1497     } else {
1498     ccs_set_lf(head);
1499 kumaneko 2897 }
1500 kumaneko 3872 switch (acl_type) {
1501     case CCS_TYPE_PATH_ACL:
1502     case CCS_TYPE_MKDEV_ACL:
1503     case CCS_TYPE_PATH2_ACL:
1504     case CCS_TYPE_PATH_NUMBER_ACL:
1505 kumaneko 3911 case CCS_TYPE_INET_ACL:
1506     case CCS_TYPE_UNIX_ACL:
1507 kumaneko 3872 goto next;
1508     }
1509 kumaneko 4049 done:
1510 kumaneko 3872 head->r.bit = 0;
1511 kumaneko 3747 return true;
1512 kumaneko 2863 }
1513    
1514     /**
1515 kumaneko 3697 * ccs_read_domain2 - Read domain policy.
1516     *
1517     * @head: Pointer to "struct ccs_io_buffer".
1518     * @domain: Pointer to "struct ccs_domain_info".
1519 kumaneko 3924 * @index: Index number.
1520 kumaneko 3697 *
1521     * Caller holds ccs_read_lock().
1522     *
1523     * Returns true on success, false otherwise.
1524     */
1525     static bool ccs_read_domain2(struct ccs_io_buffer *head,
1526 kumaneko 3924 struct ccs_domain_info *domain,
1527     const u8 index)
1528 kumaneko 3697 {
1529 kumaneko 3924 list_for_each_cookie(head->r.acl, &domain->acl_info_list[index]) {
1530 kumaneko 3780 struct ccs_acl_info *ptr =
1531     list_entry(head->r.acl, typeof(*ptr), list);
1532 kumaneko 3697 if (!ccs_print_entry(head, ptr))
1533     return false;
1534     }
1535 kumaneko 3780 head->r.acl = NULL;
1536 kumaneko 3697 return true;
1537     }
1538    
1539     /**
1540 kumaneko 3693 * ccs_read_domain - Read domain policy.
1541 kumaneko 2863 *
1542     * @head: Pointer to "struct ccs_io_buffer".
1543     *
1544     * Caller holds ccs_read_lock().
1545     */
1546 kumaneko 3693 static void ccs_read_domain(struct ccs_io_buffer *head)
1547 kumaneko 2863 {
1548 kumaneko 3780 if (head->r.eof)
1549 kumaneko 2943 return;
1550 kumaneko 3780 list_for_each_cookie(head->r.domain, &ccs_domain_list) {
1551 kumaneko 3697 struct ccs_domain_info *domain =
1552 kumaneko 3780 list_entry(head->r.domain, typeof(*domain), list);
1553     switch (head->r.step) {
1554 kumaneko 3747 u8 i;
1555 kumaneko 3697 case 0:
1556 kumaneko 3780 if (domain->is_deleted &&
1557     !head->r.print_this_domain_only)
1558 kumaneko 3697 continue;
1559     /* Print domainname and flags. */
1560 kumaneko 3780 ccs_set_string(head, domain->domainname->name);
1561     ccs_set_lf(head);
1562 kumaneko 3968 ccs_io_printf(head, "use_profile %u\n",
1563 kumaneko 3780 domain->profile);
1564 kumaneko 3968 ccs_io_printf(head, "use_group %u\n", domain->group);
1565 kumaneko 3747 for (i = 0; i < CCS_MAX_DOMAIN_INFO_FLAGS; i++)
1566 kumaneko 3780 if (domain->flags[i])
1567     ccs_set_string(head, ccs_dif[i]);
1568     head->r.step++;
1569     ccs_set_lf(head);
1570 kumaneko 3697 /* fall through */
1571     case 1:
1572 kumaneko 3924 if (!ccs_read_domain2(head, domain, 0))
1573 kumaneko 3697 return;
1574 kumaneko 3780 head->r.step++;
1575 kumaneko 3924 /* fall through */
1576     case 2:
1577     if (!ccs_read_domain2(head, domain, 1))
1578     return;
1579     head->r.step++;
1580 kumaneko 3780 if (!ccs_set_lf(head))
1581     return;
1582 kumaneko 3697 /* fall through */
1583 kumaneko 3924 case 3:
1584 kumaneko 3780 head->r.step = 0;
1585     if (head->r.print_this_domain_only)
1586     goto done;
1587 kumaneko 2863 }
1588     }
1589 kumaneko 4049 done:
1590 kumaneko 3780 head->r.eof = true;
1591 kumaneko 2863 }
1592    
1593     /**
1594     * ccs_write_domain_profile - Assign profile for specified domain.
1595     *
1596     * @head: Pointer to "struct ccs_io_buffer".
1597     *
1598     * Returns 0 on success, -EINVAL otherwise.
1599     *
1600     * This is equivalent to doing
1601     *
1602     * ( echo "select " $domainname; echo "use_profile " $profile ) |
1603 kumaneko 2948 * /usr/sbin/ccs-loadpolicy -d
1604 kumaneko 2863 *
1605     * Caller holds ccs_read_lock().
1606     */
1607     static int ccs_write_domain_profile(struct ccs_io_buffer *head)
1608     {
1609     char *data = head->write_buf;
1610     char *cp = strchr(data, ' ');
1611     struct ccs_domain_info *domain;
1612     unsigned int profile;
1613     if (!cp)
1614     return -EINVAL;
1615     *cp = '\0';
1616     profile = simple_strtoul(data, NULL, 10);
1617 kumaneko 2892 if (profile >= CCS_MAX_PROFILES)
1618 kumaneko 2863 return -EINVAL;
1619     domain = ccs_find_domain(cp + 1);
1620 kumaneko 2991 if (domain && (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile]))
1621 kumaneko 2863 domain->profile = (u8) profile;
1622     return 0;
1623     }
1624    
1625     /**
1626     * ccs_read_domain_profile - Read only domainname and profile.
1627     *
1628     * @head: Pointer to "struct ccs_io_buffer".
1629     *
1630     * This is equivalent to doing
1631     *
1632     * grep -A 1 '^<kernel>' /proc/ccs/domain_policy |
1633     * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
1634     * domainname = $0; } else if ( $1 == "use_profile" ) {
1635     * print $2 " " domainname; domainname = ""; } } ; '
1636     *
1637     * Caller holds ccs_read_lock().
1638     */
1639 kumaneko 2943 static void ccs_read_domain_profile(struct ccs_io_buffer *head)
1640 kumaneko 2863 {
1641 kumaneko 3780 if (head->r.eof)
1642 kumaneko 2943 return;
1643 kumaneko 3780 list_for_each_cookie(head->r.domain, &ccs_domain_list) {
1644     struct ccs_domain_info *domain =
1645     list_entry(head->r.domain, typeof(*domain), list);
1646 kumaneko 2863 if (domain->is_deleted)
1647     continue;
1648 kumaneko 3780 if (!ccs_flush(head))
1649 kumaneko 2943 return;
1650 kumaneko 3780 ccs_io_printf(head, "%u ", domain->profile);
1651     ccs_set_string(head, domain->domainname->name);
1652     ccs_set_lf(head);
1653 kumaneko 2863 }
1654 kumaneko 3780 head->r.eof = true;
1655 kumaneko 2863 }
1656    
1657     /**
1658     * ccs_write_pid: Specify PID to obtain domainname.
1659     *
1660     * @head: Pointer to "struct ccs_io_buffer".
1661     *
1662     * Returns 0.
1663     */
1664     static int ccs_write_pid(struct ccs_io_buffer *head)
1665     {
1666 kumaneko 3780 head->r.eof = false;
1667 kumaneko 2863 return 0;
1668     }
1669    
1670     /**
1671     * ccs_read_pid - Read information of a process.
1672     *
1673     * @head: Pointer to "struct ccs_io_buffer".
1674     *
1675     * Returns the domainname which the specified PID is in or
1676     * process information of the specified PID on success,
1677     * empty string otherwise.
1678     *
1679     * Caller holds ccs_read_lock().
1680     */
1681 kumaneko 2943 static void ccs_read_pid(struct ccs_io_buffer *head)
1682 kumaneko 2863 {
1683     char *buf = head->write_buf;
1684     bool task_info = false;
1685 kumaneko 2970 bool global_pid = false;
1686 kumaneko 2863 unsigned int pid;
1687     struct task_struct *p;
1688     struct ccs_domain_info *domain = NULL;
1689     u32 ccs_flags = 0;
1690     /* Accessing write_buf is safe because head->io_sem is held. */
1691 kumaneko 3136 if (!buf) {
1692 kumaneko 3780 head->r.eof = true;
1693 kumaneko 2943 return; /* Do nothing if open(O_RDONLY). */
1694 kumaneko 3136 }
1695 kumaneko 3780 if (head->r.w_pos || head->r.eof)
1696 kumaneko 2943 return;
1697 kumaneko 3780 head->r.eof = true;
1698 kumaneko 2863 if (ccs_str_starts(&buf, "info "))
1699     task_info = true;
1700 kumaneko 2970 if (ccs_str_starts(&buf, "global-pid "))
1701     global_pid = true;
1702 kumaneko 2863 pid = (unsigned int) simple_strtoul(buf, NULL, 10);
1703 kumaneko 3248 ccs_tasklist_lock();
1704 kumaneko 2970 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1705     if (global_pid)
1706 kumaneko 3502 p = ccsecurity_exports.find_task_by_pid_ns(pid, &init_pid_ns);
1707 kumaneko 2970 else
1708 kumaneko 3502 p = ccsecurity_exports.find_task_by_vpid(pid);
1709 kumaneko 2970 #else
1710 kumaneko 2863 p = find_task_by_pid(pid);
1711 kumaneko 2970 #endif
1712 kumaneko 2863 if (p) {
1713     domain = ccs_task_domain(p);
1714 kumaneko 4049 ccs_flags = ccs_task_flags(p);
1715 kumaneko 2863 }
1716 kumaneko 3248 ccs_tasklist_unlock();
1717 kumaneko 2863 if (!domain)
1718 kumaneko 2943 return;
1719 kumaneko 3780 if (!task_info) {
1720     ccs_io_printf(head, "%u %u ", pid, domain->profile);
1721     ccs_set_string(head, domain->domainname->name);
1722     } else {
1723 kumaneko 3924 ccs_io_printf(head, "%u manager=%s execute_handler=%s ", pid,
1724 kumaneko 2958 ccs_yesno(ccs_flags &
1725 kumaneko 3693 CCS_TASK_IS_MANAGER),
1726 kumaneko 2958 ccs_yesno(ccs_flags &
1727 kumaneko 3924 CCS_TASK_IS_EXECUTE_HANDLER));
1728 kumaneko 3780 }
1729 kumaneko 2863 }
1730    
1731 kumaneko 4063 /* String table for domain transition control keywords. */
1732 kumaneko 3968 static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {
1733     [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",
1734     [CCS_TRANSITION_CONTROL_INITIALIZE] = "initialize_domain ",
1735     [CCS_TRANSITION_CONTROL_NO_KEEP] = "no_keep_domain ",
1736     [CCS_TRANSITION_CONTROL_KEEP] = "keep_domain ",
1737 kumaneko 3752 };
1738    
1739 kumaneko 4063 /* String table for grouping keywords. */
1740 kumaneko 3968 static const char * const ccs_group_name[CCS_MAX_GROUP] = {
1741     [CCS_PATH_GROUP] = "path_group ",
1742     [CCS_NUMBER_GROUP] = "number_group ",
1743     [CCS_ADDRESS_GROUP] = "address_group ",
1744 kumaneko 3752 };
1745    
1746 kumaneko 2863 /**
1747 kumaneko 3693 * ccs_write_exception - Write exception policy.
1748 kumaneko 2863 *
1749     * @head: Pointer to "struct ccs_io_buffer".
1750     *
1751     * Returns 0 on success, negative value otherwise.
1752     */
1753 kumaneko 3693 static int ccs_write_exception(struct ccs_io_buffer *head)
1754 kumaneko 2863 {
1755     char *data = head->write_buf;
1756 kumaneko 3968 const bool is_delete = ccs_str_starts(&data, "delete ");
1757 kumaneko 3691 u8 i;
1758     static const struct {
1759     const char *keyword;
1760 kumaneko 3752 int (*write) (char *, const bool);
1761 kumaneko 4049 } ccs_callback[2] = {
1762 kumaneko 3968 { "aggregator ", ccs_write_aggregator },
1763     { "deny_autobind ", ccs_write_reserved_port },
1764 kumaneko 3691 };
1765 kumaneko 4049 for (i = 0; i < 2; i++)
1766 kumaneko 3691 if (ccs_str_starts(&data, ccs_callback[i].keyword))
1767 kumaneko 3752 return ccs_callback[i].write(data, is_delete);
1768 kumaneko 3781 for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)
1769 kumaneko 3752 if (ccs_str_starts(&data, ccs_transition_type[i]))
1770     return ccs_write_transition_control(data, is_delete,
1771     i);
1772 kumaneko 3781 for (i = 0; i < CCS_MAX_GROUP; i++)
1773 kumaneko 3752 if (ccs_str_starts(&data, ccs_group_name[i]))
1774 kumaneko 3693 return ccs_write_group(data, is_delete, i);
1775 kumaneko 3821 if (ccs_str_starts(&data, "acl_group ")) {
1776     unsigned int group;
1777     if (sscanf(data, "%u", &group) == 1 &&
1778     group < CCS_MAX_ACL_GROUPS) {
1779     data = strchr(data, ' ');
1780     if (data)
1781     return ccs_write_domain2(data + 1,
1782     &ccs_acl_group[group],
1783     is_delete);
1784     }
1785     }
1786     return -EINVAL;
1787 kumaneko 2863 }
1788    
1789     /**
1790 kumaneko 3689 * ccs_read_group - Read "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group" list.
1791 kumaneko 2863 *
1792     * @head: Pointer to "struct ccs_io_buffer".
1793 kumaneko 3689 * @idx: Index number.
1794 kumaneko 2863 *
1795 kumaneko 3689 * Returns true on success, false otherwise.
1796     *
1797 kumaneko 2863 * Caller holds ccs_read_lock().
1798     */
1799 kumaneko 3689 static bool ccs_read_group(struct ccs_io_buffer *head, const int idx)
1800 kumaneko 2863 {
1801 kumaneko 3780 list_for_each_cookie(head->r.group, &ccs_group_list[idx]) {
1802 kumaneko 3689 struct ccs_group *group =
1803 kumaneko 3780 list_entry(head->r.group, typeof(*group), head.list);
1804     list_for_each_cookie(head->r.acl, &group->member_list) {
1805 kumaneko 3689 struct ccs_acl_head *ptr =
1806 kumaneko 3780 list_entry(head->r.acl, typeof(*ptr), list);
1807 kumaneko 3689 if (ptr->is_deleted)
1808     continue;
1809 kumaneko 3780 if (!ccs_flush(head))
1810     return false;
1811     ccs_set_string(head, ccs_group_name[idx]);
1812     ccs_set_string(head, group->group_name->name);
1813 kumaneko 3689 if (idx == CCS_PATH_GROUP) {
1814 kumaneko 3780 ccs_set_space(head);
1815     ccs_set_string(head, container_of
1816     (ptr, struct ccs_path_group,
1817     head)->member_name->name);
1818 kumaneko 3689 } else if (idx == CCS_NUMBER_GROUP) {
1819 kumaneko 3780 ccs_print_number_union(head, &container_of
1820 kumaneko 4049 (ptr, struct ccs_number_group,
1821     head)->number);
1822 kumaneko 3689 } else if (idx == CCS_ADDRESS_GROUP) {
1823 kumaneko 3780 char buffer[128];
1824 kumaneko 3689 struct ccs_address_group *member =
1825     container_of(ptr, typeof(*member),
1826     head);
1827 kumaneko 3690 if (member->is_ipv6)
1828     ccs_print_ipv6(buffer, sizeof(buffer),
1829     member->min.ipv6,
1830     member->max.ipv6);
1831     else
1832     ccs_print_ipv4(buffer, sizeof(buffer),
1833     member->min.ipv4,
1834     member->max.ipv4);
1835 kumaneko 3780 ccs_io_printf(head, " %s", buffer);
1836 kumaneko 3689 }
1837 kumaneko 3780 ccs_set_lf(head);
1838 kumaneko 3689 }
1839 kumaneko 3780 head->r.acl = NULL;
1840 kumaneko 3689 }
1841 kumaneko 3780 head->r.group = NULL;
1842 kumaneko 3689 return true;
1843     }
1844    
1845     /**
1846     * ccs_read_policy - Read "struct ccs_..._entry" list.
1847     *
1848     * @head: Pointer to "struct ccs_io_buffer".
1849     * @idx: Index number.
1850     *
1851     * Returns true on success, false otherwise.
1852     *
1853     * Caller holds ccs_read_lock().
1854     */
1855     static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx)
1856     {
1857 kumaneko 3780 list_for_each_cookie(head->r.acl, &ccs_policy_list[idx]) {
1858     struct ccs_acl_head *acl =
1859     container_of(head->r.acl, typeof(*acl), list);
1860 kumaneko 3689 if (acl->is_deleted)
1861     continue;
1862 kumaneko 3780 if (!ccs_flush(head))
1863     return false;
1864 kumaneko 3689 switch (idx) {
1865 kumaneko 3752 case CCS_ID_TRANSITION_CONTROL:
1866 kumaneko 3689 {
1867 kumaneko 3752 struct ccs_transition_control *ptr =
1868 kumaneko 3689 container_of(acl, typeof(*ptr), head);
1869 kumaneko 3780 ccs_set_string(head,
1870     ccs_transition_type[ptr->type]);
1871     ccs_set_string(head, ptr->program ?
1872     ptr->program->name : "any");
1873     ccs_set_string(head, " from ");
1874     ccs_set_string(head, ptr->domainname ?
1875     ptr->domainname->name : "any");
1876 kumaneko 3689 }
1877 kumaneko 2863 break;
1878 kumaneko 3689 case CCS_ID_AGGREGATOR:
1879     {
1880 kumaneko 3693 struct ccs_aggregator *ptr =
1881 kumaneko 3689 container_of(acl, typeof(*ptr), head);
1882 kumaneko 3968 ccs_set_string(head, "aggregator ");
1883 kumaneko 3780 ccs_set_string(head, ptr->original_name->name);
1884     ccs_set_space(head);
1885     ccs_set_string(head,
1886     ptr->aggregated_name->name);
1887 kumaneko 3689 }
1888 kumaneko 2943 break;
1889 kumaneko 3689 case CCS_ID_RESERVEDPORT:
1890     {
1891 kumaneko 3693 struct ccs_reserved *ptr =
1892 kumaneko 3689 container_of(acl, typeof(*ptr), head);
1893     const u16 min_port = ptr->min_port;
1894     const u16 max_port = ptr->max_port;
1895 kumaneko 3968 ccs_set_string(head, "deny_autobind ");
1896 kumaneko 3780 ccs_io_printf(head, "%u", min_port);
1897     if (min_port != max_port)
1898     ccs_io_printf(head, "-%u", max_port);
1899 kumaneko 3689 }
1900 kumaneko 2943 break;
1901 kumaneko 3696 default:
1902     continue;
1903 kumaneko 3689 }
1904 kumaneko 3780 ccs_set_lf(head);
1905 kumaneko 2863 }
1906 kumaneko 3780 head->r.acl = NULL;
1907 kumaneko 3689 return true;
1908 kumaneko 2863 }
1909    
1910 kumaneko 2897 /**
1911 kumaneko 3693 * ccs_read_exception - Read exception policy.
1912 kumaneko 3689 *
1913     * @head: Pointer to "struct ccs_io_buffer".
1914     *
1915     * Caller holds ccs_read_lock().
1916     */
1917 kumaneko 3693 static void ccs_read_exception(struct ccs_io_buffer *head)
1918 kumaneko 3689 {
1919 kumaneko 3780 if (head->r.eof)
1920 kumaneko 3689 return;
1921 kumaneko 3780 while (head->r.step < CCS_MAX_POLICY &&
1922     ccs_read_policy(head, head->r.step))
1923     head->r.step++;
1924     if (head->r.step < CCS_MAX_POLICY)
1925 kumaneko 3689 return;
1926 kumaneko 3780 while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP &&
1927     ccs_read_group(head, head->r.step - CCS_MAX_POLICY))
1928     head->r.step++;
1929     if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP)
1930 kumaneko 3697 return;
1931 kumaneko 3821 while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP
1932 kumaneko 3924 + CCS_MAX_ACL_GROUPS * 2) {
1933     head->r.group_index = (head->r.step - CCS_MAX_POLICY
1934     - CCS_MAX_GROUP) / 2;
1935 kumaneko 3821 if (!ccs_read_domain2(head,
1936 kumaneko 3924 &ccs_acl_group[head->r.group_index],
1937     head->r.step & 1))
1938 kumaneko 3821 return;
1939     head->r.step++;
1940     }
1941     head->r.eof = true;
1942 kumaneko 3689 }
1943    
1944 kumaneko 4063 /* Wait queue for kernel -> userspace notification. */
1945 kumaneko 2863 static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
1946 kumaneko 4063 /* Wait queue for userspace -> kernel notification. */
1947 kumaneko 4049 static DECLARE_WAIT_QUEUE_HEAD(ccs_answer_wait);
1948 kumaneko 2863
1949     /* Lock for manipulating ccs_query_list. */
1950     static DEFINE_SPINLOCK(ccs_query_list_lock);
1951    
1952     /* Structure for query. */
1953 kumaneko 3781 struct ccs_query {
1954 kumaneko 2863 struct list_head list;
1955     char *query;
1956     int query_len;
1957     unsigned int serial;
1958     int timer;
1959     int answer;
1960 kumaneko 4049 u8 retry;
1961 kumaneko 2863 };
1962    
1963 kumaneko 3781 /* The list for "struct ccs_query". */
1964 kumaneko 2863 static LIST_HEAD(ccs_query_list);
1965    
1966     /* Number of "struct file" referring /proc/ccs/query interface. */
1967     static atomic_t ccs_query_observers = ATOMIC_INIT(0);
1968    
1969 kumaneko 4063 /**
1970     * ccs_truncate - Truncate a line.
1971     *
1972     * @str: String to truncate.
1973     *
1974     * Returns length of truncated @str.
1975     */
1976 kumaneko 4049 static int ccs_truncate(char *str)
1977 kumaneko 3761 {
1978 kumaneko 4049 char *start = str;
1979     while (*(unsigned char *) str > (unsigned char) ' ')
1980 kumaneko 3761 str++;
1981     *str = '\0';
1982 kumaneko 4049 return strlen(start) + 1;
1983 kumaneko 3761 }
1984    
1985 kumaneko 4063 /**
1986     * ccs_add_entry - Add an ACL to current thread's domain. Used by learning mode.
1987     *
1988     * @header: Lines containing ACL.
1989     *
1990     * Returns nothing.
1991     */
1992 kumaneko 4049 static void ccs_add_entry(char *header)
1993     {
1994     char *buffer;
1995     char *realpath = NULL;
1996     char *argv0 = NULL;
1997     char *symlink = NULL;
1998     char *handler;
1999     char *cp = strchr(header, '\n');
2000     int len;
2001     if (!cp)
2002     return;
2003     cp = strchr(cp + 1, '\n');
2004     if (!cp)
2005     return;
2006     *cp++ = '\0';
2007     len = strlen(cp) + 1;
2008     /* strstr() will return NULL if ordering is wrong. */
2009     if (*cp == 'f') {
2010     argv0 = strstr(header, " argv[]={ \"");
2011     if (argv0) {
2012     argv0 += 10;
2013     len += ccs_truncate(argv0) + 14;
2014     }
2015     realpath = strstr(header, " exec={ realpath=\"");
2016     if (realpath) {
2017     realpath += 8;
2018     len += ccs_truncate(realpath) + 6;
2019     }
2020     symlink = strstr(header, " symlink.target=\"");
2021     if (symlink)
2022     len += ccs_truncate(symlink + 1) + 1;
2023     }
2024     handler = strstr(header, "type=execute_handler");
2025     if (handler)
2026     len += ccs_truncate(handler) + 6;
2027     buffer = kmalloc(len, CCS_GFP_FLAGS);
2028     if (!buffer)
2029     return;
2030     snprintf(buffer, len - 1, "%s", cp);
2031     if (handler)
2032     ccs_addprintf(buffer, len, " task.%s", handler);
2033     if (realpath)
2034     ccs_addprintf(buffer, len, " exec.%s", realpath);
2035     if (argv0)
2036     ccs_addprintf(buffer, len, " exec.argv[0]=%s", argv0);
2037     if (symlink)
2038     ccs_addprintf(buffer, len, "%s", symlink);
2039     ccs_normalize_line(buffer);
2040     if (!ccs_write_domain2(buffer, ccs_current_domain(), false))
2041     ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2042     kfree(buffer);
2043     }
2044    
2045 kumaneko 2863 /**
2046 kumaneko 2922 * ccs_supervisor - Ask for the supervisor's decision.
2047 kumaneko 2863 *
2048 kumaneko 3701 * @r: Pointer to "struct ccs_request_info".
2049     * @fmt: The printf()'s format string, followed by parameters.
2050 kumaneko 2863 *
2051     * Returns 0 if the supervisor decided to permit the access request which
2052 kumaneko 3494 * violated the policy in enforcing mode, CCS_RETRY_REQUEST if the supervisor
2053     * decided to retry the access request which violated the policy in enforcing
2054     * mode, 0 if it is not in enforcing mode, -EPERM otherwise.
2055 kumaneko 2863 */
2056 kumaneko 2922 int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)
2057 kumaneko 2863 {
2058     va_list args;
2059 kumaneko 4049 int error;
2060 kumaneko 2863 int len;
2061     static unsigned int ccs_serial;
2062 kumaneko 4049 struct ccs_query entry = { };
2063 kumaneko 2863 bool quota_exceeded = false;
2064 kumaneko 4055 va_start(args, fmt);
2065     len = vsnprintf((char *) &len, 1, fmt, args) + 1;
2066     va_end(args);
2067 kumaneko 4049 /* Write /proc/ccs/grant_log or /proc/ccs/reject_log . */
2068 kumaneko 3746 va_start(args, fmt);
2069 kumaneko 4055 ccs_write_log2(r, len, fmt, args);
2070 kumaneko 3746 va_end(args);
2071 kumaneko 4049 /* Nothing more to do if granted. */
2072     if (r->granted)
2073 kumaneko 2897 return 0;
2074 kumaneko 4049 if (r->mode)
2075     ccs_update_stat(r->mode);
2076     switch (r->mode) {
2077 kumaneko 2863 int i;
2078 kumaneko 4049 struct ccs_profile *p;
2079     case CCS_CONFIG_ENFORCING:
2080     error = -EPERM;
2081     if (atomic_read(&ccs_query_observers))
2082     break;
2083     if (ccs_current_flags() & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)
2084     goto out;
2085     p = ccs_profile(r->profile);
2086     /* Check enforcing_penalty parameter. */
2087     for (i = 0; i < p->pref[CCS_PREF_ENFORCING_PENALTY]; i++) {
2088 kumaneko 2863 set_current_state(TASK_INTERRUPTIBLE);
2089     schedule_timeout(HZ / 10);
2090     }
2091 kumaneko 4049 goto out;
2092     case CCS_CONFIG_LEARNING:
2093     error = 0;
2094     /* Check mac_learning_entry parameter. */
2095     if (ccs_domain_quota_ok(r))
2096     break;
2097     /* fall through */
2098     default:
2099     return 0;
2100 kumaneko 2863 }
2101 kumaneko 4049 /* Get message. */
2102     va_start(args, fmt);
2103 kumaneko 4055 entry.query = ccs_init_log(r, len, fmt, args);
2104 kumaneko 4049 va_end(args);
2105     if (!entry.query)
2106 kumaneko 2863 goto out;
2107 kumaneko 4049 entry.query_len = strlen(entry.query) + 1;
2108     if (!error) {
2109     ccs_add_entry(entry.query);
2110 kumaneko 2863 goto out;
2111 kumaneko 4049 }
2112 kumaneko 4055 len = ccs_round2(entry.query_len);
2113 kumaneko 2863 spin_lock(&ccs_query_list_lock);
2114 kumaneko 4049 if (ccs_memory_quota[CCS_MEMORY_QUERY] &&
2115     ccs_memory_used[CCS_MEMORY_QUERY] + len
2116     >= ccs_memory_quota[CCS_MEMORY_QUERY]) {
2117 kumaneko 2863 quota_exceeded = true;
2118     } else {
2119 kumaneko 4049 entry.serial = ccs_serial++;
2120     entry.retry = r->retry;
2121     ccs_memory_used[CCS_MEMORY_QUERY] += len;
2122     list_add_tail(&entry.list, &ccs_query_list);
2123 kumaneko 2863 }
2124     spin_unlock(&ccs_query_list_lock);
2125     if (quota_exceeded)
2126     goto out;
2127     /* Give 10 seconds for supervisor's opinion. */
2128 kumaneko 4049 while (entry.timer < 10) {
2129     wake_up_all(&ccs_query_wait);
2130     if (wait_event_interruptible_timeout
2131     (ccs_answer_wait, entry.answer ||
2132     !atomic_read(&ccs_query_observers), HZ))
2133 kumaneko 2863 break;
2134 kumaneko 4049 else
2135     entry.timer++;
2136 kumaneko 2863 }
2137     spin_lock(&ccs_query_list_lock);
2138 kumaneko 4049 list_del(&entry.list);
2139     ccs_memory_used[CCS_MEMORY_QUERY] -= len;
2140 kumaneko 2863 spin_unlock(&ccs_query_list_lock);
2141 kumaneko 4049 switch (entry.answer) {
2142 kumaneko 2863 case 3: /* Asked to retry by administrator. */
2143 kumaneko 3494 error = CCS_RETRY_REQUEST;
2144 kumaneko 2863 r->retry++;
2145     break;
2146     case 1:
2147     /* Granted by administrator. */
2148     error = 0;
2149     break;
2150     default:
2151 kumaneko 4049 /* Timed out or rejected by administrator. */
2152 kumaneko 2863 break;
2153     }
2154 kumaneko 4049 out:
2155     kfree(entry.query);
2156 kumaneko 2863 return error;
2157     }
2158    
2159     /**
2160     * ccs_poll_query - poll() for /proc/ccs/query.
2161     *
2162     * @file: Pointer to "struct file".
2163     * @wait: Pointer to "poll_table".
2164     *
2165     * Returns POLLIN | POLLRDNORM when ready to read, 0 otherwise.
2166     *
2167     * Waits for access requests which violated policy in enforcing mode.
2168     */
2169     static int ccs_poll_query(struct file *file, poll_table *wait)
2170     {
2171     struct list_head *tmp;
2172     bool found = false;
2173     u8 i;
2174     for (i = 0; i < 2; i++) {
2175     spin_lock(&ccs_query_list_lock);
2176     list_for_each(tmp, &ccs_query_list) {
2177 kumaneko 3781 struct ccs_query *ptr =
2178     list_entry(tmp, typeof(*ptr), list);
2179 kumaneko 2863 if (ptr->answer)
2180     continue;
2181     found = true;
2182     break;
2183     }
2184     spin_unlock(&ccs_query_list_lock);
2185     if (found)
2186     return POLLIN | POLLRDNORM;
2187     if (i)
2188     break;
2189     poll_wait(file, &ccs_query_wait, wait);
2190     }
2191     return 0;
2192     }
2193    
2194     /**
2195     * ccs_read_query - Read access requests which violated policy in enforcing mode.
2196     *
2197     * @head: Pointer to "struct ccs_io_buffer".
2198 kumaneko 4063 *
2199     * Returns nothing.
2200 kumaneko 2863 */
2201 kumaneko 2943 static void ccs_read_query(struct ccs_io_buffer *head)
2202 kumaneko 2863 {
2203     struct list_head *tmp;
2204     int pos = 0;
2205     int len = 0;
2206     char *buf;
2207 kumaneko 3780 if (head->r.w_pos)
2208 kumaneko 2943 return;
2209 kumaneko 2863 if (head->read_buf) {
2210     kfree(head->read_buf);
2211     head->read_buf = NULL;
2212     }
2213     spin_lock(&ccs_query_list_lock);
2214     list_for_each(tmp, &ccs_query_list) {
2215 kumaneko 3781 struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
2216 kumaneko 2863 if (ptr->answer)
2217     continue;
2218 kumaneko 3780 if (pos++ != head->r.query_index)
2219 kumaneko