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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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