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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26