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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2918 - (show annotations) (download) (as text)
Tue Aug 18 05:21:21 2009 UTC (14 years, 9 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 70093 byte(s)


1 /*
2 * security/ccsecurity/policy_io.c
3 *
4 * Copyright (C) 2005-2009 NTT DATA CORPORATION
5 *
6 * Version: 1.7.0-pre 2009/08/08
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 /* Lock for protecting ccs_profile->comment */
16 static DEFINE_SPINLOCK(ccs_profile_comment_lock);
17
18 /* String table for functionality that takes 2 modes. */
19 static const char *ccs_mode_2[2] = {
20 "disabled", "enabled"
21 };
22
23 static const char *ccs_keyword_mode[4] = {
24 "MAC_MODE_DISABLED", "MAC_MODE_LEARNING",
25 "MAC_MODE_PERMISSIVE", "MAC_MODE_ENFORCING"
26 };
27
28 static const char *ccs_keyword_audit[2] = {
29 "NO_AUDIT_GRANT_LOG", "NO_AUDIT_REJECT_LOG"
30 };
31
32 static const char *ccs_mac_keywords[CCS_MAX_MAC_INDEX +
33 CCS_MAX_CAPABILITY_INDEX] = {
34 [CCS_MAC_EXECUTE] = "execute",
35 [CCS_MAC_OPEN] = "open",
36 [CCS_MAC_CREATE] = "create",
37 [CCS_MAC_UNLINK] = "unlink",
38 [CCS_MAC_MKDIR] = "mkdir",
39 [CCS_MAC_RMDIR] = "rmdir",
40 [CCS_MAC_MKFIFO] = "mkfifo",
41 [CCS_MAC_MKSOCK] = "mksock",
42 [CCS_MAC_TRUNCATE] = "truncate",
43 [CCS_MAC_SYMLINK] = "symlink",
44 [CCS_MAC_REWRITE] = "rewrite",
45 [CCS_MAC_MKBLOCK] = "mkblock",
46 [CCS_MAC_MKCHAR] = "mkchar",
47 [CCS_MAC_LINK] = "link",
48 [CCS_MAC_RENAME] = "rename",
49 [CCS_MAC_CHMOD] = "chmod",
50 [CCS_MAC_CHOWN] = "chown",
51 [CCS_MAC_CHGRP] = "chgrp",
52 [CCS_MAC_IOCTL] = "ioctl",
53 [CCS_MAC_CHROOT] = "chroot",
54 [CCS_MAC_MOUNT] = "mount",
55 [CCS_MAC_UMOUNT] = "umount",
56 [CCS_MAC_PIVOT_ROOT] = "pivot_root",
57 [CCS_MAC_ENVIRON] = "env",
58 [CCS_MAC_NETWORK] = "network",
59 [CCS_MAC_SIGNAL] = "signal",
60 [CCS_MAX_MAC_INDEX + CCS_INET_STREAM_SOCKET_CREATE]
61 = "inet_tcp_create",
62 [CCS_MAX_MAC_INDEX + CCS_INET_STREAM_SOCKET_LISTEN]
63 = "inet_tcp_listen",
64 [CCS_MAX_MAC_INDEX + CCS_INET_STREAM_SOCKET_CONNECT]
65 = "inet_tcp_connect",
66 [CCS_MAX_MAC_INDEX + CCS_USE_INET_DGRAM_SOCKET] = "use_inet_udp",
67 [CCS_MAX_MAC_INDEX + CCS_USE_INET_RAW_SOCKET] = "use_inet_ip",
68 [CCS_MAX_MAC_INDEX + CCS_USE_ROUTE_SOCKET] = "use_route",
69 [CCS_MAX_MAC_INDEX + CCS_USE_PACKET_SOCKET] = "use_packet",
70 [CCS_MAX_MAC_INDEX + CCS_SYS_MOUNT] = "SYS_MOUNT",
71 [CCS_MAX_MAC_INDEX + CCS_SYS_UMOUNT] = "SYS_UMOUNT",
72 [CCS_MAX_MAC_INDEX + CCS_SYS_REBOOT] = "SYS_REBOOT",
73 [CCS_MAX_MAC_INDEX + CCS_SYS_CHROOT] = "SYS_CHROOT",
74 [CCS_MAX_MAC_INDEX + CCS_SYS_KILL] = "SYS_KILL",
75 [CCS_MAX_MAC_INDEX + CCS_SYS_VHANGUP] = "SYS_VHANGUP",
76 [CCS_MAX_MAC_INDEX + CCS_SYS_SETTIME] = "SYS_TIME",
77 [CCS_MAX_MAC_INDEX + CCS_SYS_NICE] = "SYS_NICE",
78 [CCS_MAX_MAC_INDEX + CCS_SYS_SETHOSTNAME] = "SYS_SETHOSTNAME",
79 [CCS_MAX_MAC_INDEX + CCS_USE_KERNEL_MODULE] = "use_kernel_module",
80 [CCS_MAX_MAC_INDEX + CCS_CREATE_FIFO] = "create_fifo",
81 [CCS_MAX_MAC_INDEX + CCS_CREATE_BLOCK_DEV] = "create_block_dev",
82 [CCS_MAX_MAC_INDEX + CCS_CREATE_CHAR_DEV] = "create_char_dev",
83 [CCS_MAX_MAC_INDEX + CCS_CREATE_UNIX_SOCKET] = "create_unix_socket",
84 [CCS_MAX_MAC_INDEX + CCS_SYS_LINK] = "SYS_LINK",
85 [CCS_MAX_MAC_INDEX + CCS_SYS_SYMLINK] = "SYS_SYMLINK",
86 [CCS_MAX_MAC_INDEX + CCS_SYS_RENAME] = "SYS_RENAME",
87 [CCS_MAX_MAC_INDEX + CCS_SYS_UNLINK] = "SYS_UNLINK",
88 [CCS_MAX_MAC_INDEX + CCS_SYS_CHMOD] = "SYS_CHMOD",
89 [CCS_MAX_MAC_INDEX + CCS_SYS_CHOWN] = "SYS_CHOWN",
90 [CCS_MAX_MAC_INDEX + CCS_SYS_IOCTL] = "SYS_IOCTL",
91 [CCS_MAX_MAC_INDEX + CCS_SYS_KEXEC_LOAD] = "SYS_KEXEC_LOAD",
92 [CCS_MAX_MAC_INDEX + CCS_SYS_PIVOT_ROOT] = "SYS_PIVOT_ROOT",
93 [CCS_MAX_MAC_INDEX + CCS_SYS_PTRACE] = "SYS_PTRACE",
94 [CCS_MAX_MAC_INDEX + CCS_CONCEAL_MOUNT] = "conceal_mount"
95 };
96
97 /* Table for profile. */
98 static struct {
99 const char *keyword;
100 unsigned int current_value;
101 const unsigned int max_value;
102 } ccs_control_array[CCS_MAX_CONTROL_INDEX] = {
103 [CCS_AUTOLEARN_EXEC_REALPATH] = { "AUTOLEARN_EXEC_REALPATH", 0, 1 },
104 [CCS_AUTOLEARN_EXEC_ARGV0] = { "AUTOLEARN_EXEC_ARGV0", 0, 1 },
105 [CCS_MAX_ACCEPT_ENTRY]
106 = { "MAX_ACCEPT_ENTRY", CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY, INT_MAX },
107 #ifdef CONFIG_CCSECURITY_AUDIT
108 [CCS_MAX_GRANT_LOG]
109 = { "MAX_GRANT_LOG", CONFIG_CCSECURITY_MAX_GRANT_LOG, INT_MAX },
110 [CCS_MAX_REJECT_LOG]
111 = { "MAX_REJECT_LOG", CONFIG_CCSECURITY_MAX_REJECT_LOG, INT_MAX },
112 #endif
113 [CCS_VERBOSE] = { "PRINT_VIOLATION", 1, 1 },
114 [CCS_SLEEP_PERIOD] = { "SLEEP_PERIOD", 0, 3000 }, /* in 0.1 second */
115 };
116
117 /* Permit policy management by non-root user? */
118 static bool ccs_manage_by_non_root;
119
120 /**
121 * ccs_cap2keyword - Convert capability operation to capability name.
122 *
123 * @operation: The capability index.
124 *
125 * Returns the name of the specified capability's name.
126 */
127 const char *ccs_cap2keyword(const u8 operation)
128 {
129 return operation < CCS_MAX_CAPABILITY_INDEX
130 ? ccs_mac_keywords[CCS_MAX_MAC_INDEX + operation] : NULL;
131 }
132
133 /**
134 * ccs_quiet_setup - Set CCS_VERBOSE=0 by default.
135 *
136 * @str: Unused.
137 *
138 * Returns 0.
139 */
140 static int __init ccs_quiet_setup(char *str)
141 {
142 ccs_control_array[CCS_VERBOSE].current_value = 0;
143 return 0;
144 }
145
146 __setup("CCS_QUIET", ccs_quiet_setup);
147
148 /**
149 * ccs_io_printf - Transactional printf() to "struct ccs_io_buffer" structure.
150 *
151 * @head: Pointer to "struct ccs_io_buffer".
152 * @fmt: The printf()'s format string, followed by parameters.
153 *
154 * Returns true on success, false otherwise.
155 *
156 * The snprintf() will truncate, but ccs_io_printf() won't.
157 */
158 bool ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
159 {
160 va_list args;
161 int len;
162 int pos = head->read_avail;
163 int size = head->readbuf_size - pos;
164 if (size <= 0)
165 return false;
166 va_start(args, fmt);
167 len = vsnprintf(head->read_buf + pos, size, fmt, args);
168 va_end(args);
169 if (pos + len >= head->readbuf_size)
170 return false;
171 head->read_avail += len;
172 return true;
173 }
174
175 /**
176 * ccs_find_or_assign_new_profile - Create a new profile.
177 *
178 * @profile: Profile number to create.
179 *
180 * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
181 */
182 static struct ccs_profile *ccs_find_or_assign_new_profile(const unsigned int
183 profile)
184 {
185 struct ccs_profile *ptr;
186 struct ccs_profile *entry;
187 int i;
188 if (profile >= CCS_MAX_PROFILES)
189 return NULL;
190 ptr = ccs_profile_ptr[profile];
191 if (ptr)
192 return ptr;
193 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
194 mutex_lock(&ccs_policy_lock);
195 ptr = ccs_profile_ptr[profile];
196 if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
197 ptr = entry;
198 for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++)
199 ptr->value[i] = ccs_control_array[i].current_value;
200 mb(); /* Avoid out-of-order execution. */
201 ccs_profile_ptr[profile] = ptr;
202 entry = NULL;
203 }
204 mutex_unlock(&ccs_policy_lock);
205 kfree(entry);
206 return ptr;
207 }
208
209 static int ccs_find_match(char *str)
210 {
211 int i;
212 if (ccs_str_starts(&str, CCS_KEYWORD_CAPABILITY))
213 for (i = 0; i < CCS_MAX_CAPABILITY_INDEX; i++) {
214 if (strcmp(str,
215 ccs_mac_keywords[CCS_MAX_MAC_INDEX + i]))
216 continue;
217 return CCS_MAX_MAC_INDEX + i;
218 }
219 else
220 for (i = 0; i < CCS_MAX_MAC_INDEX; i++) {
221 if (strcmp(str, ccs_mac_keywords[i]))
222 continue;
223 return i;
224 }
225 return -1;
226 }
227
228 /**
229 * ccs_write_profile - Write profile table.
230 *
231 * @head: Pointer to "struct ccs_io_buffer".
232 *
233 * Returns 0 on success, negative value otherwise.
234 */
235 static int ccs_write_profile(struct ccs_io_buffer *head)
236 {
237 char *data = head->write_buf;
238 unsigned int i;
239 unsigned int value;
240 int mode;
241 char *cp;
242 struct ccs_profile *ccs_profile;
243 i = simple_strtoul(data, &cp, 10);
244 if (data != cp) {
245 if (*cp != '-')
246 return -EINVAL;
247 data = cp + 1;
248 }
249 ccs_profile = ccs_find_or_assign_new_profile(i);
250 if (!ccs_profile)
251 return -EINVAL;
252 cp = strchr(data, '=');
253 if (!cp)
254 return -EINVAL;
255 *cp = '\0';
256 if (!strcmp(data, "COMMENT")) {
257 const struct ccs_path_info *new_comment
258 = ccs_get_name(cp + 1);
259 const struct ccs_path_info *old_comment;
260 /* Protect reader from ccs_put_name(). */
261 /***** CRITICAL SECTION START *****/
262 spin_lock(&ccs_profile_comment_lock);
263 old_comment = ccs_profile->comment;
264 ccs_profile->comment = new_comment;
265 spin_unlock(&ccs_profile_comment_lock);
266 /***** CRITICAL SECTION END *****/
267 ccs_put_name(old_comment);
268 return 0;
269 }
270 for (mode = 0; mode < 4; mode++) {
271 if (strcmp(data, ccs_keyword_mode[mode]))
272 continue;
273 cp++;
274 while (1) {
275 int index;
276 char *cp2 = strchr(cp, ' ');
277 if (cp2)
278 *cp2 = '\0';
279 index = ccs_find_match(cp);
280 if (index >= 0)
281 ccs_profile->mac_mode[index] = mode;
282 if (!cp2)
283 break;
284 cp = cp2 + 1;
285 }
286 return 0;
287 }
288 for (mode = 0; mode < 2; mode++) {
289 if (strcmp(data, ccs_keyword_audit[mode]))
290 continue;
291 memset(ccs_profile->dont_audit[mode], 0,
292 sizeof(ccs_profile->dont_audit[mode]));
293 cp++;
294 while (1) {
295 int index;
296 char *cp2 = strchr(cp, ' ');
297 if (cp2)
298 *cp2 = '\0';
299 index = ccs_find_match(cp);
300 if (index >= 0)
301 ccs_profile->dont_audit[mode][index] = true;
302 if (!cp2)
303 break;
304 cp = cp2 + 1;
305 }
306 return 0;
307 }
308 for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++) {
309 if (strcmp(data, ccs_control_array[i].keyword))
310 continue;
311 if (sscanf(cp + 1, "%u", &value) != 1) {
312 int j;
313 for (j = 0; j < 2; j++) {
314 if (strcmp(cp + 1, ccs_mode_2[j]))
315 continue;
316 value = j;
317 break;
318 }
319 if (j == 4)
320 return -EINVAL;
321 } else if (value > ccs_control_array[i].max_value) {
322 value = ccs_control_array[i].max_value;
323 }
324 ccs_profile->value[i] = value;
325 return 0;
326 }
327 return -EINVAL;
328 }
329
330 static bool ccs_print_mac_mode(struct ccs_io_buffer *head, u8 index)
331 {
332 const int pos = head->read_avail;
333 int i;
334 int mode;
335 const struct ccs_profile *ccs_profile = ccs_profile_ptr[index];
336 for (mode = 0; mode < 4; mode++) {
337 if (!ccs_io_printf(head, "%u-%s={", index,
338 ccs_keyword_mode[mode]))
339 goto out;
340 for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX;
341 i++) {
342 if (ccs_profile->mac_mode[i] != mode)
343 continue;
344 if (!ccs_io_printf(head, " %s%s",
345 i >= CCS_MAX_MAC_INDEX ?
346 CCS_KEYWORD_CAPABILITY : "",
347 ccs_mac_keywords[i]))
348 goto out;
349 }
350 if (!ccs_io_printf(head, " }\n"))
351 goto out;
352 }
353 return true;
354 out:
355 head->read_avail = pos;
356 return false;
357 }
358
359 static bool ccs_print_audit_mode(struct ccs_io_buffer *head, u8 index)
360 {
361 const int pos = head->read_avail;
362 int i;
363 int mode;
364 const struct ccs_profile *ccs_profile = ccs_profile_ptr[index];
365 for (mode = 0; mode < 2; mode++) {
366 if (!ccs_io_printf(head, "%u-%s={", index,
367 ccs_keyword_audit[mode]))
368 goto out;
369 for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX;
370 i++) {
371 if (!ccs_profile->dont_audit[mode][i])
372 continue;
373 if (!ccs_io_printf(head, " %s%s",
374 i >= CCS_MAX_MAC_INDEX ?
375 CCS_KEYWORD_CAPABILITY : "",
376 ccs_mac_keywords[i]))
377 goto out;
378 }
379 if (!ccs_io_printf(head, " }\n"))
380 goto out;
381 }
382 return true;
383 out:
384 head->read_avail = pos;
385 return false;
386 }
387
388 /**
389 * ccs_read_profile - Read profile table.
390 *
391 * @head: Pointer to "struct ccs_io_buffer".
392 *
393 * Returns 0.
394 */
395 static int ccs_read_profile(struct ccs_io_buffer *head)
396 {
397 static const int ccs_total = CCS_MAX_CONTROL_INDEX + 2;
398 int step;
399 if (head->read_eof)
400 return 0;
401 for (step = head->read_step; step < CCS_MAX_PROFILES * ccs_total;
402 step++) {
403 const u8 index = step / ccs_total;
404 u8 type = step % ccs_total;
405 const struct ccs_profile *ccs_profile = ccs_profile_ptr[index];
406 head->read_step = step;
407 if (!ccs_profile)
408 continue;
409 if (!type) { /* Print profile' comment tag. */
410 bool done;
411 /***** CRITICAL SECTION START *****/
412 spin_lock(&ccs_profile_comment_lock);
413 done = ccs_io_printf(head, "%u-COMMENT=%s\n",
414 index, ccs_profile->comment ?
415 ccs_profile->comment->name : "");
416 spin_unlock(&ccs_profile_comment_lock);
417 /***** CRITICAL SECTION END *****/
418 if (!done)
419 break;
420 continue;
421 } else if (type == 1) {
422 if (!ccs_print_mac_mode(head, index))
423 break;
424 continue;
425 } else if (type == 2) {
426 if (!ccs_print_audit_mode(head, index))
427 break;
428 continue;
429 }
430 type -= 3;
431 {
432 const unsigned int value = ccs_profile->value[type];
433 const char *keyword = ccs_control_array[type].keyword;
434 if (ccs_control_array[type].max_value == 1) {
435 if (!ccs_io_printf(head, "%u-%s=%s\n", index,
436 keyword, ccs_mode_2[value]))
437 break;
438 } else {
439 if (!ccs_io_printf(head, "%u-%s=%u\n", index,
440 keyword, value))
441 break;
442 }
443 }
444 }
445 if (step == CCS_MAX_PROFILES * ccs_total)
446 head->read_eof = true;
447 return 0;
448 }
449
450 /* The list for "struct ccs_policy_manager_entry". */
451 LIST_HEAD(ccs_policy_manager_list);
452
453 /**
454 * ccs_update_manager_entry - Add a manager entry.
455 *
456 * @manager: The path to manager or the domainnamme.
457 * @is_delete: True if it is a delete request.
458 *
459 * Returns 0 on success, negative value otherwise.
460 */
461 static int ccs_update_manager_entry(const char *manager, const bool is_delete)
462 {
463 struct ccs_policy_manager_entry *entry = NULL;
464 struct ccs_policy_manager_entry *ptr;
465 struct ccs_policy_manager_entry e = { };
466 int error = is_delete ? -ENOENT : -ENOMEM;
467 if (ccs_is_domain_def(manager)) {
468 if (!ccs_is_correct_domain(manager))
469 return -EINVAL;
470 e.is_domain = true;
471 } else {
472 if (!ccs_is_correct_path(manager, 1, -1, -1))
473 return -EINVAL;
474 }
475 e.manager = ccs_get_name(manager);
476 if (!e.manager)
477 return -ENOMEM;
478 if (!is_delete)
479 entry = kmalloc(sizeof(e), GFP_KERNEL);
480 mutex_lock(&ccs_policy_lock);
481 list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
482 if (ptr->manager != e.manager)
483 continue;
484 ptr->is_deleted = is_delete;
485 error = 0;
486 break;
487 }
488 if (!is_delete && error && ccs_commit_ok(entry, &e, sizeof(e))) {
489 list_add_tail_rcu(&entry->list, &ccs_policy_manager_list);
490 entry = NULL;
491 error = 0;
492 }
493 mutex_unlock(&ccs_policy_lock);
494 ccs_put_name(e.manager);
495 kfree(entry);
496 return error;
497 }
498
499 /**
500 * ccs_write_manager_policy - Write manager policy.
501 *
502 * @head: Pointer to "struct ccs_io_buffer".
503 *
504 * Returns 0 on success, negative value otherwise.
505 */
506 static int ccs_write_manager_policy(struct ccs_io_buffer *head)
507 {
508 char *data = head->write_buf;
509 bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);
510 if (!strcmp(data, "manage_by_non_root")) {
511 ccs_manage_by_non_root = !is_delete;
512 return 0;
513 }
514 return ccs_update_manager_entry(data, is_delete);
515 }
516
517 /**
518 * ccs_read_manager_policy - Read manager policy.
519 *
520 * @head: Pointer to "struct ccs_io_buffer".
521 *
522 * Returns 0.
523 *
524 * Caller holds ccs_read_lock().
525 */
526 static int ccs_read_manager_policy(struct ccs_io_buffer *head)
527 {
528 struct list_head *pos;
529 ccs_check_read_lock();
530 if (head->read_eof)
531 return 0;
532 list_for_each_cookie(pos, head->read_var2, &ccs_policy_manager_list) {
533 struct ccs_policy_manager_entry *ptr;
534 ptr = list_entry(pos, struct ccs_policy_manager_entry, list);
535 if (ptr->is_deleted)
536 continue;
537 if (!ccs_io_printf(head, "%s\n", ptr->manager->name))
538 return 0;
539 }
540 head->read_eof = true;
541 return 0;
542 }
543
544 /**
545 * ccs_is_policy_manager - Check whether the current process is a policy manager.
546 *
547 * Returns true if the current process is permitted to modify policy
548 * via /proc/ccs/ interface.
549 *
550 * Caller holds ccs_read_lock().
551 */
552 static bool ccs_is_policy_manager(void)
553 {
554 struct ccs_policy_manager_entry *ptr;
555 const char *exe;
556 struct task_struct *task = current;
557 const struct ccs_path_info *domainname
558 = ccs_current_domain()->domainname;
559 bool found = false;
560 ccs_check_read_lock();
561 if (!ccs_policy_loaded)
562 return true;
563 if (task->ccs_flags & CCS_TASK_IS_POLICY_MANAGER)
564 return true;
565 if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
566 return false;
567 list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
568 if (!ptr->is_deleted && ptr->is_domain
569 && !ccs_pathcmp(domainname, ptr->manager)) {
570 /* Set manager flag. */
571 task->ccs_flags |= CCS_TASK_IS_POLICY_MANAGER;
572 return true;
573 }
574 }
575 exe = ccs_get_exe();
576 if (!exe)
577 return false;
578 list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
579 if (!ptr->is_deleted && !ptr->is_domain
580 && !strcmp(exe, ptr->manager->name)) {
581 found = true;
582 /* Set manager flag. */
583 task->ccs_flags |= CCS_TASK_IS_POLICY_MANAGER;
584 break;
585 }
586 }
587 if (!found) { /* Reduce error messages. */
588 static pid_t ccs_last_pid;
589 const pid_t pid = current->pid;
590 if (ccs_last_pid != pid) {
591 printk(KERN_WARNING "%s ( %s ) is not permitted to "
592 "update policies.\n", domainname->name, exe);
593 ccs_last_pid = pid;
594 }
595 }
596 kfree(exe);
597 return found;
598 }
599
600 /**
601 * ccs_find_condition_part - Find condition part from the statement.
602 *
603 * @data: String to parse.
604 *
605 * Returns pointer to the condition part if it was found in the statement,
606 * NULL otherwise.
607 */
608 static char *ccs_find_condition_part(char *data)
609 {
610 char *cp = strstr(data, " if ");
611 if (cp) {
612 while (1) {
613 char *cp2 = strstr(cp + 3, " if ");
614 if (!cp2)
615 break;
616 cp = cp2;
617 }
618 *cp++ = '\0';
619 } else {
620 cp = strstr(data, " ; set ");
621 if (cp)
622 *cp++ = '\0';
623 }
624 return cp;
625 }
626
627 /**
628 * ccs_is_select_one - Parse select command.
629 *
630 * @head: Pointer to "struct ccs_io_buffer".
631 * @data: String to parse.
632 *
633 * Returns true on success, false otherwise.
634 *
635 * Caller holds ccs_read_lock().
636 */
637 static bool ccs_is_select_one(struct ccs_io_buffer *head, const char *data)
638 {
639 unsigned int pid;
640 struct ccs_domain_info *domain = NULL;
641 ccs_check_read_lock();
642 if (!strcmp(data, "allow_execute")) {
643 head->read_execute_only = true;
644 return true;
645 }
646 if (sscanf(data, "pid=%u", &pid) == 1) {
647 struct task_struct *p;
648 /***** CRITICAL SECTION START *****/
649 read_lock(&tasklist_lock);
650 p = find_task_by_pid(pid);
651 if (p)
652 domain = ccs_task_domain(p);
653 read_unlock(&tasklist_lock);
654 /***** CRITICAL SECTION END *****/
655 } else if (!strncmp(data, "domain=", 7)) {
656 if (ccs_is_domain_def(data + 7))
657 domain = ccs_find_domain(data + 7);
658 } else
659 return false;
660 head->write_var1 = domain;
661 /* Accessing read_buf is safe because head->io_sem is held. */
662 if (!head->read_buf)
663 return true; /* Do nothing if open(O_WRONLY). */
664 head->read_avail = 0;
665 ccs_io_printf(head, "# select %s\n", data);
666 head->read_single_domain = true;
667 head->read_eof = !domain;
668 if (domain) {
669 struct ccs_domain_info *d;
670 head->read_var1 = NULL;
671 list_for_each_entry_rcu(d, &ccs_domain_list, list) {
672 if (d == domain)
673 break;
674 head->read_var1 = &d->list;
675 }
676 head->read_var2 = NULL;
677 head->read_bit = 0;
678 head->read_step = 0;
679 if (domain->is_deleted)
680 ccs_io_printf(head, "# This is a deleted domain.\n");
681 }
682 return true;
683 }
684
685 static int ccs_write_domain_policy2(char *data, struct ccs_domain_info *domain,
686 struct ccs_condition *cond,
687 const bool is_delete)
688 {
689 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CAPABILITY))
690 return ccs_write_capability_policy(data, domain, cond,
691 is_delete);
692 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_NETWORK))
693 return ccs_write_network_policy(data, domain, cond, is_delete);
694 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_SIGNAL))
695 return ccs_write_signal_policy(data, domain, cond, is_delete);
696 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV))
697 return ccs_write_env_policy(data, domain, cond, is_delete);
698 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_MOUNT))
699 return ccs_write_mount_policy(data, domain, cond, is_delete);
700 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_UNMOUNT))
701 return ccs_write_umount_policy(data, domain, cond, is_delete);
702 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CHROOT))
703 return ccs_write_chroot_policy(data, domain, cond, is_delete);
704 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_PIVOT_ROOT))
705 return ccs_write_pivot_root_policy(data, domain, cond,
706 is_delete);
707 return ccs_write_file_policy(data, domain, cond, is_delete);
708 }
709
710 /**
711 * ccs_write_domain_policy - Write domain policy.
712 *
713 * @head: Pointer to "struct ccs_io_buffer".
714 *
715 * Returns 0 on success, negative value otherwise.
716 */
717 static int ccs_write_domain_policy(struct ccs_io_buffer *head)
718 {
719 char *data = head->write_buf;
720 struct ccs_domain_info *domain = head->write_var1;
721 bool is_delete = false;
722 bool is_select = false;
723 unsigned int profile;
724 struct ccs_condition *cond = NULL;
725 char *cp;
726 int error;
727 if (ccs_str_starts(&data, CCS_KEYWORD_DELETE))
728 is_delete = true;
729 else if (ccs_str_starts(&data, CCS_KEYWORD_SELECT))
730 is_select = true;
731 if (is_select && ccs_is_select_one(head, data))
732 return 0;
733 /* Don't allow updating policies by non manager programs. */
734 if (!ccs_is_policy_manager())
735 return -EPERM;
736 if (ccs_is_domain_def(data)) {
737 domain = NULL;
738 if (is_delete)
739 ccs_delete_domain(data);
740 else if (is_select)
741 domain = ccs_find_domain(data);
742 else
743 domain = ccs_find_or_assign_new_domain(data, 0);
744 head->write_var1 = domain;
745 return 0;
746 }
747 if (!domain)
748 return -EINVAL;
749
750 if (sscanf(data, CCS_KEYWORD_USE_PROFILE "%u", &profile) == 1
751 && profile < CCS_MAX_PROFILES) {
752 if (ccs_profile_ptr[profile] || !ccs_policy_loaded)
753 domain->profile = (u8) profile;
754 return 0;
755 }
756 if (!strcmp(data, CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
757 domain->ignore_global_allow_read = !is_delete;
758 return 0;
759 }
760 if (!strcmp(data, CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV)) {
761 domain->ignore_global_allow_env = !is_delete;
762 return 0;
763 }
764 cp = ccs_find_condition_part(data);
765 if (cp) {
766 cond = ccs_get_condition(cp);
767 if (!cond)
768 return -EINVAL;
769 }
770 error = ccs_write_domain_policy2(data, domain, cond, is_delete);
771 if (cond)
772 ccs_put_condition(cond);
773 return error;
774 }
775
776 static bool ccs_print_name_union(struct ccs_io_buffer *head,
777 const struct ccs_name_union *ptr)
778 {
779 int pos = head->read_avail;
780 if (pos && head->read_buf[pos - 1] == ' ')
781 head->read_avail--;
782 if (ptr->is_group)
783 return ccs_io_printf(head, " @%s",
784 ptr->group->group_name->name);
785 return ccs_io_printf(head, " %s", ptr->filename->name);
786 }
787
788 static bool ccs_print_name_union_quoted(struct ccs_io_buffer *head,
789 const struct ccs_name_union *ptr)
790 {
791 if (ptr->is_group)
792 return ccs_io_printf(head, "@%s",
793 ptr->group->group_name->name);
794 return ccs_io_printf(head, "\"%s\"", ptr->filename->name);
795 }
796
797 static bool ccs_print_number_union_common(struct ccs_io_buffer *head,
798 const struct ccs_number_union *ptr,
799 const bool need_space)
800 {
801 unsigned long min;
802 unsigned long max;
803 u8 min_type;
804 u8 max_type;
805 if (need_space && !ccs_io_printf(head, " "))
806 return false;
807 if (ptr->is_group)
808 return ccs_io_printf(head, "@%s",
809 ptr->group->group_name->name);
810 min_type = ptr->min_type;
811 max_type = ptr->max_type;
812 min = ptr->values[0];
813 max = ptr->values[1];
814 switch (min_type) {
815 case CCS_VALUE_TYPE_HEXADECIMAL:
816 if (!ccs_io_printf(head, "0x%lX", min))
817 return false;
818 break;
819 case CCS_VALUE_TYPE_OCTAL:
820 if (!ccs_io_printf(head, "0%lo", min))
821 return false;
822 break;
823 default:
824 if (!ccs_io_printf(head, "%lu", min))
825 return false;
826 break;
827 }
828 if (min == max && min_type == max_type)
829 return true;
830 switch (max_type) {
831 case CCS_VALUE_TYPE_HEXADECIMAL:
832 return ccs_io_printf(head, "-0x%lX", max);
833 case CCS_VALUE_TYPE_OCTAL:
834 return ccs_io_printf(head, "-0%lo", max);
835 default:
836 return ccs_io_printf(head, "-%lu", max);
837 }
838 }
839
840 bool ccs_print_number_union(struct ccs_io_buffer *head,
841 const struct ccs_number_union *ptr)
842 {
843 return ccs_print_number_union_common(head, ptr, true);
844 }
845
846 static bool ccs_print_number_union_nospace(struct ccs_io_buffer *head,
847 const struct ccs_number_union *ptr)
848 {
849 return ccs_print_number_union_common(head, ptr, false);
850 }
851
852 /**
853 * ccs_print_condition - Print condition part.
854 *
855 * @head: Pointer to "struct ccs_io_buffer".
856 * @cond: Pointer to "struct ccs_condition". May be NULL.
857 *
858 * Returns true on success, false otherwise.
859 */
860 static bool ccs_print_condition(struct ccs_io_buffer *head,
861 const struct ccs_condition *cond)
862 {
863 const struct ccs_condition_element *condp;
864 const struct ccs_number_union *numbers_p;
865 const struct ccs_name_union *names_p;
866 const struct ccs_argv_entry *argv;
867 const struct ccs_envp_entry *envp;
868 u16 condc;
869 u16 i;
870 u16 j;
871 char buffer[32];
872 if (!cond)
873 goto no_condition;
874 condc = cond->condc;
875 condp = (const struct ccs_condition_element *) (cond + 1);
876 numbers_p = (const struct ccs_number_union *) (condp + condc);
877 names_p = (const struct ccs_name_union *)
878 (numbers_p + cond->numbers_count);
879 argv = (const struct ccs_argv_entry *) (names_p + cond->names_count);
880 envp = (const struct ccs_envp_entry *) (argv + cond->argc);
881 memset(buffer, 0, sizeof(buffer));
882 if (condc && !ccs_io_printf(head, "%s", " if"))
883 goto out;
884 for (i = 0; i < condc; i++) {
885 const u8 match = condp->equals;
886 const u8 left = condp->left;
887 const u8 right = condp->right;
888 condp++;
889 switch (left) {
890 case CCS_ARGV_ENTRY:
891 if (!ccs_io_printf(head, " exec.argv[%u]%s\"%s\"",
892 argv->index, argv->is_not ?
893 "!=" : "=", argv->value->name))
894 goto out;
895 argv++;
896 continue;
897 case CCS_ENVP_ENTRY:
898 if (!ccs_io_printf(head, " exec.envp[\"%s\"]%s",
899 envp->name->name, envp->is_not ?
900 "!=" : "="))
901 goto out;
902 if (envp->value) {
903 if (!ccs_io_printf(head, "\"%s\"",
904 envp->value->name))
905 goto out;
906 } else {
907 if (!ccs_io_printf(head, "NULL"))
908 goto out;
909 }
910 envp++;
911 continue;
912 case CCS_NUMBER_UNION:
913 if (!ccs_print_number_union(head, numbers_p++))
914 goto out;
915 break;
916 default:
917 if (left >= CCS_MAX_CONDITION_KEYWORD)
918 goto out;
919 if (!ccs_io_printf(head, " %s",
920 ccs_condition_keyword[left]))
921 goto out;
922 break;
923 }
924 if (!ccs_io_printf(head, "%s", match ? "=" : "!="))
925 goto out;
926 switch (right) {
927 case CCS_NAME_UNION:
928 if (!ccs_print_name_union_quoted(head, names_p++))
929 goto out;
930 break;
931 case CCS_NUMBER_UNION:
932 if (!ccs_print_number_union_nospace(head, numbers_p++))
933 goto out;
934 break;
935 default:
936 if (right >= CCS_MAX_CONDITION_KEYWORD)
937 goto out;
938 if (!ccs_io_printf(head, "%s",
939 ccs_condition_keyword[right]))
940 goto out;
941 break;
942 }
943 }
944 i = cond->post_state[3];
945 if (!i)
946 goto no_condition;
947 if (!ccs_io_printf(head, " ; set"))
948 goto out;
949 for (j = 0; j < 3; j++) {
950 if (!(i & (1 << j)))
951 continue;
952 if (!ccs_io_printf(head, " task.state[%u]=%u", j,
953 cond->post_state[j]))
954 goto out;
955 }
956 no_condition:
957 if (ccs_io_printf(head, "\n"))
958 return true;
959 out:
960 return false;
961 }
962
963 /**
964 * ccs_print_path_acl - Print a single path ACL entry.
965 *
966 * @head: Pointer to "struct ccs_io_buffer".
967 * @ptr: Pointer to "struct ccs_path_acl".
968 * @cond: Pointer to "struct ccs_condition". May be NULL.
969 *
970 * Returns true on success, false otherwise.
971 */
972 static bool ccs_print_path_acl(struct ccs_io_buffer *head,
973 struct ccs_path_acl *ptr,
974 const struct ccs_condition *cond)
975 {
976 int pos;
977 u8 bit;
978 const u16 perm = ptr->perm;
979 for (bit = head->read_bit; bit < CCS_MAX_PATH_OPERATION; bit++) {
980 if (!(perm & (1 << bit)))
981 continue;
982 if (head->read_execute_only && bit != CCS_TYPE_EXECUTE)
983 continue;
984 /* Print "read/write" instead of "read" and "write". */
985 if ((bit == CCS_TYPE_READ || bit == CCS_TYPE_WRITE)
986 && (perm & (1 << CCS_TYPE_READ_WRITE)))
987 continue;
988 pos = head->read_avail;
989 if (!ccs_io_printf(head, "allow_%s", ccs_path2keyword(bit)) ||
990 !ccs_print_name_union(head, &ptr->name) ||
991 !ccs_print_condition(head, cond)) {
992 head->read_bit = bit;
993 head->read_avail = pos;
994 return false;
995 }
996 }
997 head->read_bit = 0;
998 return true;
999 }
1000
1001 /**
1002 * ccs_print_path_number_number_acl - Print a path_number_number ACL entry.
1003 *
1004 * @head: Pointer to "struct ccs_io_buffer".
1005 * @ptr: Pointer to "struct ccs_path_number_number_acl".
1006 * @cond: Pointer to "struct ccs_condition". May be NULL.
1007 *
1008 * Returns true on success, false otherwise.
1009 */
1010 static bool ccs_print_path_number_number_acl(struct ccs_io_buffer *head,
1011 struct ccs_path_number_number_acl *ptr,
1012 const struct ccs_condition *cond)
1013 {
1014 int pos;
1015 u8 bit;
1016 const u16 perm = ptr->perm;
1017 for (bit = head->read_bit; bit < CCS_MAX_PATH_NUMBER_NUMBER_OPERATION;
1018 bit++) {
1019 if (!(perm & (1 << bit)))
1020 continue;
1021 pos = head->read_avail;
1022 if (!ccs_io_printf(head, "allow_%s",
1023 ccs_path_number_number2keyword(bit)) ||
1024 !ccs_print_name_union(head, &ptr->name) ||
1025 !ccs_print_number_union(head, &ptr->major) ||
1026 !ccs_print_number_union(head, &ptr->minor) ||
1027 !ccs_print_condition(head, cond)) {
1028 head->read_bit = bit;
1029 head->read_avail = pos;
1030 return false;
1031 }
1032 }
1033 head->read_bit = 0;
1034 return true;
1035 }
1036
1037 /**
1038 * ccs_print_path_path_acl - Print a double path ACL entry.
1039 *
1040 * @head: Pointer to "struct ccs_io_buffer".
1041 * @ptr: Pointer to "struct ccs_path_path_acl".
1042 * @cond: Pointer to "struct ccs_condition". May be NULL.
1043 *
1044 * Returns true on success, false otherwise.
1045 */
1046 static bool ccs_print_path_path_acl(struct ccs_io_buffer *head,
1047 struct ccs_path_path_acl *ptr,
1048 const struct ccs_condition *cond)
1049 {
1050 int pos;
1051 u8 bit;
1052 const u8 perm = ptr->perm;
1053 for (bit = head->read_bit; bit < CCS_MAX_PATH_PATH_OPERATION; bit++) {
1054 if (!(perm & (1 << bit)))
1055 continue;
1056 pos = head->read_avail;
1057 if (!ccs_io_printf(head, "allow_%s",
1058 ccs_path_path2keyword(bit)) ||
1059 !ccs_print_name_union(head, &ptr->name1) ||
1060 !ccs_print_name_union(head, &ptr->name2) ||
1061 !ccs_print_condition(head, cond)) {
1062 head->read_bit = bit;
1063 head->read_avail = pos;
1064 return false;
1065 }
1066 }
1067 head->read_bit = 0;
1068 return true;
1069 }
1070
1071 /**
1072 * ccs_print_path_number_acl - Print an ioctl/chmod/chown/chgrp ACL entry.
1073 *
1074 * @head: Pointer to "struct ccs_io_buffer".
1075 * @ptr: Pointer to "struct ccs_path_number_acl".
1076 * @cond: Pointer to "struct ccs_condition". May be NULL.
1077 *
1078 * Returns true on success, false otherwise.
1079 */
1080 static bool ccs_print_path_number_acl(struct ccs_io_buffer *head,
1081 struct ccs_path_number_acl *ptr,
1082 const struct ccs_condition *cond)
1083 {
1084 int pos;
1085 u8 bit;
1086 const u8 perm = ptr->perm;
1087 for (bit = head->read_bit; bit < CCS_MAX_PATH_NUMBER_OPERATION;
1088 bit++) {
1089 if (!(perm & (1 << bit)))
1090 continue;
1091 pos = head->read_avail;
1092 if (!ccs_io_printf(head, "allow_%s",
1093 ccs_path_number2keyword(bit)) ||
1094 !ccs_print_name_union(head, &ptr->name) ||
1095 !ccs_print_number_union(head, &ptr->number) ||
1096 !ccs_print_condition(head, cond)) {
1097 head->read_bit = bit;
1098 head->read_avail = pos;
1099 return false;
1100 }
1101 }
1102 head->read_bit = 0;
1103 return true;
1104 }
1105
1106 /**
1107 * ccs_print_env_acl - Print an evironment variable name's ACL entry.
1108 *
1109 * @head: Pointer to "struct ccs_io_buffer".
1110 * @ptr: Pointer to "struct ccs_env_acl".
1111 * @cond: Pointer to "struct ccs_condition". May be NULL.
1112 *
1113 * Returns true on success, false otherwise.
1114 */
1115 static bool ccs_print_env_acl(struct ccs_io_buffer *head,
1116 struct ccs_env_acl *ptr,
1117 const struct ccs_condition *cond)
1118 {
1119 const int pos = head->read_avail;
1120 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_ENV "%s", ptr->env->name) ||
1121 !ccs_print_condition(head, cond)) {
1122 head->read_avail = pos;
1123 return false;
1124 }
1125 return true;
1126 }
1127
1128 /**
1129 * ccs_print_capability_acl - Print a capability ACL entry.
1130 *
1131 * @head: Pointer to "struct ccs_io_buffer".
1132 * @ptr: Pointer to "struct ccs_capability_acl".
1133 * @cond: Pointer to "struct ccs_condition". May be NULL.
1134 *
1135 * Returns true on success, false otherwise.
1136 */
1137 static bool ccs_print_capability_acl(struct ccs_io_buffer *head,
1138 struct ccs_capability_acl *ptr,
1139 const struct ccs_condition *cond)
1140 {
1141 const int pos = head->read_avail;
1142 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CAPABILITY "%s",
1143 ccs_cap2keyword(ptr->operation)) ||
1144 !ccs_print_condition(head, cond)) {
1145 head->read_avail = pos;
1146 return false;
1147 }
1148 return true;
1149 }
1150
1151 /**
1152 * ccs_print_ipv4_entry - Print IPv4 address of a network ACL entry.
1153 *
1154 * @head: Pointer to "struct ccs_io_buffer".
1155 * @ptr: Pointer to "struct ccs_ip_network_acl".
1156 *
1157 * Returns true on success, false otherwise.
1158 */
1159 static bool ccs_print_ipv4_entry(struct ccs_io_buffer *head,
1160 struct ccs_ip_network_acl *ptr)
1161 {
1162 const u32 min_address = ptr->address.ipv4.min;
1163 const u32 max_address = ptr->address.ipv4.max;
1164 if (!ccs_io_printf(head, "%u.%u.%u.%u", HIPQUAD(min_address)))
1165 return false;
1166 if (min_address != max_address
1167 && !ccs_io_printf(head, "-%u.%u.%u.%u", HIPQUAD(max_address)))
1168 return false;
1169 return true;
1170 }
1171
1172 /**
1173 * ccs_print_ipv6_entry - Print IPv6 address of a network ACL entry.
1174 *
1175 * @head: Pointer to "struct ccs_io_buffer".
1176 * @ptr: Pointer to "struct ccs_ip_network_acl".
1177 *
1178 * Returns true on success, false otherwise.
1179 */
1180 static bool ccs_print_ipv6_entry(struct ccs_io_buffer *head,
1181 struct ccs_ip_network_acl *ptr)
1182 {
1183 char buf[64];
1184 const struct in6_addr *min_address = ptr->address.ipv6.min;
1185 const struct in6_addr *max_address = ptr->address.ipv6.max;
1186 ccs_print_ipv6(buf, sizeof(buf), min_address);
1187 if (!ccs_io_printf(head, "%s", buf))
1188 return false;
1189 if (min_address != max_address) {
1190 ccs_print_ipv6(buf, sizeof(buf), max_address);
1191 if (!ccs_io_printf(head, "-%s", buf))
1192 return false;
1193 }
1194 return true;
1195 }
1196
1197 /**
1198 * ccs_print_network_acl - Print a network ACL entry.
1199 *
1200 * @head: Pointer to "struct ccs_io_buffer".
1201 * @ptr: Pointer to "struct ccs_ip_network_acl".
1202 * @cond: Pointer to "struct ccs_condition". May be NULL.
1203 *
1204 * Returns true on success, false otherwise.
1205 */
1206 static bool ccs_print_network_acl(struct ccs_io_buffer *head,
1207 struct ccs_ip_network_acl *ptr,
1208 const struct ccs_condition *cond)
1209 {
1210 int pos;
1211 u8 bit;
1212 const u16 perm = ptr->perm;
1213 for (bit = head->read_bit; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1214 if (!(perm & (1 << bit)))
1215 continue;
1216 pos = head->read_avail;
1217 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s ",
1218 ccs_net2keyword(bit)))
1219 goto out;
1220 switch (ptr->address_type) {
1221 case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:
1222 if (!ccs_io_printf(head, "@%s", ptr->address.group->
1223 group_name->name))
1224 goto out;
1225 break;
1226 case CCS_IP_ADDRESS_TYPE_IPv4:
1227 if (!ccs_print_ipv4_entry(head, ptr))
1228 goto out;
1229 break;
1230 case CCS_IP_ADDRESS_TYPE_IPv6:
1231 if (!ccs_print_ipv6_entry(head, ptr))
1232 goto out;
1233 break;
1234 }
1235 if (!ccs_print_number_union(head, &ptr->port) ||
1236 !ccs_print_condition(head, cond))
1237 goto out;
1238 }
1239 head->read_bit = 0;
1240 return true;
1241 out:
1242 head->read_bit = bit;
1243 head->read_avail = pos;
1244 return false;
1245 }
1246
1247 /**
1248 * ccs_print_signal_acl - Print a signal ACL entry.
1249 *
1250 * @head: Pointer to "struct ccs_io_buffer".
1251 * @ptr: Pointer to "struct signale_acl".
1252 * @cond: Pointer to "struct ccs_condition". May be NULL.
1253 *
1254 * Returns true on success, false otherwise.
1255 */
1256 static bool ccs_print_signal_acl(struct ccs_io_buffer *head,
1257 struct ccs_signal_acl *ptr,
1258 const struct ccs_condition *cond)
1259 {
1260 const int pos = head->read_avail;
1261 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u %s",
1262 ptr->sig, ptr->domainname->name) ||
1263 !ccs_print_condition(head, cond)) {
1264 head->read_avail = pos;
1265 return false;
1266 }
1267 return true;
1268 }
1269
1270 /**
1271 * ccs_print_execute_handler_record - Print an execute handler ACL entry.
1272 *
1273 * @head: Pointer to "struct ccs_io_buffer".
1274 * @keyword: Name of the keyword.
1275 * @ptr: Pointer to "struct ccs_execute_handler_record".
1276 *
1277 * Returns true on success, false otherwise.
1278 */
1279 static bool ccs_print_execute_handler_record(struct ccs_io_buffer *head,
1280 const char *keyword,
1281 struct ccs_execute_handler_record *
1282 ptr)
1283 {
1284 return ccs_io_printf(head, "%s %s\n", keyword, ptr->handler->name);
1285 }
1286
1287 /**
1288 * ccs_print_mount_acl - Print a mount ACL entry.
1289 *
1290 * @head: Pointer to "struct ccs_io_buffer".
1291 * @ptr: Pointer to "struct ccs_mount_acl".
1292 * @cond: Pointer to "struct ccs_condition". May be NULL.
1293 *
1294 * Returns true on success, false otherwise.
1295 */
1296 static bool ccs_print_mount_acl(struct ccs_io_buffer *head,
1297 struct ccs_mount_acl *ptr,
1298 const struct ccs_condition *cond)
1299 {
1300 const int pos = head->read_avail;
1301 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_MOUNT) ||
1302 !ccs_print_name_union(head, &ptr->dev_name) ||
1303 !ccs_print_name_union(head, &ptr->dir_name) ||
1304 !ccs_print_name_union(head, &ptr->fs_type) ||
1305 !ccs_print_number_union(head, &ptr->flags) ||
1306 !ccs_print_condition(head, cond)) {
1307 head->read_avail = pos;
1308 return false;
1309 }
1310 return true;
1311 }
1312
1313 /**
1314 * ccs_print_umount_acl - Print a mount ACL entry.
1315 *
1316 * @head: Pointer to "struct ccs_io_buffer".
1317 * @ptr: Pointer to "struct ccs_umount_acl".
1318 * @cond: Pointer to "struct ccs_condition". May be NULL.
1319 *
1320 * Returns true on success, false otherwise.
1321 */
1322 static bool ccs_print_umount_acl(struct ccs_io_buffer *head,
1323 struct ccs_umount_acl *ptr,
1324 const struct ccs_condition *cond)
1325 {
1326 const int pos = head->read_avail;
1327 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_UNMOUNT) ||
1328 !ccs_print_name_union(head, &ptr->dir) ||
1329 !ccs_print_condition(head, cond)) {
1330 head->read_avail = pos;
1331 return false;
1332 }
1333 return true;
1334 }
1335
1336 /**
1337 * ccs_print_chroot_acl - Print a chroot ACL entry.
1338 *
1339 * @head: Pointer to "struct ccs_io_buffer".
1340 * @ptr: Pointer to "struct ccs_chroot_acl".
1341 * @cond: Pointer to "struct ccs_condition". May be NULL.
1342 *
1343 * Returns true on success, false otherwise.
1344 */
1345 static bool ccs_print_chroot_acl(struct ccs_io_buffer *head,
1346 struct ccs_chroot_acl *ptr,
1347 const struct ccs_condition *cond)
1348 {
1349 const int pos = head->read_avail;
1350 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CHROOT) ||
1351 !ccs_print_name_union(head, &ptr->dir) ||
1352 !ccs_print_condition(head, cond)) {
1353 head->read_avail = pos;
1354 return false;
1355 }
1356 return true;
1357 }
1358
1359 /**
1360 * ccs_print_pivot_root_acl - Print a pivot_root ACL entry.
1361 *
1362 * @head: Pointer to "struct ccs_io_buffer".
1363 * @ptr: Pointer to "struct ccs_pivot_root_acl".
1364 * @cond: Pointer to "struct ccs_condition". May be NULL.
1365 *
1366 * Returns true on success, false otherwise.
1367 */
1368 static bool ccs_print_pivot_root_acl(struct ccs_io_buffer *head,
1369 struct ccs_pivot_root_acl *ptr,
1370 const struct ccs_condition *cond)
1371 {
1372 const int pos = head->read_avail;
1373 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_PIVOT_ROOT) ||
1374 !ccs_print_name_union(head, &ptr->new_root) ||
1375 !ccs_print_name_union(head, &ptr->old_root) ||
1376 !ccs_print_condition(head, cond)) {
1377 head->read_avail = pos;
1378 return false;
1379 }
1380 return true;
1381 }
1382
1383 /**
1384 * ccs_print_entry - Print an ACL entry.
1385 *
1386 * @head: Pointer to "struct ccs_io_buffer".
1387 * @ptr: Pointer to an ACL entry.
1388 *
1389 * Returns true on success, false otherwise.
1390 */
1391 static bool ccs_print_entry(struct ccs_io_buffer *head,
1392 struct ccs_acl_info *ptr)
1393 {
1394 const struct ccs_condition *cond = ptr->cond;
1395 const u8 acl_type = ptr->type;
1396 if (ptr->is_deleted)
1397 return true;
1398 if (acl_type == CCS_TYPE_PATH_ACL) {
1399 struct ccs_path_acl *acl
1400 = container_of(ptr, struct ccs_path_acl,
1401 head);
1402 return ccs_print_path_acl(head, acl, cond);
1403 }
1404 if (acl_type == CCS_TYPE_EXECUTE_HANDLER) {
1405 struct ccs_execute_handler_record *acl
1406 = container_of(ptr, struct ccs_execute_handler_record,
1407 head);
1408 const char *keyword = CCS_KEYWORD_EXECUTE_HANDLER;
1409 return ccs_print_execute_handler_record(head, keyword, acl);
1410 }
1411 if (acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
1412 struct ccs_execute_handler_record *acl
1413 = container_of(ptr, struct ccs_execute_handler_record,
1414 head);
1415 const char *keyword = CCS_KEYWORD_DENIED_EXECUTE_HANDLER;
1416 return ccs_print_execute_handler_record(head, keyword, acl);
1417 }
1418 if (head->read_execute_only)
1419 return true;
1420 if (acl_type == CCS_TYPE_PATH_NUMBER_NUMBER_ACL) {
1421 struct ccs_path_number_number_acl *acl
1422 = container_of(ptr, struct ccs_path_number_number_acl, head);
1423 return ccs_print_path_number_number_acl(head, acl, cond);
1424 }
1425 if (acl_type == CCS_TYPE_PATH_PATH_ACL) {
1426 struct ccs_path_path_acl *acl
1427 = container_of(ptr, struct ccs_path_path_acl,
1428 head);
1429 return ccs_print_path_path_acl(head, acl, cond);
1430 }
1431 if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
1432 struct ccs_path_number_acl *acl
1433 = container_of(ptr, struct ccs_path_number_acl,
1434 head);
1435 return ccs_print_path_number_acl(head, acl, cond);
1436 }
1437 if (acl_type == CCS_TYPE_ENV_ACL) {
1438 struct ccs_env_acl *acl
1439 = container_of(ptr, struct ccs_env_acl, head);
1440 return ccs_print_env_acl(head, acl, cond);
1441 }
1442 if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
1443 struct ccs_capability_acl *acl
1444 = container_of(ptr, struct ccs_capability_acl,
1445 head);
1446 return ccs_print_capability_acl(head, acl, cond);
1447 }
1448 if (acl_type == CCS_TYPE_IP_NETWORK_ACL) {
1449 struct ccs_ip_network_acl *acl
1450 = container_of(ptr, struct ccs_ip_network_acl,
1451 head);
1452 return ccs_print_network_acl(head, acl, cond);
1453 }
1454 if (acl_type == CCS_TYPE_SIGNAL_ACL) {
1455 struct ccs_signal_acl *acl
1456 = container_of(ptr, struct ccs_signal_acl, head);
1457 return ccs_print_signal_acl(head, acl, cond);
1458 }
1459 if (acl_type == CCS_TYPE_MOUNT_ACL) {
1460 struct ccs_mount_acl *acl
1461 = container_of(ptr, struct ccs_mount_acl, head);
1462 return ccs_print_mount_acl(head, acl, cond);
1463 }
1464 if (acl_type == CCS_TYPE_UMOUNT_ACL) {
1465 struct ccs_umount_acl *acl
1466 = container_of(ptr, struct ccs_umount_acl, head);
1467 return ccs_print_umount_acl(head, acl, cond);
1468 }
1469 if (acl_type == CCS_TYPE_CHROOT_ACL) {
1470 struct ccs_chroot_acl *acl
1471 = container_of(ptr, struct ccs_chroot_acl, head);
1472 return ccs_print_chroot_acl(head, acl, cond);
1473 }
1474 if (acl_type == CCS_TYPE_PIVOT_ROOT_ACL) {
1475 struct ccs_pivot_root_acl *acl
1476 = container_of(ptr, struct ccs_pivot_root_acl,
1477 head);
1478 return ccs_print_pivot_root_acl(head, acl, cond);
1479 }
1480 BUG(); /* This must not happen. */
1481 return false;
1482 }
1483
1484 /**
1485 * ccs_read_domain_policy - Read domain policy.
1486 *
1487 * @head: Pointer to "struct ccs_io_buffer".
1488 *
1489 * Returns 0.
1490 *
1491 * Caller holds ccs_read_lock().
1492 */
1493 static int ccs_read_domain_policy(struct ccs_io_buffer *head)
1494 {
1495 struct list_head *dpos;
1496 struct list_head *apos;
1497 ccs_check_read_lock();
1498 if (head->read_eof)
1499 return 0;
1500 if (head->read_step == 0)
1501 head->read_step = 1;
1502 list_for_each_cookie(dpos, head->read_var1, &ccs_domain_list) {
1503 struct ccs_domain_info *domain;
1504 const char *quota_exceeded = "";
1505 const char *transition_failed = "";
1506 const char *ignore_global_allow_read = "";
1507 const char *ignore_global_allow_env = "";
1508 domain = list_entry(dpos, struct ccs_domain_info, list);
1509 if (head->read_step != 1)
1510 goto acl_loop;
1511 if (domain->is_deleted && !head->read_single_domain)
1512 continue;
1513 /* Print domainname and flags. */
1514 if (domain->quota_warned)
1515 quota_exceeded = "quota_exceeded\n";
1516 if (domain->domain_transition_failed)
1517 transition_failed = "transition_failed\n";
1518 if (domain->ignore_global_allow_read)
1519 ignore_global_allow_read
1520 = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
1521 if (domain->ignore_global_allow_env)
1522 ignore_global_allow_env
1523 = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n";
1524 if (!ccs_io_printf(head, "%s\n" CCS_KEYWORD_USE_PROFILE "%u\n"
1525 "%s%s%s%s\n", domain->domainname->name,
1526 domain->profile, quota_exceeded,
1527 transition_failed,
1528 ignore_global_allow_read,
1529 ignore_global_allow_env))
1530 return 0;
1531 head->read_step = 2;
1532 acl_loop:
1533 if (head->read_step == 3)
1534 goto tail_mark;
1535 /* Print ACL entries in the domain. */
1536 list_for_each_cookie(apos, head->read_var2,
1537 &domain->acl_info_list) {
1538 struct ccs_acl_info *ptr
1539 = list_entry(apos, struct ccs_acl_info, list);
1540 if (!ccs_print_entry(head, ptr))
1541 return 0;
1542 }
1543 head->read_step = 3;
1544 tail_mark:
1545 if (!ccs_io_printf(head, "\n"))
1546 return 0;
1547 head->read_step = 1;
1548 if (head->read_single_domain)
1549 break;
1550 }
1551 head->read_eof = true;
1552 return 0;
1553 }
1554
1555 /**
1556 * ccs_write_domain_profile - Assign profile for specified domain.
1557 *
1558 * @head: Pointer to "struct ccs_io_buffer".
1559 *
1560 * Returns 0 on success, -EINVAL otherwise.
1561 *
1562 * This is equivalent to doing
1563 *
1564 * ( echo "select " $domainname; echo "use_profile " $profile ) |
1565 * /usr/lib/ccs/loadpolicy -d
1566 *
1567 * Caller holds ccs_read_lock().
1568 */
1569 static int ccs_write_domain_profile(struct ccs_io_buffer *head)
1570 {
1571 char *data = head->write_buf;
1572 char *cp = strchr(data, ' ');
1573 struct ccs_domain_info *domain;
1574 unsigned int profile;
1575 ccs_check_read_lock();
1576 if (!cp)
1577 return -EINVAL;
1578 *cp = '\0';
1579 profile = simple_strtoul(data, NULL, 10);
1580 if (profile >= CCS_MAX_PROFILES)
1581 return -EINVAL;
1582 domain = ccs_find_domain(cp + 1);
1583 if (domain && (ccs_profile_ptr[profile] || !ccs_policy_loaded))
1584 domain->profile = (u8) profile;
1585 return 0;
1586 }
1587
1588 /**
1589 * ccs_read_domain_profile - Read only domainname and profile.
1590 *
1591 * @head: Pointer to "struct ccs_io_buffer".
1592 *
1593 * Returns list of profile number and domainname pairs.
1594 *
1595 * This is equivalent to doing
1596 *
1597 * grep -A 1 '^<kernel>' /proc/ccs/domain_policy |
1598 * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
1599 * domainname = $0; } else if ( $1 == "use_profile" ) {
1600 * print $2 " " domainname; domainname = ""; } } ; '
1601 *
1602 * Caller holds ccs_read_lock().
1603 */
1604 static int ccs_read_domain_profile(struct ccs_io_buffer *head)
1605 {
1606 struct list_head *pos;
1607 ccs_check_read_lock();
1608 if (head->read_eof)
1609 return 0;
1610 list_for_each_cookie(pos, head->read_var1, &ccs_domain_list) {
1611 struct ccs_domain_info *domain;
1612 domain = list_entry(pos, struct ccs_domain_info, list);
1613 if (domain->is_deleted)
1614 continue;
1615 if (!ccs_io_printf(head, "%u %s\n", domain->profile,
1616 domain->domainname->name))
1617 return 0;
1618 }
1619 head->read_eof = true;
1620 return 0;
1621 }
1622
1623 /**
1624 * ccs_write_pid: Specify PID to obtain domainname.
1625 *
1626 * @head: Pointer to "struct ccs_io_buffer".
1627 *
1628 * Returns 0.
1629 */
1630 static int ccs_write_pid(struct ccs_io_buffer *head)
1631 {
1632 head->read_eof = false;
1633 return 0;
1634 }
1635
1636 /**
1637 * ccs_read_pid - Read information of a process.
1638 *
1639 * @head: Pointer to "struct ccs_io_buffer".
1640 *
1641 * Returns the domainname which the specified PID is in or
1642 * process information of the specified PID on success,
1643 * empty string otherwise.
1644 *
1645 * Caller holds ccs_read_lock().
1646 */
1647 static int ccs_read_pid(struct ccs_io_buffer *head)
1648 {
1649 char *buf = head->write_buf;
1650 bool task_info = false;
1651 unsigned int pid;
1652 struct task_struct *p;
1653 struct ccs_domain_info *domain = NULL;
1654 u32 ccs_flags = 0;
1655 ccs_check_read_lock();
1656 /* Accessing write_buf is safe because head->io_sem is held. */
1657 if (!buf)
1658 goto done; /* Do nothing if open(O_RDONLY). */
1659 if (head->read_avail || head->read_eof)
1660 goto done;
1661 head->read_eof = true;
1662 if (ccs_str_starts(&buf, "info "))
1663 task_info = true;
1664 pid = (unsigned int) simple_strtoul(buf, NULL, 10);
1665 /***** CRITICAL SECTION START *****/
1666 read_lock(&tasklist_lock);
1667 p = find_task_by_pid(pid);
1668 if (p) {
1669 domain = ccs_task_domain(p);
1670 ccs_flags = p->ccs_flags;
1671 }
1672 read_unlock(&tasklist_lock);
1673 /***** CRITICAL SECTION END *****/
1674 if (!domain)
1675 goto done;
1676 if (!task_info)
1677 ccs_io_printf(head, "%u %u %s", pid, domain->profile,
1678 domain->domainname->name);
1679 else
1680 ccs_io_printf(head, "%u manager=%s execute_handler=%s "
1681 "state[0]=%u state[1]=%u state[2]=%u", pid,
1682 ccs_flags & CCS_TASK_IS_POLICY_MANAGER ?
1683 "yes" : "no",
1684 ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER ?
1685 "yes" : "no",
1686 (u8) (ccs_flags >> 24),
1687 (u8) (ccs_flags >> 16),
1688 (u8) (ccs_flags >> 8));
1689 done:
1690 return 0;
1691 }
1692
1693 /**
1694 * ccs_write_exception_policy - Write exception policy.
1695 *
1696 * @head: Pointer to "struct ccs_io_buffer".
1697 *
1698 * Returns 0 on success, negative value otherwise.
1699 */
1700 static int ccs_write_exception_policy(struct ccs_io_buffer *head)
1701 {
1702 char *data = head->write_buf;
1703 bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);
1704 if (ccs_str_starts(&data, CCS_KEYWORD_KEEP_DOMAIN))
1705 return ccs_write_domain_keeper_policy(data, false, is_delete);
1706 if (ccs_str_starts(&data, CCS_KEYWORD_NO_KEEP_DOMAIN))
1707 return ccs_write_domain_keeper_policy(data, true, is_delete);
1708 if (ccs_str_starts(&data, CCS_KEYWORD_INITIALIZE_DOMAIN))
1709 return ccs_write_domain_initializer_policy(data, false,
1710 is_delete);
1711 if (ccs_str_starts(&data, CCS_KEYWORD_NO_INITIALIZE_DOMAIN))
1712 return ccs_write_domain_initializer_policy(data, true,
1713 is_delete);
1714 if (ccs_str_starts(&data, CCS_KEYWORD_AGGREGATOR))
1715 return ccs_write_aggregator_policy(data, is_delete);
1716 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_READ))
1717 return ccs_write_globally_readable_policy(data, is_delete);
1718 if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV))
1719 return ccs_write_globally_usable_env_policy(data, is_delete);
1720 if (ccs_str_starts(&data, CCS_KEYWORD_FILE_PATTERN))
1721 return ccs_write_pattern_policy(data, is_delete);
1722 if (ccs_str_starts(&data, CCS_KEYWORD_PATH_GROUP))
1723 return ccs_write_path_group_policy(data, is_delete);
1724 if (ccs_str_starts(&data, CCS_KEYWORD_NUMBER_GROUP))
1725 return ccs_write_number_group_policy(data, is_delete);
1726 if (ccs_str_starts(&data, CCS_KEYWORD_DENY_REWRITE))
1727 return ccs_write_no_rewrite_policy(data, is_delete);
1728 if (ccs_str_starts(&data, CCS_KEYWORD_ADDRESS_GROUP))
1729 return ccs_write_address_group_policy(data, is_delete);
1730 if (ccs_str_starts(&data, CCS_KEYWORD_DENY_AUTOBIND))
1731 return ccs_write_reserved_port_policy(data, is_delete);
1732 return -EINVAL;
1733 }
1734
1735 /**
1736 * ccs_read_exception_policy - Read exception policy.
1737 *
1738 * @head: Pointer to "struct ccs_io_buffer".
1739 *
1740 * Returns 0 on success, -EINVAL otherwise.
1741 *
1742 * Caller holds ccs_read_lock().
1743 */
1744 static int ccs_read_exception_policy(struct ccs_io_buffer *head)
1745 {
1746 ccs_check_read_lock();
1747 if (!head->read_eof) {
1748 switch (head->read_step) {
1749 case 0:
1750 head->read_var2 = NULL;
1751 head->read_step = 1;
1752 case 1:
1753 if (!ccs_read_domain_keeper_policy(head))
1754 break;
1755 head->read_var2 = NULL;
1756 head->read_step = 2;
1757 case 2:
1758 if (!ccs_read_globally_readable_policy(head))
1759 break;
1760 head->read_var2 = NULL;
1761 head->read_step = 3;
1762 case 3:
1763 if (!ccs_read_globally_usable_env_policy(head))
1764 break;
1765 head->read_var2 = NULL;
1766 head->read_step = 4;
1767 case 4:
1768 if (!ccs_read_domain_initializer_policy(head))
1769 break;
1770 head->read_var2 = NULL;
1771 head->read_step = 6;
1772 case 6:
1773 if (!ccs_read_aggregator_policy(head))
1774 break;
1775 head->read_var2 = NULL;
1776 head->read_step = 7;
1777 case 7:
1778 if (!ccs_read_file_pattern(head))
1779 break;
1780 head->read_var2 = NULL;
1781 head->read_step = 8;
1782 case 8:
1783 if (!ccs_read_no_rewrite_policy(head))
1784 break;
1785 head->read_var2 = NULL;
1786 head->read_step = 9;
1787 case 9:
1788 if (!ccs_read_path_group_policy(head))
1789 break;
1790 head->read_var1 = NULL;
1791 head->read_var2 = NULL;
1792 head->read_step = 10;
1793 case 10:
1794 if (!ccs_read_number_group_policy(head))
1795 break;
1796 head->read_var1 = NULL;
1797 head->read_var2 = NULL;
1798 head->read_step = 11;
1799 case 11:
1800 if (!ccs_read_address_group_policy(head))
1801 break;
1802 head->read_var2 = NULL;
1803 head->read_step = 12;
1804 case 12:
1805 if (!ccs_read_reserved_port_policy(head))
1806 break;
1807 head->read_eof = true;
1808 break;
1809 default:
1810 return -EINVAL;
1811 }
1812 }
1813 return 0;
1814 }
1815
1816 /**
1817 * ccs_get_argv0 - Get argv[0].
1818 *
1819 * @ee: Pointer to "struct ccs_execve_entry".
1820 *
1821 * Returns true on success, false otherwise.
1822 */
1823 static bool ccs_get_argv0(struct ccs_execve_entry *ee)
1824 {
1825 struct linux_binprm *bprm = ee->bprm;
1826 char *arg_ptr = ee->tmp;
1827 int arg_len = 0;
1828 unsigned long pos = bprm->p;
1829 int offset = pos % PAGE_SIZE;
1830 bool done = false;
1831 if (!bprm->argc)
1832 goto out;
1833 while (1) {
1834 if (!ccs_dump_page(bprm, pos, &ee->dump))
1835 goto out;
1836 pos += PAGE_SIZE - offset;
1837 /* Read. */
1838 while (offset < PAGE_SIZE) {
1839 const char *kaddr = ee->dump.data;
1840 const unsigned char c = kaddr[offset++];
1841 if (c && arg_len < CCS_MAX_PATHNAME_LEN - 10) {
1842 if (c == '\\') {
1843 arg_ptr[arg_len++] = '\\';
1844 arg_ptr[arg_len++] = '\\';
1845 } else if (c == '/') {
1846 arg_len = 0;
1847 } else if (c > ' ' && c < 127) {
1848 arg_ptr[arg_len++] = c;
1849 } else {
1850 arg_ptr[arg_len++] = '\\';
1851 arg_ptr[arg_len++] = (c >> 6) + '0';
1852 arg_ptr[arg_len++]
1853 = ((c >> 3) & 7) + '0';
1854 arg_ptr[arg_len++] = (c & 7) + '0';
1855 }
1856 } else {
1857 arg_ptr[arg_len] = '\0';
1858 done = true;
1859 break;
1860 }
1861 }
1862 offset = 0;
1863 if (done)
1864 break;
1865 }
1866 return true;
1867 out:
1868 return false;
1869 }
1870
1871 static struct ccs_condition *ccs_get_execute_condition(struct ccs_execve_entry
1872 *ee)
1873 {
1874 struct ccs_condition *cond;
1875 char *buf;
1876 int len = 256;
1877 char *realpath = NULL;
1878 char *argv0 = NULL;
1879 if (ccs_check_flags(NULL, CCS_AUTOLEARN_EXEC_REALPATH)) {
1880 struct file *file = ee->bprm->file;
1881 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
1882 struct path path = { file->f_vfsmnt, file->f_dentry };
1883 realpath = ccs_realpath_from_path(&path);
1884 #else
1885 realpath = ccs_realpath_from_path(&file->f_path);
1886 #endif
1887 if (realpath)
1888 len += strlen(realpath) + 17;
1889 }
1890 if (ccs_check_flags(NULL, CCS_AUTOLEARN_EXEC_REALPATH)) {
1891 if (ccs_get_argv0(ee)) {
1892 argv0 = ee->tmp;
1893 len += strlen(argv0) + 16;
1894 }
1895 }
1896 buf = kmalloc(len, GFP_KERNEL);
1897 if (!buf)
1898 return NULL;
1899 snprintf(buf, len - 1, "if");
1900 if (current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER) {
1901 const int pos = strlen(buf);
1902 snprintf(buf + pos, len - pos - 1,
1903 " task.type=execute_handler");
1904 }
1905 if (realpath) {
1906 const int pos = strlen(buf);
1907 snprintf(buf + pos, len - pos - 1, " exec.realpath=\"%s\"",
1908 realpath);
1909 kfree(realpath);
1910 }
1911 if (argv0) {
1912 const int pos = strlen(buf);
1913 snprintf(buf + pos, len - pos - 1, " exec.argv[0]=\"%s\"",
1914 argv0);
1915 }
1916 cond = ccs_get_condition(buf);
1917 kfree(buf);
1918 return cond;
1919 }
1920
1921 /* Wait queue for ccs_query_list. */
1922 static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
1923
1924 /* Lock for manipulating ccs_query_list. */
1925 static DEFINE_SPINLOCK(ccs_query_list_lock);
1926
1927 /* Structure for query. */
1928 struct ccs_query_entry {
1929 struct list_head list;
1930 char *query;
1931 int query_len;
1932 unsigned int serial;
1933 int timer;
1934 int answer;
1935 };
1936
1937 /* The list for "struct ccs_query_entry". */
1938 static LIST_HEAD(ccs_query_list);
1939
1940 /* Number of "struct file" referring /proc/ccs/query interface. */
1941 static atomic_t ccs_query_observers = ATOMIC_INIT(0);
1942
1943 /**
1944 * ccs_check_supervisor - Ask for the supervisor's decision.
1945 *
1946 * @r: Pointer to "struct ccs_request_info".
1947 * @fmt: The printf()'s format string, followed by parameters.
1948 *
1949 * Returns 0 if the supervisor decided to permit the access request which
1950 * violated the policy in enforcing mode, 1 if the supervisor decided to
1951 * retry the access request which violated the policy in enforcing mode,
1952 * 0 if it is not in enforcing mode, -EPERM otherwise.
1953 */
1954 int ccs_check_supervisor(struct ccs_request_info *r, const char *fmt, ...)
1955 {
1956 va_list args;
1957 int error = -EPERM;
1958 int pos;
1959 int len;
1960 static unsigned int ccs_serial;
1961 struct ccs_query_entry *ccs_query_entry = NULL;
1962 bool quota_exceeded = false;
1963 char *header;
1964 if (!r->domain)
1965 r->domain = ccs_current_domain();
1966 switch (r->mode) {
1967 char *buffer;
1968 struct ccs_condition *cond;
1969 case 1:
1970 if (!ccs_domain_quota_ok(r))
1971 return 0;
1972 va_start(args, fmt);
1973 len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4;
1974 va_end(args);
1975 buffer = kmalloc(len, GFP_KERNEL);
1976 if (!buffer)
1977 return 0;
1978 va_start(args, fmt);
1979 vsnprintf(buffer, len - 1, fmt, args);
1980 va_end(args);
1981 ccs_normalize_line(buffer);
1982 if (r->ee && !strncmp(buffer, "allow_execute ", 14))
1983 cond = ccs_get_execute_condition(r->ee);
1984 else if ((current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {
1985 char str[] = "if task.type=execute_handler";
1986 cond = ccs_get_condition(str);
1987 } else
1988 cond = NULL;
1989 ccs_write_domain_policy2(buffer, r->domain, cond, false);
1990 ccs_put_condition(cond);
1991 kfree(buffer);
1992 /* fall through */
1993 case 2:
1994 return 0;
1995 }
1996 if (!atomic_read(&ccs_query_observers)) {
1997 int i;
1998 if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)
1999 return -EPERM;
2000 for (i = 0; i < ccs_check_flags(r->domain, CCS_SLEEP_PERIOD);
2001 i++) {
2002 set_current_state(TASK_INTERRUPTIBLE);
2003 schedule_timeout(HZ / 10);
2004 }
2005 return -EPERM;
2006 }
2007 va_start(args, fmt);
2008 len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;
2009 va_end(args);
2010 header = ccs_init_audit_log(&len, r);
2011 if (!header)
2012 goto out;
2013 ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), GFP_KERNEL);
2014 if (!ccs_query_entry)
2015 goto out;
2016 len = ccs_round2(len);
2017 ccs_query_entry->query = kzalloc(len, GFP_KERNEL);
2018 if (!ccs_query_entry->query)
2019 goto out;
2020 INIT_LIST_HEAD(&ccs_query_entry->list);
2021 /***** CRITICAL SECTION START *****/
2022 spin_lock(&ccs_query_list_lock);
2023 if (ccs_quota_for_query && ccs_query_memory_size + len +
2024 sizeof(*ccs_query_entry) >= ccs_quota_for_query) {
2025 quota_exceeded = true;
2026 } else {
2027 ccs_query_memory_size += len + sizeof(*ccs_query_entry);
2028 ccs_query_entry->serial = ccs_serial++;
2029 }
2030 spin_unlock(&ccs_query_list_lock);
2031 /***** CRITICAL SECTION END *****/
2032 if (quota_exceeded)
2033 goto out;
2034 pos = snprintf(ccs_query_entry->query, len - 1, "Q%u-%hu\n%s",
2035 ccs_query_entry->serial, r->retry, header);
2036 kfree(header);
2037 header = NULL;
2038 va_start(args, fmt);
2039 vsnprintf(ccs_query_entry->query + pos, len - 1 - pos, fmt, args);
2040 ccs_query_entry->query_len = strlen(ccs_query_entry->query) + 1;
2041 va_end(args);
2042 /***** CRITICAL SECTION START *****/
2043 spin_lock(&ccs_query_list_lock);
2044 list_add_tail(&ccs_query_entry->list, &ccs_query_list);
2045 spin_unlock(&ccs_query_list_lock);
2046 /***** CRITICAL SECTION END *****/
2047 /* Give 10 seconds for supervisor's opinion. */
2048 for (ccs_query_entry->timer = 0;
2049 atomic_read(&ccs_query_observers) && ccs_query_entry->timer < 100;
2050 ccs_query_entry->timer++) {
2051 wake_up(&ccs_query_wait);
2052 set_current_state(TASK_INTERRUPTIBLE);
2053 schedule_timeout(HZ / 10);
2054 if (ccs_query_entry->answer)
2055 break;
2056 }
2057 /***** CRITICAL SECTION START *****/
2058 spin_lock(&ccs_query_list_lock);
2059 list_del(&ccs_query_entry->list);
2060 ccs_query_memory_size -= len + sizeof(*ccs_query_entry);
2061 spin_unlock(&ccs_query_list_lock);
2062 /***** CRITICAL SECTION END *****/
2063 switch (ccs_query_entry->answer) {
2064 case 3: /* Asked to retry by administrator. */
2065 error = 1;
2066 r->retry++;
2067 break;
2068 case 1:
2069 /* Granted by administrator. */
2070 error = 0;
2071 break;
2072 case 0:
2073 /* Timed out. */
2074 break;
2075 default:
2076 /* Rejected by administrator. */
2077 break;
2078 }
2079 out:
2080 if (ccs_query_entry)
2081 kfree(ccs_query_entry->query);
2082 kfree(ccs_query_entry);
2083 kfree(header);
2084 return error;
2085 }
2086
2087 /**
2088 * ccs_poll_query - poll() for /proc/ccs/query.
2089 *
2090 * @file: Pointer to "struct file".
2091 * @wait: Pointer to "poll_table".
2092 *
2093 * Returns POLLIN | POLLRDNORM when ready to read, 0 otherwise.
2094 *
2095 * Waits for access requests which violated policy in enforcing mode.
2096 */
2097 static int ccs_poll_query(struct file *file, poll_table *wait)
2098 {
2099 struct list_head *tmp;
2100 bool found = false;
2101 u8 i;
2102 for (i = 0; i < 2; i++) {
2103 /***** CRITICAL SECTION START *****/
2104 spin_lock(&ccs_query_list_lock);
2105 list_for_each(tmp, &ccs_query_list) {
2106 struct ccs_query_entry *ptr
2107 = list_entry(tmp, struct ccs_query_entry, list);
2108 if (ptr->answer)
2109 continue;
2110 found = true;
2111 break;
2112 }
2113 spin_unlock(&ccs_query_list_lock);
2114 /***** CRITICAL SECTION END *****/
2115 if (found)
2116 return POLLIN | POLLRDNORM;
2117 if (i)
2118 break;
2119 poll_wait(file, &ccs_query_wait, wait);
2120 }
2121 return 0;
2122 }
2123
2124 /**
2125 * ccs_read_query - Read access requests which violated policy in enforcing mode.
2126 *
2127 * @head: Pointer to "struct ccs_io_buffer".
2128 *
2129 * Returns 0.
2130 */
2131 static int ccs_read_query(struct ccs_io_buffer *head)
2132 {
2133 struct list_head *tmp;
2134 int pos = 0;
2135 int len = 0;
2136 char *buf;
2137 if (head->read_avail)
2138 return 0;
2139 if (head->read_buf) {
2140 kfree(head->read_buf);
2141 head->read_buf = NULL;
2142 head->readbuf_size = 0;
2143 }
2144 /***** CRITICAL SECTION START *****/
2145 spin_lock(&ccs_query_list_lock);
2146 list_for_each(tmp, &ccs_query_list) {
2147 struct ccs_query_entry *ptr
2148 = list_entry(tmp, struct ccs_query_entry, list);
2149 if (ptr->answer)
2150 continue;
2151 if (pos++ != head->read_step)
2152 continue;
2153 len = ptr->query_len;
2154 break;
2155 }
2156 spin_unlock(&ccs_query_list_lock);
2157 /***** CRITICAL SECTION END *****/
2158 if (!len) {
2159 head->read_step = 0;
2160 return 0;
2161 }
2162 buf = kzalloc(len, GFP_KERNEL);
2163 if (!buf)
2164 return 0;
2165 pos = 0;
2166 /***** CRITICAL SECTION START *****/
2167 spin_lock(&ccs_query_list_lock);
2168 list_for_each(tmp, &ccs_query_list) {
2169 struct ccs_query_entry *ptr
2170 = list_entry(tmp, struct ccs_query_entry, list);
2171 if (ptr->answer)
2172 continue;
2173 if (pos++ != head->read_step)
2174 continue;
2175 /*
2176 * Some query can be skipped because ccs_query_list
2177 * can change, but I don't care.
2178 */
2179 if (len == ptr->query_len)
2180 memmove(buf, ptr->query, len);
2181 break;
2182 }
2183 spin_unlock(&ccs_query_list_lock);
2184 /***** CRITICAL SECTION END *****/
2185 if (buf[0]) {
2186 head->read_avail = len;
2187 head->readbuf_size = head->read_avail;
2188 head->read_buf = buf;
2189 head->read_step++;
2190 } else {
2191 kfree(buf);
2192 }
2193 return 0;
2194 }
2195
2196 /**
2197 * ccs_write_answer - Write the supervisor's decision.
2198 *
2199 * @head: Pointer to "struct ccs_io_buffer".
2200 *
2201 * Returns 0 on success, -EINVAL otherwise.
2202 */
2203 static int ccs_write_answer(struct ccs_io_buffer *head)
2204 {
2205 char *data = head->write_buf;
2206 struct list_head *tmp;
2207 unsigned int serial;
2208 unsigned int answer;
2209 /***** CRITICAL SECTION START *****/
2210 spin_lock(&ccs_query_list_lock);
2211 list_for_each(tmp, &ccs_query_list) {
2212 struct ccs_query_entry *ptr
2213 = list_entry(tmp, struct ccs_query_entry, list);
2214 ptr->timer = 0;
2215 }
2216 spin_unlock(&ccs_query_list_lock);
2217 /***** CRITICAL SECTION END *****/
2218 if (sscanf(data, "A%u=%u", &serial, &answer) != 2)
2219 return -EINVAL;
2220 /***** CRITICAL SECTION START *****/
2221 spin_lock(&ccs_query_list_lock);
2222 list_for_each(tmp, &ccs_query_list) {
2223 struct ccs_query_entry *ptr
2224 = list_entry(tmp, struct ccs_query_entry, list);
2225 if (ptr->serial != serial)
2226 continue;
2227 if (!ptr->answer)
2228 ptr->answer = answer;
2229 break;
2230 }
2231 spin_unlock(&ccs_query_list_lock);
2232 /***** CRITICAL SECTION END *****/
2233 return 0;
2234 }
2235
2236 /**
2237 * ccs_read_version: Get version.
2238 *
2239 * @head: Pointer to "struct ccs_io_buffer".
2240 *
2241 * Returns version information.
2242 */
2243 static int ccs_read_version(struct ccs_io_buffer *head)
2244 {
2245 if (!head->read_eof) {
2246 ccs_io_printf(head, "1.7.0-pre");
2247 head->read_eof = true;
2248 }
2249 return 0;
2250 }
2251
2252 /**
2253 * ccs_read_self_domain - Get the current process's domainname.
2254 *
2255 * @head: Pointer to "struct ccs_io_buffer".
2256 *
2257 * Returns the current process's domainname.
2258 */
2259 static int ccs_read_self_domain(struct ccs_io_buffer *head)
2260 {
2261 if (!head->read_eof) {
2262 /*
2263 * ccs_current_domain()->domainname != NULL
2264 * because every process belongs to a domain and
2265 * the domain's name cannot be NULL.
2266 */
2267 ccs_io_printf(head, "%s",
2268 ccs_current_domain()->domainname->name);
2269 head->read_eof = true;
2270 }
2271 return 0;
2272 }
2273
2274 /**
2275 * ccs_open_control - open() for /proc/ccs/ interface.
2276 *
2277 * @type: Type of interface.
2278 * @file: Pointer to "struct file".
2279 *
2280 * Associates policy handler and returns 0 on success, -ENOMEM otherwise.
2281 */
2282 int ccs_open_control(const u8 type, struct file *file)
2283 {
2284 struct ccs_io_buffer *head = kzalloc(sizeof(*head), GFP_KERNEL);
2285 if (!head)
2286 return -ENOMEM;
2287 mutex_init(&head->io_sem);
2288 head->type = type;
2289 switch (type) {
2290 case CCS_DOMAINPOLICY: /* /proc/ccs/domain_policy */
2291 head->write = ccs_write_domain_policy;
2292 head->read = ccs_read_domain_policy;
2293 break;
2294 case CCS_EXCEPTIONPOLICY: /* /proc/ccs/exception_policy */
2295 head->write = ccs_write_exception_policy;
2296 head->read = ccs_read_exception_policy;
2297 break;
2298 #ifdef CONFIG_CCSECURITY_AUDIT
2299 case CCS_GRANTLOG: /* /proc/ccs/grant_log */
2300 head->poll = ccs_poll_grant_log;
2301 head->read = ccs_read_grant_log;
2302 break;
2303 case CCS_REJECTLOG: /* /proc/ccs/reject_log */
2304 head->poll = ccs_poll_reject_log;
2305 head->read = ccs_read_reject_log;
2306 break;
2307 #endif
2308 case CCS_SELFDOMAIN: /* /proc/ccs/self_domain */
2309 head->read = ccs_read_self_domain;
2310 break;
2311 case CCS_DOMAIN_STATUS: /* /proc/ccs/.domain_status */
2312 head->write = ccs_write_domain_profile;
2313 head->read = ccs_read_domain_profile;
2314 break;
2315 case CCS_EXECUTE_HANDLER: /* /proc/ccs/.execute_handler */
2316 /* Allow execute_handler to read process's status. */
2317 if (!(current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {
2318 kfree(head);
2319 return -EPERM;
2320 }
2321 /* fall through */
2322 case CCS_PROCESS_STATUS: /* /proc/ccs/.process_status */
2323 head->write = ccs_write_pid;
2324 head->read = ccs_read_pid;
2325 break;
2326 case CCS_VERSION: /* /proc/ccs/version */
2327 head->read = ccs_read_version;
2328 head->readbuf_size = 128;
2329 break;
2330 case CCS_MEMINFO: /* /proc/ccs/meminfo */
2331 head->write = ccs_write_memory_quota;
2332 head->read = ccs_read_memory_counter;
2333 head->readbuf_size = 512;
2334 break;
2335 case CCS_PROFILE: /* /proc/ccs/profile */
2336 head->write = ccs_write_profile;
2337 head->read = ccs_read_profile;
2338 break;
2339 case CCS_QUERY: /* /proc/ccs/query */
2340 head->poll = ccs_poll_query;
2341 head->write = ccs_write_answer;
2342 head->read = ccs_read_query;
2343 break;
2344 case CCS_MANAGER: /* /proc/ccs/manager */
2345 head->write = ccs_write_manager_policy;
2346 head->read = ccs_read_manager_policy;
2347 break;
2348 }
2349 if (!(file->f_mode & FMODE_READ)) {
2350 /*
2351 * No need to allocate read_buf since it is not opened
2352 * for reading.
2353 */
2354 head->read = NULL;
2355 head->poll = NULL;
2356 } else if (type != CCS_QUERY &&
2357 type != CCS_GRANTLOG && type != CCS_REJECTLOG) {
2358 /*
2359 * Don't allocate buffer for reading if the file is one of
2360 * /proc/ccs/grant_log , /proc/ccs/reject_log , /proc/ccs/query.
2361 */
2362 if (!head->readbuf_size)
2363 head->readbuf_size = 4096 * 2;
2364 head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL);
2365 if (!head->read_buf) {
2366 kfree(head);
2367 return -ENOMEM;
2368 }
2369 }
2370 if (!(file->f_mode & FMODE_WRITE)) {
2371 /*
2372 * No need to allocate write_buf since it is not opened
2373 * for writing.
2374 */
2375 head->write = NULL;
2376 } else if (head->write) {
2377 head->writebuf_size = 4096 * 2;
2378 head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL);
2379 if (!head->write_buf) {
2380 kfree(head->read_buf);
2381 kfree(head);
2382 return -ENOMEM;
2383 }
2384 }
2385 if (type != CCS_QUERY &&
2386 type != CCS_GRANTLOG && type != CCS_REJECTLOG)
2387 head->reader_idx = ccs_read_lock();
2388 file->private_data = head;
2389 /*
2390 * Call the handler now if the file is /proc/ccs/self_domain
2391 * so that the user can use "cat < /proc/ccs/self_domain" to
2392 * know the current process's domainname.
2393 */
2394 if (type == CCS_SELFDOMAIN)
2395 ccs_read_control(file, NULL, 0);
2396 /*
2397 * If the file is /proc/ccs/query , increment the observer counter.
2398 * The obserber counter is used by ccs_check_supervisor() to see if
2399 * there is some process monitoring /proc/ccs/query.
2400 */
2401 else if (type == CCS_QUERY)
2402 atomic_inc(&ccs_query_observers);
2403 return 0;
2404 }
2405
2406 /**
2407 * ccs_poll_control - poll() for /proc/ccs/ interface.
2408 *
2409 * @file: Pointer to "struct file".
2410 * @wait: Pointer to "poll_table".
2411 *
2412 * Waits for read readiness.
2413 * /proc/ccs/query is handled by /usr/lib/ccs/ccs-queryd and
2414 * /proc/ccs/grant_log and /proc/ccs/reject_log are handled by
2415 * /usr/lib/ccs/ccs-auditd.
2416 */
2417 int ccs_poll_control(struct file *file, poll_table *wait)
2418 {
2419 struct ccs_io_buffer *head = file->private_data;
2420 if (!head->poll)
2421 return -ENOSYS;
2422 return head->poll(file, wait);
2423 }
2424
2425 /**
2426 * ccs_read_control - read() for /proc/ccs/ interface.
2427 *
2428 * @file: Pointer to "struct file".
2429 * @buffer: Poiner to buffer to write to.
2430 * @buffer_len: Size of @buffer.
2431 *
2432 * Returns bytes read on success, negative value otherwise.
2433 */
2434 int ccs_read_control(struct file *file, char __user *buffer,
2435 const int buffer_len)
2436 {
2437 int len = 0;
2438 struct ccs_io_buffer *head = file->private_data;
2439 char *cp;
2440 if (!head->read)
2441 return -ENOSYS;
2442 if (!access_ok(VERIFY_WRITE, buffer, buffer_len))
2443 return -EFAULT;
2444 if (mutex_lock_interruptible(&head->io_sem))
2445 return -EINTR;
2446 /* Call the policy handler. */
2447 len = head->read(head);
2448 if (len < 0)
2449 goto out;
2450 /* Write to buffer. */
2451 len = head->read_avail;
2452 if (len > buffer_len)
2453 len = buffer_len;
2454 if (!len)
2455 goto out;
2456 /* head->read_buf changes by some functions. */
2457 cp = head->read_buf;
2458 if (copy_to_user(buffer, cp, len)) {
2459 len = -EFAULT;
2460 goto out;
2461 }
2462 head->read_avail -= len;
2463 memmove(cp, cp + len, head->read_avail);
2464 out:
2465 mutex_unlock(&head->io_sem);
2466 return len;
2467 }
2468
2469 /**
2470 * ccs_write_control - write() for /proc/ccs/ interface.
2471 *
2472 * @file: Pointer to "struct file".
2473 * @buffer: Pointer to buffer to read from.
2474 * @buffer_len: Size of @buffer.
2475 *
2476 * Returns @buffer_len on success, negative value otherwise.
2477 */
2478 int ccs_write_control(struct file *file, const char __user *buffer,
2479 const int buffer_len)
2480 {
2481 struct ccs_io_buffer *head = file->private_data;
2482 int error = buffer_len;
2483 int avail_len = buffer_len;
2484 char *cp0 = head->write_buf;
2485 if (!head->write)
2486 return -ENOSYS;
2487 if (!access_ok(VERIFY_READ, buffer, buffer_len))
2488 return -EFAULT;
2489 /* Don't allow updating policies by non manager programs. */
2490 if (head->write != ccs_write_pid &&
2491 head->write != ccs_write_domain_policy &&
2492 !ccs_is_policy_manager())
2493 return -EPERM;
2494 if (mutex_lock_interruptible(&head->io_sem))
2495 return -EINTR;
2496 /* Read a line and dispatch it to the policy handler. */
2497 while (avail_len > 0) {
2498 char c;
2499 if (head->write_avail >= head->writebuf_size - 1) {
2500 error = -ENOMEM;
2501 break;
2502 } else if (get_user(c, buffer)) {
2503 error = -EFAULT;
2504 break;
2505 }
2506 buffer++;
2507 avail_len--;
2508 cp0[head->write_avail++] = c;
2509 if (c != '\n')
2510 continue;
2511 cp0[head->write_avail - 1] = '\0';
2512 head->write_avail = 0;
2513 ccs_normalize_line(cp0);
2514 head->write(head);
2515 }
2516 mutex_unlock(&head->io_sem);
2517 return error;
2518 }
2519
2520 /**
2521 * ccs_close_control - close() for /proc/ccs/ interface.
2522 *
2523 * @file: Pointer to "struct file".
2524 *
2525 * Releases memory and returns 0.
2526 */
2527 int ccs_close_control(struct file *file)
2528 {
2529 struct ccs_io_buffer *head = file->private_data;
2530 const bool is_write = head->write_buf != NULL;
2531 const u8 type = head->type;
2532 /*
2533 * If the file is /proc/ccs/query , decrement the observer counter.
2534 */
2535 if (type == CCS_QUERY)
2536 atomic_dec(&ccs_query_observers);
2537 if (type != CCS_QUERY &&
2538 type != CCS_GRANTLOG && type != CCS_REJECTLOG)
2539 ccs_read_unlock(head->reader_idx);
2540 /* Release memory used for policy I/O. */
2541 kfree(head->read_buf);
2542 head->read_buf = NULL;
2543 kfree(head->write_buf);
2544 head->write_buf = NULL;
2545 kfree(head);
2546 head = NULL;
2547 file->private_data = NULL;
2548 if (is_write)
2549 ccs_run_gc();
2550 return 0;
2551 }

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