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

Subversion リポジトリの参照

Annotation of /branches/ccs-patch/security/ccsecurity/policy_io.c

Parent Directory Parent Directory | Revision Log Revision Log


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