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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5594 - (hide annotations) (download) (as text)
Sun Nov 6 02:01:16 2011 UTC (12 years, 6 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 125163 byte(s)


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