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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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