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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3773 - (show annotations) (download) (as text)
Tue Jun 22 07:17:52 2010 UTC (13 years, 11 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 69090 byte(s)


1 /*
2 * security/ccsecurity/policy_io.c
3 *
4 * Copyright (C) 2005-2010 NTT DATA CORPORATION
5 *
6 * Version: 1.7.2+ 2010/06/04
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 static struct ccs_profile ccs_default_profile = {
16 .learning = &ccs_default_profile.preference,
17 .permissive = &ccs_default_profile.preference,
18 .enforcing = &ccs_default_profile.preference,
19 .audit = &ccs_default_profile.preference,
20 #ifdef CONFIG_CCSECURITY_AUDIT
21 .preference.audit_max_grant_log = CONFIG_CCSECURITY_MAX_GRANT_LOG,
22 .preference.audit_max_reject_log = CONFIG_CCSECURITY_MAX_REJECT_LOG,
23 #endif
24 .preference.audit_task_info = true,
25 .preference.audit_path_info = true,
26 .preference.enforcing_penalty = 0,
27 .preference.enforcing_verbose = true,
28 .preference.learning_max_entry = CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY,
29 .preference.learning_verbose = false,
30 .preference.learning_exec_realpath = true,
31 .preference.learning_exec_argv0 = true,
32 .preference.learning_symlink_target = true,
33 .preference.permissive_verbose = true
34 };
35
36 /* Profile version. Currently only 20090903 is defined. */
37 static unsigned int ccs_profile_version;
38
39 /* Profile table. Memory is allocated as needed. */
40 static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES];
41
42 /* String table for functionality that takes 4 modes. */
43 static const char *ccs_mode[CCS_CONFIG_MAX_MODE] = {
44 [CCS_CONFIG_DISABLED] = "disabled",
45 [CCS_CONFIG_LEARNING] = "learning",
46 [CCS_CONFIG_PERMISSIVE] = "permissive",
47 [CCS_CONFIG_ENFORCING] = "enforcing"
48 };
49
50 /* String table for /proc/ccs/profile */
51 static const char *ccs_mac_keywords[CCS_MAX_MAC_INDEX +
52 CCS_MAX_CAPABILITY_INDEX +
53 CCS_MAX_MAC_CATEGORY_INDEX] = {
54 [CCS_MAC_FILE_EXECUTE]
55 = "file::execute",
56 [CCS_MAC_FILE_OPEN]
57 = "file::open",
58 [CCS_MAC_FILE_CREATE]
59 = "file::create",
60 [CCS_MAC_FILE_UNLINK]
61 = "file::unlink",
62 [CCS_MAC_FILE_MKDIR]
63 = "file::mkdir",
64 [CCS_MAC_FILE_RMDIR]
65 = "file::rmdir",
66 [CCS_MAC_FILE_MKFIFO]
67 = "file::mkfifo",
68 [CCS_MAC_FILE_MKSOCK]
69 = "file::mksock",
70 [CCS_MAC_FILE_TRUNCATE]
71 = "file::truncate",
72 [CCS_MAC_FILE_SYMLINK]
73 = "file::symlink",
74 [CCS_MAC_FILE_REWRITE]
75 = "file::rewrite",
76 [CCS_MAC_FILE_MKBLOCK]
77 = "file::mkblock",
78 [CCS_MAC_FILE_MKCHAR]
79 = "file::mkchar",
80 [CCS_MAC_FILE_LINK]
81 = "file::link",
82 [CCS_MAC_FILE_RENAME]
83 = "file::rename",
84 [CCS_MAC_FILE_CHMOD]
85 = "file::chmod",
86 [CCS_MAC_FILE_CHOWN]
87 = "file::chown",
88 [CCS_MAC_FILE_CHGRP]
89 = "file::chgrp",
90 [CCS_MAC_FILE_IOCTL]
91 = "file::ioctl",
92 [CCS_MAC_FILE_CHROOT]
93 = "file::chroot",
94 [CCS_MAC_FILE_MOUNT]
95 = "file::mount",
96 [CCS_MAC_FILE_UMOUNT]
97 = "file::umount",
98 [CCS_MAC_FILE_PIVOT_ROOT]
99 = "file::pivot_root",
100 [CCS_MAC_FILE_TRANSIT]
101 = "file::transit",
102 [CCS_MAC_ENVIRON]
103 = "misc::env",
104 [CCS_MAC_NETWORK_UDP_BIND]
105 = "network::inet_udp_bind",
106 [CCS_MAC_NETWORK_UDP_CONNECT]
107 = "network::inet_udp_connect",
108 [CCS_MAC_NETWORK_TCP_BIND]
109 = "network::inet_tcp_bind",
110 [CCS_MAC_NETWORK_TCP_LISTEN]
111 = "network::inet_tcp_listen",
112 [CCS_MAC_NETWORK_TCP_CONNECT]
113 = "network::inet_tcp_connect",
114 [CCS_MAC_NETWORK_TCP_ACCEPT]
115 = "network::inet_tcp_accept",
116 [CCS_MAC_NETWORK_RAW_BIND]
117 = "network::inet_raw_bind",
118 [CCS_MAC_NETWORK_RAW_CONNECT]
119 = "network::inet_raw_connect",
120 [CCS_MAC_SIGNAL]
121 = "ipc::signal",
122 [CCS_MAX_MAC_INDEX + CCS_INET_STREAM_SOCKET_CREATE]
123 = "capability::inet_tcp_create",
124 [CCS_MAX_MAC_INDEX + CCS_INET_STREAM_SOCKET_LISTEN]
125 = "capability::inet_tcp_listen",
126 [CCS_MAX_MAC_INDEX + CCS_INET_STREAM_SOCKET_CONNECT]
127 = "capability::inet_tcp_connect",
128 [CCS_MAX_MAC_INDEX + CCS_USE_INET_DGRAM_SOCKET]
129 = "capability::use_inet_udp",
130 [CCS_MAX_MAC_INDEX + CCS_USE_INET_RAW_SOCKET]
131 = "capability::use_inet_ip",
132 [CCS_MAX_MAC_INDEX + CCS_USE_ROUTE_SOCKET]
133 = "capability::use_route",
134 [CCS_MAX_MAC_INDEX + CCS_USE_PACKET_SOCKET]
135 = "capability::use_packet",
136 [CCS_MAX_MAC_INDEX + CCS_SYS_MOUNT]
137 = "capability::SYS_MOUNT",
138 [CCS_MAX_MAC_INDEX + CCS_SYS_UMOUNT]
139 = "capability::SYS_UMOUNT",
140 [CCS_MAX_MAC_INDEX + CCS_SYS_REBOOT]
141 = "capability::SYS_REBOOT",
142 [CCS_MAX_MAC_INDEX + CCS_SYS_CHROOT]
143 = "capability::SYS_CHROOT",
144 [CCS_MAX_MAC_INDEX + CCS_SYS_KILL]
145 = "capability::SYS_KILL",
146 [CCS_MAX_MAC_INDEX + CCS_SYS_VHANGUP]
147 = "capability::SYS_VHANGUP",
148 [CCS_MAX_MAC_INDEX + CCS_SYS_SETTIME]
149 = "capability::SYS_TIME",
150 [CCS_MAX_MAC_INDEX + CCS_SYS_NICE]
151 = "capability::SYS_NICE",
152 [CCS_MAX_MAC_INDEX + CCS_SYS_SETHOSTNAME]
153 = "capability::SYS_SETHOSTNAME",
154 [CCS_MAX_MAC_INDEX + CCS_USE_KERNEL_MODULE]
155 = "capability::use_kernel_module",
156 [CCS_MAX_MAC_INDEX + CCS_CREATE_FIFO]
157 = "capability::create_fifo",
158 [CCS_MAX_MAC_INDEX + CCS_CREATE_BLOCK_DEV]
159 = "capability::create_block_dev",
160 [CCS_MAX_MAC_INDEX + CCS_CREATE_CHAR_DEV]
161 = "capability::create_char_dev",
162 [CCS_MAX_MAC_INDEX + CCS_CREATE_UNIX_SOCKET]
163 = "capability::create_unix_socket",
164 [CCS_MAX_MAC_INDEX + CCS_SYS_LINK]
165 = "capability::SYS_LINK",
166 [CCS_MAX_MAC_INDEX + CCS_SYS_SYMLINK]
167 = "capability::SYS_SYMLINK",
168 [CCS_MAX_MAC_INDEX + CCS_SYS_RENAME]
169 = "capability::SYS_RENAME",
170 [CCS_MAX_MAC_INDEX + CCS_SYS_UNLINK]
171 = "capability::SYS_UNLINK",
172 [CCS_MAX_MAC_INDEX + CCS_SYS_CHMOD]
173 = "capability::SYS_CHMOD",
174 [CCS_MAX_MAC_INDEX + CCS_SYS_CHOWN]
175 = "capability::SYS_CHOWN",
176 [CCS_MAX_MAC_INDEX + CCS_SYS_IOCTL]
177 = "capability::SYS_IOCTL",
178 [CCS_MAX_MAC_INDEX + CCS_SYS_KEXEC_LOAD]
179 = "capability::SYS_KEXEC_LOAD",
180 [CCS_MAX_MAC_INDEX + CCS_SYS_PIVOT_ROOT]
181 = "capability::SYS_PIVOT_ROOT",
182 [CCS_MAX_MAC_INDEX + CCS_SYS_PTRACE]
183 = "capability::SYS_PTRACE",
184 [CCS_MAX_MAC_INDEX + CCS_CONCEAL_MOUNT]
185 = "capability::conceal_mount",
186 [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
187 + CCS_MAC_CATEGORY_FILE] = "file",
188 [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
189 + CCS_MAC_CATEGORY_NETWORK] = "network",
190 [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
191 + CCS_MAC_CATEGORY_MISC] = "misc",
192 [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
193 + CCS_MAC_CATEGORY_IPC] = "ipc",
194 [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
195 + CCS_MAC_CATEGORY_CAPABILITY] = "capability",
196 };
197
198 /* Permit policy management by non-root user? */
199 static bool ccs_manage_by_non_root;
200
201 /**
202 * ccs_cap2keyword - Convert capability operation to capability name.
203 *
204 * @operation: The capability index.
205 *
206 * Returns the name of the specified capability's name.
207 */
208 const char *ccs_cap2keyword(const u8 operation)
209 {
210 return operation < CCS_MAX_CAPABILITY_INDEX
211 ? ccs_mac_keywords[CCS_MAX_MAC_INDEX + operation] + 12 : NULL;
212 }
213
214 /**
215 * ccs_yesno - Return "yes" or "no".
216 *
217 * @value: Bool value.
218 */
219 static const char *ccs_yesno(const unsigned int value)
220 {
221 return value ? "yes" : "no";
222 }
223
224 /**
225 * ccs_io_printf - Transactional printf() to "struct ccs_io_buffer" structure.
226 *
227 * @head: Pointer to "struct ccs_io_buffer".
228 * @fmt: The printf()'s format string, followed by parameters.
229 *
230 * Returns true on success, false otherwise.
231 *
232 * The snprintf() will truncate, but ccs_io_printf() won't.
233 */
234 bool ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
235 {
236 va_list args;
237 int len;
238 int pos = head->read_avail;
239 int size = head->readbuf_size - pos;
240 if (size <= 0)
241 return false;
242 va_start(args, fmt);
243 len = vsnprintf(head->read_buf + pos, size, fmt, args);
244 va_end(args);
245 if (pos + len >= head->readbuf_size)
246 return false;
247 head->read_avail += len;
248 return true;
249 }
250
251 /**
252 * ccs_assign_profile - Create a new profile.
253 *
254 * @profile: Profile number to create.
255 *
256 * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
257 */
258 static struct ccs_profile *ccs_assign_profile(const unsigned int profile)
259 {
260 struct ccs_profile *ptr;
261 struct ccs_profile *entry;
262 if (profile >= CCS_MAX_PROFILES)
263 return NULL;
264 ptr = ccs_profile_ptr[profile];
265 if (ptr)
266 return ptr;
267 entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
268 if (mutex_lock_interruptible(&ccs_policy_lock))
269 goto out;
270 ptr = ccs_profile_ptr[profile];
271 if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
272 ptr = entry;
273 ptr->audit = &ccs_default_profile.preference;
274 ptr->learning = &ccs_default_profile.preference;
275 ptr->permissive = &ccs_default_profile.preference;
276 ptr->enforcing = &ccs_default_profile.preference;
277 ptr->default_config = CCS_CONFIG_DISABLED |
278 CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;
279 memset(ptr->config, CCS_CONFIG_USE_DEFAULT,
280 sizeof(ptr->config));
281 mb(); /* Avoid out-of-order execution. */
282 ccs_profile_ptr[profile] = ptr;
283 entry = NULL;
284 }
285 mutex_unlock(&ccs_policy_lock);
286 out:
287 kfree(entry);
288 return ptr;
289 }
290
291 /**
292 * ccs_check_profile - Check all profiles currently assigned to domains are defined.
293 */
294 static void ccs_check_profile(void)
295 {
296 struct ccs_domain_info *domain;
297 const int idx = ccs_read_lock();
298 ccs_policy_loaded = true;
299 list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
300 const u8 profile = domain->profile;
301 if (ccs_profile_ptr[profile])
302 continue;
303 panic("Profile %u (used by '%s') not defined.\n",
304 profile, domain->domainname->name);
305 }
306 ccs_read_unlock(idx);
307 if (ccs_profile_version != 20090903)
308 panic("Profile version %u is not supported.\n",
309 ccs_profile_version);
310 printk(KERN_INFO "CCSecurity: 1.7.2+ 2010/06/04\n");
311 printk(KERN_INFO "Mandatory Access Control activated.\n");
312 }
313
314 /**
315 * ccs_profile - Find a profile.
316 *
317 * @profile: Profile number to find.
318 *
319 * Returns pointer to "struct ccs_profile".
320 */
321 struct ccs_profile *ccs_profile(const u8 profile)
322 {
323 struct ccs_profile *ptr = ccs_profile_ptr[profile];
324 if (!ccs_policy_loaded)
325 return &ccs_default_profile;
326 BUG_ON(!ptr);
327 return ptr;
328 }
329
330 static s8 ccs_find_yesno(const char *string, const char *find)
331 {
332 const char *cp = strstr(string, find);
333 if (cp) {
334 cp += strlen(find);
335 if (!strncmp(cp, "=yes", 4))
336 return 1;
337 else if (!strncmp(cp, "=no", 3))
338 return 0;
339 }
340 return -1;
341 }
342
343 static void ccs_set_bool(bool *b, const char *string, const char *find)
344 {
345 switch (ccs_find_yesno(string, find)) {
346 case 1:
347 *b = true;
348 break;
349 case 0:
350 *b = false;
351 break;
352 }
353 }
354
355 static void ccs_set_uint(unsigned int *i, const char *string, const char *find)
356 {
357 const char *cp = strstr(string, find);
358 if (cp)
359 sscanf(cp + strlen(find), "=%u", i);
360 }
361
362 static void ccs_set_pref(const char *name, const char *value,
363 const bool use_default, struct ccs_profile *profile)
364 {
365 struct ccs_preference **pref;
366 bool *verbose;
367 if (!strcmp(name, "audit")) {
368 if (use_default) {
369 pref = &profile->audit;
370 goto set_default;
371 }
372 profile->audit = &profile->preference;
373 #ifdef CONFIG_CCSECURITY_AUDIT
374 ccs_set_uint(&profile->preference.audit_max_grant_log, value,
375 "max_grant_log");
376 ccs_set_uint(&profile->preference.audit_max_reject_log, value,
377 "max_reject_log");
378 #endif
379 ccs_set_bool(&profile->preference.audit_task_info, value,
380 "task_info");
381 ccs_set_bool(&profile->preference.audit_path_info, value,
382 "path_info");
383 return;
384 }
385 if (!strcmp(name, "enforcing")) {
386 if (use_default) {
387 pref = &profile->enforcing;
388 goto set_default;
389 }
390 profile->enforcing = &profile->preference;
391 ccs_set_uint(&profile->preference.enforcing_penalty, value,
392 "penalty");
393 verbose = &profile->preference.enforcing_verbose;
394 goto set_verbose;
395 }
396 if (!strcmp(name, "permissive")) {
397 if (use_default) {
398 pref = &profile->permissive;
399 goto set_default;
400 }
401 profile->permissive = &profile->preference;
402 verbose = &profile->preference.permissive_verbose;
403 goto set_verbose;
404 }
405 if (!strcmp(name, "learning")) {
406 if (use_default) {
407 pref = &profile->learning;
408 goto set_default;
409 }
410 profile->learning = &profile->preference;
411 ccs_set_uint(&profile->preference.learning_max_entry, value,
412 "max_entry");
413 ccs_set_bool(&profile->preference.learning_exec_realpath,
414 value, "exec.realpath");
415 ccs_set_bool(&profile->preference.learning_exec_argv0, value,
416 "exec.argv0");
417 ccs_set_bool(&profile->preference.learning_symlink_target,
418 value, "symlink.target");
419 verbose = &profile->preference.learning_verbose;
420 goto set_verbose;
421 }
422 return;
423 set_default:
424 *pref = &ccs_default_profile.preference;
425 return;
426 set_verbose:
427 ccs_set_bool(verbose, value, "verbose");
428 }
429
430 static int ccs_set_mode(char *name, const char *value, const bool use_default,
431 struct ccs_profile *profile)
432 {
433 u8 i;
434 u8 config;
435 if (!strcmp(name, "CONFIG")) {
436 i = CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
437 + CCS_MAX_MAC_CATEGORY_INDEX;
438 config = profile->default_config;
439 } else if (ccs_str_starts(&name, "CONFIG::")) {
440 config = 0;
441 for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
442 + CCS_MAX_MAC_CATEGORY_INDEX; i++) {
443 if (strcmp(name, ccs_mac_keywords[i]))
444 continue;
445 config = profile->config[i];
446 break;
447 }
448 if (i == CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
449 + CCS_MAX_MAC_CATEGORY_INDEX)
450 return -EINVAL;
451 } else {
452 return -EINVAL;
453 }
454 if (use_default) {
455 config = CCS_CONFIG_USE_DEFAULT;
456 } else {
457 u8 mode;
458 for (mode = 0; mode < CCS_CONFIG_MAX_MODE; mode++)
459 if (strstr(value, ccs_mode[mode]))
460 /*
461 * Update lower 3 bits in order to distinguish
462 * 'config' from 'CCS_CONFIG_USE_DEAFULT'.
463 */
464 config = (config & ~7) | mode;
465 #ifdef CONFIG_CCSECURITY_AUDIT
466 if (config != CCS_CONFIG_USE_DEFAULT) {
467 switch (ccs_find_yesno(value, "grant_log")) {
468 case 1:
469 config |= CCS_CONFIG_WANT_GRANT_LOG;
470 break;
471 case 0:
472 config &= ~CCS_CONFIG_WANT_GRANT_LOG;
473 break;
474 }
475 switch (ccs_find_yesno(value, "reject_log")) {
476 case 1:
477 config |= CCS_CONFIG_WANT_REJECT_LOG;
478 break;
479 case 0:
480 config &= ~CCS_CONFIG_WANT_REJECT_LOG;
481 break;
482 }
483 }
484 #endif
485 }
486 if (i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
487 + CCS_MAX_MAC_CATEGORY_INDEX)
488 profile->config[i] = config;
489 else if (config != CCS_CONFIG_USE_DEFAULT)
490 profile->default_config = config;
491 return 0;
492 }
493
494 /**
495 * ccs_write_profile - Write profile table.
496 *
497 * @head: Pointer to "struct ccs_io_buffer".
498 *
499 * Returns 0 on success, negative value otherwise.
500 */
501 static int ccs_write_profile(struct ccs_io_buffer *head)
502 {
503 char *data = head->write_buf;
504 bool use_default = false;
505 char *cp;
506 int i;
507 struct ccs_profile *profile;
508 if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1)
509 return 0;
510 i = simple_strtoul(data, &cp, 10);
511 if (data == cp) {
512 profile = &ccs_default_profile;
513 } else {
514 if (*cp != '-')
515 return -EINVAL;
516 data = cp + 1;
517 profile = ccs_assign_profile(i);
518 if (!profile)
519 return -EINVAL;
520 }
521 cp = strchr(data, '=');
522 if (!cp)
523 return -EINVAL;
524 *cp++ = '\0';
525 if (profile != &ccs_default_profile)
526 use_default = strstr(cp, "use_default") != NULL;
527 if (ccs_str_starts(&data, "PREFERENCE::")) {
528 ccs_set_pref(data, cp, use_default, profile);
529 return 0;
530 }
531 if (profile == &ccs_default_profile)
532 return -EINVAL;
533 if (!strcmp(data, "COMMENT")) {
534 const struct ccs_path_info *old_comment = profile->comment;
535 profile->comment = ccs_get_name(cp);
536 ccs_put_name(old_comment);
537 return 0;
538 }
539 return ccs_set_mode(data, cp, use_default, profile);
540 }
541
542 static bool ccs_print_preference(struct ccs_io_buffer *head, const int idx)
543 {
544 struct ccs_preference *pref = &ccs_default_profile.preference;
545 const struct ccs_profile *profile = idx >= 0 ?
546 ccs_profile_ptr[idx] : NULL;
547 char buffer[16] = "";
548 if (profile) {
549 buffer[sizeof(buffer) - 1] = '\0';
550 snprintf(buffer, sizeof(buffer) - 1, "%u-", idx);
551 }
552 if (profile) {
553 pref = profile->audit;
554 if (pref == &ccs_default_profile.preference)
555 pref = NULL;
556 }
557 if (pref && !ccs_io_printf(head, "%sPREFERENCE::%s={ "
558 #ifdef CONFIG_CCSECURITY_AUDIT
559 "max_grant_log=%u max_reject_log=%u "
560 #endif
561 "task_info=%s path_info=%s }\n", buffer,
562 "audit",
563 #ifdef CONFIG_CCSECURITY_AUDIT
564 pref->audit_max_grant_log,
565 pref->audit_max_reject_log,
566 #endif
567 ccs_yesno(pref->audit_task_info),
568 ccs_yesno(pref->audit_path_info)))
569 return false;
570 if (profile) {
571 pref = profile->learning;
572 if (pref == &ccs_default_profile.preference)
573 pref = NULL;
574 }
575 if (pref && !ccs_io_printf(head, "%sPREFERENCE::%s={ "
576 "verbose=%s max_entry=%u exec.realpath=%s "
577 "exec.argv0=%s symlink.target=%s }\n",
578 buffer, "learning",
579 ccs_yesno(pref->learning_verbose),
580 pref->learning_max_entry,
581 ccs_yesno(pref->learning_exec_realpath),
582 ccs_yesno(pref->learning_exec_argv0),
583 ccs_yesno(pref->learning_symlink_target)))
584 return false;
585 if (profile) {
586 pref = profile->permissive;
587 if (pref == &ccs_default_profile.preference)
588 pref = NULL;
589 }
590 if (pref && !ccs_io_printf(head, "%sPREFERENCE::%s={ verbose=%s }\n",
591 buffer, "permissive",
592 ccs_yesno(pref->permissive_verbose)))
593 return false;
594 if (profile) {
595 pref = profile->enforcing;
596 if (pref == &ccs_default_profile.preference)
597 pref = NULL;
598 }
599 return !pref || ccs_io_printf(head, "%sPREFERENCE::%s={ verbose=%s "
600 "penalty=%u }\n", buffer, "enforcing",
601 ccs_yesno(pref->enforcing_verbose),
602 pref->enforcing_penalty);
603 }
604
605 /**
606 * ccs_read_profile - Read profile table.
607 *
608 * @head: Pointer to "struct ccs_io_buffer".
609 */
610 static void ccs_read_profile(struct ccs_io_buffer *head)
611 {
612 int index;
613 if (head->read_eof)
614 return;
615 if (head->read_bit)
616 goto body;
617 ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20090903");
618 ccs_print_preference(head, -1);
619 head->read_bit = 1;
620 body:
621 for (index = head->read_step; index < CCS_MAX_PROFILES; index++) {
622 bool done;
623 u8 config;
624 int i;
625 int pos;
626 const struct ccs_profile *profile = ccs_profile_ptr[index];
627 const struct ccs_path_info *comment;
628 head->read_step = index;
629 if (!profile)
630 continue;
631 pos = head->read_avail;
632 comment = profile->comment;
633 done = ccs_io_printf(head, "%u-COMMENT=%s\n", index,
634 comment ? comment->name : "");
635 if (!done)
636 goto out;
637 config = profile->default_config;
638 #ifdef CONFIG_CCSECURITY_AUDIT
639 if (!ccs_io_printf(head, "%u-%s%s={ mode=%s "
640 "grant_log=%s reject_log=%s }\n", index,
641 "CONFIG", "", ccs_mode[config & 3],
642 ccs_yesno(config &
643 CCS_CONFIG_WANT_GRANT_LOG),
644 ccs_yesno(config &
645 CCS_CONFIG_WANT_REJECT_LOG)))
646 goto out;
647 #else
648 if (!ccs_io_printf(head, "%u-%s%s={ mode=%s }\n", index,
649 "CONFIG", "", ccs_mode[config & 3]))
650 goto out;
651 #endif
652 for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
653 + CCS_MAX_MAC_CATEGORY_INDEX; i++) {
654 #ifdef CONFIG_CCSECURITY_AUDIT
655 const char *g;
656 const char *r;
657 #endif
658 config = profile->config[i];
659 if (config == CCS_CONFIG_USE_DEFAULT)
660 continue;
661 #ifdef CONFIG_CCSECURITY_AUDIT
662 g = ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG);
663 r = ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG);
664 if (!ccs_io_printf(head, "%u-%s%s={ mode=%s "
665 "grant_log=%s reject_log=%s }\n",
666 index, "CONFIG::",
667 ccs_mac_keywords[i],
668 ccs_mode[config & 3], g, r))
669 goto out;
670 #else
671 if (!ccs_io_printf(head, "%u-%s%s={ mode=%s }\n",
672 index, "CONFIG::",
673 ccs_mac_keywords[i],
674 ccs_mode[config & 3]))
675 goto out;
676 #endif
677 }
678 if (!ccs_print_preference(head, index))
679 goto out;
680 continue;
681 out:
682 head->read_avail = pos;
683 break;
684 }
685 if (index == CCS_MAX_PROFILES)
686 head->read_eof = true;
687 }
688
689 static bool ccs_same_manager_entry(const struct ccs_acl_head *a,
690 const struct ccs_acl_head *b)
691 {
692 return container_of(a, struct ccs_manager, head)->manager
693 == container_of(b, struct ccs_manager, head)->manager;
694 }
695
696 /**
697 * ccs_update_manager_entry - Add a manager entry.
698 *
699 * @manager: The path to manager or the domainnamme.
700 * @is_delete: True if it is a delete request.
701 *
702 * Returns 0 on success, negative value otherwise.
703 */
704 static int ccs_update_manager_entry(const char *manager, const bool is_delete)
705 {
706 struct ccs_manager e = { };
707 int error = is_delete ? -ENOENT : -ENOMEM;
708 if (ccs_domain_def(manager)) {
709 if (!ccs_correct_domain(manager))
710 return -EINVAL;
711 e.is_domain = true;
712 } else {
713 if (!ccs_correct_path(manager))
714 return -EINVAL;
715 }
716 e.manager = ccs_get_name(manager);
717 if (!e.manager)
718 return error;
719 error = ccs_update_policy(&e.head, sizeof(e), is_delete,
720 &ccs_policy_list[CCS_ID_MANAGER],
721 ccs_same_manager_entry);
722 ccs_put_name(e.manager);
723 return error;
724 }
725
726 /**
727 * ccs_write_manager - Write manager policy.
728 *
729 * @head: Pointer to "struct ccs_io_buffer".
730 *
731 * Returns 0 on success, negative value otherwise.
732 */
733 static int ccs_write_manager(struct ccs_io_buffer *head)
734 {
735 char *data = head->write_buf;
736 bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);
737 if (!strcmp(data, "manage_by_non_root")) {
738 ccs_manage_by_non_root = !is_delete;
739 return 0;
740 }
741 return ccs_update_manager_entry(data, is_delete);
742 }
743
744 /**
745 * ccs_read_manager - Read manager policy.
746 *
747 * @head: Pointer to "struct ccs_io_buffer".
748 *
749 * Caller holds ccs_read_lock().
750 */
751 static void ccs_read_manager(struct ccs_io_buffer *head)
752 {
753 struct list_head *pos;
754 if (head->read_eof)
755 return;
756 list_for_each_cookie(pos, head->read_var2,
757 &ccs_policy_list[CCS_ID_MANAGER]) {
758 struct ccs_manager *ptr
759 = list_entry(pos, typeof(*ptr), head.list);
760 if (ptr->head.is_deleted)
761 continue;
762 if (!ccs_io_printf(head, "%s\n", ptr->manager->name))
763 return;
764 }
765 head->read_eof = true;
766 }
767
768 /**
769 * ccs_manager - Check whether the current process is a policy manager.
770 *
771 * Returns true if the current process is permitted to modify policy
772 * via /proc/ccs/ interface.
773 *
774 * Caller holds ccs_read_lock().
775 */
776 static bool ccs_manager(void)
777 {
778 struct ccs_manager *ptr;
779 const char *exe;
780 struct task_struct *task = current;
781 const struct ccs_path_info *domainname
782 = ccs_current_domain()->domainname;
783 bool found = false;
784 if (!ccs_policy_loaded)
785 return true;
786 if (task->ccs_flags & CCS_TASK_IS_MANAGER)
787 return true;
788 if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
789 return false;
790 exe = ccs_get_exe();
791 list_for_each_entry_rcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],
792 head.list) {
793 if (ptr->head.is_deleted)
794 continue;
795 if (ptr->is_domain) {
796 if (ccs_pathcmp(domainname, ptr->manager))
797 continue;
798 } else {
799 if (!exe || strcmp(exe, ptr->manager->name))
800 continue;
801 }
802 /* Set manager flag. */
803 task->ccs_flags |= CCS_TASK_IS_MANAGER;
804 found = true;
805 break;
806 }
807 if (!found) { /* Reduce error messages. */
808 static pid_t ccs_last_pid;
809 const pid_t pid = current->pid;
810 if (ccs_last_pid != pid) {
811 printk(KERN_WARNING "%s ( %s ) is not permitted to "
812 "update policies.\n", domainname->name, exe);
813 ccs_last_pid = pid;
814 }
815 }
816 kfree(exe);
817 return found;
818 }
819
820 /**
821 * ccs_find_condition_part - Find condition part from the statement.
822 *
823 * @data: String to parse.
824 *
825 * Returns pointer to the condition part if it was found in the statement,
826 * NULL otherwise.
827 */
828 static char *ccs_find_condition_part(char *data)
829 {
830 char *cp = strstr(data, " if ");
831 if (!cp)
832 cp = strstr(data, " ; set ");
833 if (cp)
834 *cp++ = '\0';
835 return cp;
836 }
837
838 /**
839 * ccs_select_one - Parse select command.
840 *
841 * @head: Pointer to "struct ccs_io_buffer".
842 * @data: String to parse.
843 *
844 * Returns true on success, false otherwise.
845 *
846 * Caller holds ccs_read_lock().
847 */
848 static bool ccs_select_one(struct ccs_io_buffer *head, const char *data)
849 {
850 unsigned int pid;
851 struct ccs_domain_info *domain = NULL;
852 bool global_pid = false;
853 if (!strcmp(data, "allow_execute")) {
854 head->read_execute_only = true;
855 return true;
856 }
857 if (sscanf(data, "pid=%u", &pid) == 1 ||
858 (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
859 struct task_struct *p;
860 ccs_tasklist_lock();
861 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
862 if (global_pid)
863 p = ccsecurity_exports.find_task_by_pid_ns(pid,
864 &init_pid_ns);
865 else
866 p = ccsecurity_exports.find_task_by_vpid(pid);
867 #else
868 p = find_task_by_pid(pid);
869 #endif
870 if (p)
871 domain = ccs_task_domain(p);
872 ccs_tasklist_unlock();
873 } else if (!strncmp(data, "domain=", 7)) {
874 if (ccs_domain_def(data + 7))
875 domain = ccs_find_domain(data + 7);
876 } else
877 return false;
878 head->write_var1 = domain;
879 /* Accessing read_buf is safe because head->io_sem is held. */
880 if (!head->read_buf)
881 return true; /* Do nothing if open(O_WRONLY). */
882 head->read_avail = 0;
883 head->read_cond = false;
884 ccs_io_printf(head, "# select %s\n", data);
885 head->read_single_domain = true;
886 head->read_eof = !domain;
887 head->read_var1 = &domain->list;
888 head->read_var2 = NULL;
889 head->read_bit = 0;
890 head->read_step = 0;
891 if (domain && domain->is_deleted)
892 ccs_io_printf(head, "# This is a deleted domain.\n");
893 return true;
894 }
895
896 static int ccs_write_domain2(char *data, struct ccs_domain_info *domain,
897 const bool is_delete)
898 {
899 static const struct {
900 const char *keyword;
901 int (*write) (char *, struct ccs_domain_info *,
902 struct ccs_condition *, const bool);
903 } ccs_callback[5] = {
904 { CCS_KEYWORD_ALLOW_NETWORK, ccs_write_network },
905 { CCS_KEYWORD_ALLOW_ENV, ccs_write_env },
906 { CCS_KEYWORD_ALLOW_CAPABILITY, ccs_write_capability },
907 { CCS_KEYWORD_ALLOW_SIGNAL, ccs_write_signal },
908 { CCS_KEYWORD_ALLOW_MOUNT, ccs_write_mount }
909 };
910 int (*write) (char *, struct ccs_domain_info *, struct ccs_condition *,
911 const bool) = ccs_write_file;
912 int error;
913 u8 i;
914 struct ccs_condition *cond = NULL;
915 char *cp = ccs_find_condition_part(data);
916 if (cp) {
917 cond = ccs_get_condition(cp);
918 if (!cond)
919 return -EINVAL;
920 }
921 for (i = 0; i < 5; i++) {
922 if (!ccs_str_starts(&data, ccs_callback[i].keyword))
923 continue;
924 write = ccs_callback[i].write;
925 break;
926 }
927 error = write(data, domain, cond, is_delete);
928 if (cond)
929 ccs_put_condition(cond);
930 return error;
931 }
932
933 static const char *ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {
934 [CCS_DIF_QUOTA_WARNED] = CCS_KEYWORD_QUOTA_EXCEEDED "\n",
935 [CCS_DIF_IGNORE_GLOBAL] = CCS_KEYWORD_IGNORE_GLOBAL "\n",
936 [CCS_DIF_IGNORE_GLOBAL_ALLOW_READ]
937 = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n",
938 [CCS_DIF_IGNORE_GLOBAL_ALLOW_ENV]
939 = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n",
940 [CCS_DIF_TRANSITION_FAILED] = CCS_KEYWORD_TRANSITION_FAILED "\n"
941 };
942
943 /**
944 * ccs_write_domain - Write domain policy.
945 *
946 * @head: Pointer to "struct ccs_io_buffer".
947 *
948 * Returns 0 on success, negative value otherwise.
949 */
950 static int ccs_write_domain(struct ccs_io_buffer *head)
951 {
952 char *data = head->write_buf;
953 struct ccs_domain_info *domain = head->write_var1;
954 bool is_delete = false;
955 bool is_select = false;
956 unsigned int profile;
957 if (ccs_str_starts(&data, CCS_KEYWORD_DELETE))
958 is_delete = true;
959 else if (ccs_str_starts(&data, CCS_KEYWORD_SELECT))
960 is_select = true;
961 if (is_select && ccs_select_one(head, data))
962 return 0;
963 /* Don't allow updating policies by non manager programs. */
964 if (!ccs_manager())
965 return -EPERM;
966 if (ccs_domain_def(data)) {
967 domain = NULL;
968 if (is_delete)
969 ccs_delete_domain(data);
970 else if (is_select)
971 domain = ccs_find_domain(data);
972 else
973 domain = ccs_assign_domain(data, 0);
974 head->write_var1 = domain;
975 return 0;
976 }
977 if (!domain)
978 return -EINVAL;
979
980 if (sscanf(data, CCS_KEYWORD_USE_PROFILE "%u", &profile) == 1
981 && profile < CCS_MAX_PROFILES) {
982 if (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile])
983 domain->profile = (u8) profile;
984 return 0;
985 }
986 for (profile = 0; profile < CCS_MAX_DOMAIN_INFO_FLAGS; profile++) {
987 const char *cp = ccs_dif[profile];
988 if (strncmp(data, cp, strlen(cp) - 1))
989 continue;
990 domain->flags[profile] = !is_delete;
991 return 0;
992 }
993 return ccs_write_domain2(data, domain, is_delete);
994 }
995
996 /**
997 * ccs_print_name_union - Print a ccs_name_union.
998 *
999 * @head: Pointer to "struct ccs_io_buffer".
1000 * @ptr: Pointer to "struct ccs_name_union".
1001 *
1002 * Returns true on success, false otherwise.
1003 */
1004 static bool ccs_print_name_union(struct ccs_io_buffer *head,
1005 const struct ccs_name_union *ptr)
1006 {
1007 int pos = head->read_avail;
1008 if (pos && head->read_buf[pos - 1] == ' ')
1009 head->read_avail--;
1010 if (ptr->is_group)
1011 return ccs_io_printf(head, " @%s",
1012 ptr->group->group_name->name);
1013 return ccs_io_printf(head, " %s", ptr->filename->name);
1014 }
1015
1016 /**
1017 * ccs_print_name_union_quoted - Print a ccs_name_union with double quotes.
1018 *
1019 * @head: Pointer to "struct ccs_io_buffer".
1020 * @ptr: Pointer to "struct ccs_name_union".
1021 *
1022 * Returns true on success, false otherwise.
1023 */
1024 static bool ccs_print_name_union_quoted(struct ccs_io_buffer *head,
1025 const struct ccs_name_union *ptr)
1026 {
1027 if (ptr->is_group)
1028 return ccs_io_printf(head, "@%s",
1029 ptr->group->group_name->name);
1030 return ccs_io_printf(head, "\"%s\"", ptr->filename->name);
1031 }
1032
1033 static void ccs_print_number(char *buffer, int buffer_len,
1034 const struct ccs_number_union *ptr)
1035 {
1036 int i;
1037 unsigned long min = ptr->values[0];
1038 const unsigned long max = ptr->values[1];
1039 u8 min_type = ptr->value_type[0];
1040 const u8 max_type = ptr->value_type[1];
1041 memset(buffer, 0, buffer_len);
1042 buffer_len -= 2;
1043 for (i = 0; i < 2; i++) {
1044 int len;
1045 switch (min_type) {
1046 case CCS_VALUE_TYPE_HEXADECIMAL:
1047 snprintf(buffer, buffer_len, "0x%lX", min);
1048 break;
1049 case CCS_VALUE_TYPE_OCTAL:
1050 snprintf(buffer, buffer_len, "0%lo", min);
1051 break;
1052 default:
1053 snprintf(buffer, buffer_len, "%lu", min);
1054 break;
1055 }
1056 if (min == max && min_type == max_type)
1057 break;
1058 len = strlen(buffer);
1059 buffer[len++] = '-';
1060 buffer += len;
1061 buffer_len -= len;
1062 min_type = max_type;
1063 min = max;
1064 }
1065 }
1066
1067 /**
1068 * ccs_print_number_union_common - Print a ccs_number_union.
1069 *
1070 * @head: Pointer to "struct ccs_io_buffer".
1071 * @ptr: Pointer to "struct ccs_number_union".
1072 * @need_space: True if a space character is needed.
1073 *
1074 * Returns true on success, false otherwise.
1075 */
1076 static bool ccs_print_number_union_common(struct ccs_io_buffer *head,
1077 const struct ccs_number_union *ptr,
1078 const bool need_space)
1079 {
1080 char buffer[128];
1081 if (need_space && !ccs_io_printf(head, " "))
1082 return false;
1083 if (ptr->is_group)
1084 return ccs_io_printf(head, "@%s",
1085 ptr->group->group_name->name);
1086 ccs_print_number(buffer, sizeof(buffer), ptr);
1087 return ccs_io_printf(head, "%s", buffer);
1088 }
1089
1090 /**
1091 * ccs_print_number_union - Print a ccs_number_union.
1092 *
1093 * @head: Pointer to "struct ccs_io_buffer".
1094 * @ptr: Pointer to "struct ccs_number_union".
1095 *
1096 * Returns true on success, false otherwise.
1097 */
1098 static bool ccs_print_number_union(struct ccs_io_buffer *head,
1099 const struct ccs_number_union *ptr)
1100 {
1101 return ccs_print_number_union_common(head, ptr, true);
1102 }
1103
1104 /**
1105 * ccs_print_number_union_nospace - Print a ccs_number_union without a space character.
1106 *
1107 * @head: Pointer to "struct ccs_io_buffer".
1108 * @ptr: Pointer to "struct ccs_number_union".
1109 *
1110 * Returns true on success, false otherwise.
1111 */
1112 static bool ccs_print_number_union_nospace(struct ccs_io_buffer *head,
1113 const struct ccs_number_union *ptr)
1114 {
1115 return ccs_print_number_union_common(head, ptr, false);
1116 }
1117
1118 /**
1119 * ccs_print_condition - Print condition part.
1120 *
1121 * @head: Pointer to "struct ccs_io_buffer".
1122 * @cond: Pointer to "struct ccs_condition". Maybe NULL.
1123 *
1124 * Returns true on success, false otherwise.
1125 */
1126 static bool ccs_print_condition(struct ccs_io_buffer *head,
1127 const struct ccs_condition *cond)
1128 {
1129 const struct ccs_condition_element *condp;
1130 const struct ccs_number_union *numbers_p;
1131 const struct ccs_name_union *names_p;
1132 const struct ccs_argv *argv;
1133 const struct ccs_envp *envp;
1134 u16 condc;
1135 u16 i;
1136 u16 j;
1137 char buffer[32];
1138 if (!cond)
1139 goto no_condition;
1140 condc = cond->condc;
1141 condp = (const struct ccs_condition_element *) (cond + 1);
1142 numbers_p = (const struct ccs_number_union *) (condp + condc);
1143 names_p = (const struct ccs_name_union *)
1144 (numbers_p + cond->numbers_count);
1145 argv = (const struct ccs_argv *) (names_p + cond->names_count);
1146 envp = (const struct ccs_envp *) (argv + cond->argc);
1147 memset(buffer, 0, sizeof(buffer));
1148 if (condc && !ccs_io_printf(head, "%s", " if"))
1149 goto out;
1150 for (i = 0; i < condc; i++) {
1151 const u8 match = condp->equals;
1152 const u8 left = condp->left;
1153 const u8 right = condp->right;
1154 condp++;
1155 switch (left) {
1156 case CCS_ARGV_ENTRY:
1157 if (!ccs_io_printf(head, " exec.argv[%u]%s\"%s\"",
1158 argv->index, argv->is_not ?
1159 "!=" : "=", argv->value->name))
1160 goto out;
1161 argv++;
1162 continue;
1163 case CCS_ENVP_ENTRY:
1164 if (!ccs_io_printf(head, " exec.envp[\"%s\"]%s",
1165 envp->name->name, envp->is_not ?
1166 "!=" : "="))
1167 goto out;
1168 if (envp->value) {
1169 if (!ccs_io_printf(head, "\"%s\"",
1170 envp->value->name))
1171 goto out;
1172 } else {
1173 if (!ccs_io_printf(head, "NULL"))
1174 goto out;
1175 }
1176 envp++;
1177 continue;
1178 case CCS_NUMBER_UNION:
1179 if (!ccs_print_number_union(head, numbers_p++))
1180 goto out;
1181 break;
1182 default:
1183 if (left >= CCS_MAX_CONDITION_KEYWORD)
1184 goto out;
1185 if (!ccs_io_printf(head, " %s",
1186 ccs_condition_keyword[left]))
1187 goto out;
1188 break;
1189 }
1190 if (!ccs_io_printf(head, "%s", match ? "=" : "!="))
1191 goto out;
1192 switch (right) {
1193 case CCS_NAME_UNION:
1194 if (!ccs_print_name_union_quoted(head, names_p++))
1195 goto out;
1196 break;
1197 case CCS_NUMBER_UNION:
1198 if (!ccs_print_number_union_nospace(head, numbers_p++))
1199 goto out;
1200 break;
1201 default:
1202 if (right >= CCS_MAX_CONDITION_KEYWORD)
1203 goto out;
1204 if (!ccs_io_printf(head, "%s",
1205 ccs_condition_keyword[right]))
1206 goto out;
1207 break;
1208 }
1209 }
1210 i = cond->post_state[3];
1211 if (!i)
1212 goto no_condition;
1213 if (!ccs_io_printf(head, " ; set"))
1214 goto out;
1215 for (j = 0; j < 3; j++) {
1216 if (!(i & (1 << j)))
1217 continue;
1218 if (!ccs_io_printf(head, " task.state[%u]=%u", j,
1219 cond->post_state[j]))
1220 goto out;
1221 }
1222 if (i & (1 << 4)) {
1223 if (!ccs_io_printf(head, " audit=%s",
1224 ccs_yesno(cond->post_state[4])))
1225 goto out;
1226 }
1227 no_condition:
1228 if (ccs_io_printf(head, "\n"))
1229 return true;
1230 out:
1231 return false;
1232 }
1233
1234 /**
1235 * ccs_print_entry - Print an ACL entry.
1236 *
1237 * @head: Pointer to "struct ccs_io_buffer".
1238 * @ptr: Pointer to an ACL entry.
1239 *
1240 * Returns true on success, false otherwise.
1241 */
1242 static bool ccs_print_entry(struct ccs_io_buffer *head,
1243 const struct ccs_acl_info *acl)
1244 {
1245 int pos;
1246 const u8 acl_type = acl->type;
1247 u8 bit = head->read_bit;
1248 if (head->read_cond)
1249 goto print_cond;
1250 if (acl->is_deleted)
1251 return true;
1252 next:
1253 pos = head->read_avail;
1254 if (acl_type == CCS_TYPE_PATH_ACL) {
1255 struct ccs_path_acl *ptr
1256 = container_of(acl, typeof(*ptr), head);
1257 const u16 perm = ptr->perm;
1258 for ( ; bit < CCS_MAX_PATH_OPERATION; bit++) {
1259 if (!(perm & (1 << bit)))
1260 continue;
1261 if (head->read_execute_only && bit != CCS_TYPE_EXECUTE
1262 && bit != CCS_TYPE_TRANSIT)
1263 continue;
1264 /* Print "read/write" instead of "read" and "write". */
1265 if ((bit == CCS_TYPE_READ || bit == CCS_TYPE_WRITE)
1266 && (perm & (1 << CCS_TYPE_READ_WRITE)))
1267 continue;
1268 break;
1269 }
1270 if (bit == CCS_MAX_PATH_OPERATION)
1271 goto done;
1272 if (!ccs_io_printf(head, "allow_%s", ccs_path_keyword[bit]) ||
1273 !ccs_print_name_union(head, &ptr->name))
1274 goto fail;
1275 } else if (acl_type == CCS_TYPE_EXECUTE_HANDLER ||
1276 acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
1277 struct ccs_execute_handler *ptr
1278 = container_of(acl, typeof(*ptr), head);
1279 if (!ccs_io_printf(head, "%s %s",
1280 acl_type == CCS_TYPE_EXECUTE_HANDLER ?
1281 CCS_KEYWORD_EXECUTE_HANDLER :
1282 CCS_KEYWORD_DENIED_EXECUTE_HANDLER,
1283 ptr->handler->name))
1284 goto fail;
1285 } if (head->read_execute_only) {
1286 return true;
1287 } else if (acl_type == CCS_TYPE_MKDEV_ACL) {
1288 struct ccs_mkdev_acl *ptr
1289 = container_of(acl, typeof(*ptr), head);
1290 const u8 perm = ptr->perm;
1291 for ( ; bit < CCS_MAX_MKDEV_OPERATION; bit++) {
1292 if (!(perm & (1 << bit)))
1293 continue;
1294 break;
1295 }
1296 if (bit == CCS_MAX_MKDEV_OPERATION)
1297 goto done;
1298 if (!ccs_io_printf(head, "allow_%s", ccs_mkdev_keyword[bit]) ||
1299 !ccs_print_name_union(head, &ptr->name) ||
1300 !ccs_print_number_union(head, &ptr->mode) ||
1301 !ccs_print_number_union(head, &ptr->major) ||
1302 !ccs_print_number_union(head, &ptr->minor))
1303 goto fail;
1304 } else if (acl_type == CCS_TYPE_PATH2_ACL) {
1305 struct ccs_path2_acl *ptr
1306 = container_of(acl, typeof(*ptr), head);
1307 const u8 perm = ptr->perm;
1308 for ( ; bit < CCS_MAX_PATH2_OPERATION; bit++) {
1309 if (!(perm & (1 << bit)))
1310 continue;
1311 break;
1312 }
1313 if (bit == CCS_MAX_PATH2_OPERATION)
1314 goto done;
1315 if (!ccs_io_printf(head, "allow_%s", ccs_path2_keyword[bit]) ||
1316 !ccs_print_name_union(head, &ptr->name1) ||
1317 !ccs_print_name_union(head, &ptr->name2))
1318 goto fail;
1319 } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
1320 struct ccs_path_number_acl *ptr
1321 = container_of(acl, typeof(*ptr), head);
1322 const u8 perm = ptr->perm;
1323 for ( ; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) {
1324 if (!(perm & (1 << bit)))
1325 continue;
1326 break;
1327 }
1328 if (bit == CCS_MAX_PATH_NUMBER_OPERATION)
1329 goto done;
1330 if (!ccs_io_printf(head, "allow_%s",
1331 ccs_path_number_keyword[bit]) ||
1332 !ccs_print_name_union(head, &ptr->name) ||
1333 !ccs_print_number_union(head, &ptr->number))
1334 goto fail;
1335 } else if (acl_type == CCS_TYPE_ENV_ACL) {
1336 struct ccs_env_acl *ptr
1337 = container_of(acl, typeof(*ptr), head);
1338 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_ENV "%s",
1339 ptr->env->name))
1340 goto fail;
1341 } else if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
1342 struct ccs_capability_acl *ptr
1343 = container_of(acl, typeof(*ptr), head);
1344 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CAPABILITY "%s",
1345 ccs_cap2keyword(ptr->operation)))
1346 goto fail;
1347 } else if (acl_type == CCS_TYPE_IP_NETWORK_ACL) {
1348 struct ccs_ip_network_acl *ptr
1349 = container_of(acl, typeof(*ptr), head);
1350 char buf[128];
1351 const char *w[2] = { buf, "" };
1352 const u8 perm = ptr->perm;
1353 for ( ; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1354 if (!(perm & (1 << bit)))
1355 continue;
1356 break;
1357 }
1358 if (bit == CCS_MAX_NETWORK_OPERATION)
1359 goto done;
1360 switch (ptr->address_type) {
1361 case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:
1362 w[0] = "@";
1363 w[1] = ptr->address.group->group_name->name;
1364 break;
1365 case CCS_IP_ADDRESS_TYPE_IPv4:
1366 ccs_print_ipv4(buf, sizeof(buf), ptr->address.ipv4.min,
1367 ptr->address.ipv4.max);
1368 break;
1369 case CCS_IP_ADDRESS_TYPE_IPv6:
1370 ccs_print_ipv6(buf, sizeof(buf), ptr->address.ipv6.min,
1371 ptr->address.ipv6.max);
1372 break;
1373 }
1374 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s %s%s",
1375 ccs_net_keyword[bit], w[0], w[1]) ||
1376 !ccs_print_number_union(head, &ptr->port))
1377 goto fail;
1378 } else if (acl_type == CCS_TYPE_SIGNAL_ACL) {
1379 struct ccs_signal_acl *ptr
1380 = container_of(acl, typeof(*ptr), head);
1381 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u %s",
1382 ptr->sig, ptr->domainname->name))
1383 goto fail;
1384 } else if (acl_type == CCS_TYPE_MOUNT_ACL) {
1385 struct ccs_mount_acl *ptr
1386 = container_of(acl, typeof(*ptr), head);
1387 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_MOUNT) ||
1388 !ccs_print_name_union(head, &ptr->dev_name) ||
1389 !ccs_print_name_union(head, &ptr->dir_name) ||
1390 !ccs_print_name_union(head, &ptr->fs_type) ||
1391 !ccs_print_number_union(head, &ptr->flags))
1392 goto fail;
1393 }
1394 head->read_bit = bit;
1395 head->read_cond = true;
1396 print_cond:
1397 pos = head->read_avail;
1398 if (!ccs_print_condition(head, acl->cond)) {
1399 head->read_avail = pos;
1400 return false;
1401 }
1402 head->read_cond = false;
1403 switch (acl_type) {
1404 case CCS_TYPE_PATH_ACL:
1405 case CCS_TYPE_MKDEV_ACL:
1406 case CCS_TYPE_PATH2_ACL:
1407 case CCS_TYPE_PATH_NUMBER_ACL:
1408 case CCS_TYPE_IP_NETWORK_ACL:
1409 bit++;
1410 goto next;
1411 }
1412 done:
1413 head->read_bit = 0;
1414 return true;
1415 fail:
1416 head->read_bit = bit;
1417 head->read_avail = pos;
1418 return false;
1419 }
1420
1421 /**
1422 * ccs_read_domain2 - Read domain policy.
1423 *
1424 * @head: Pointer to "struct ccs_io_buffer".
1425 * @domain: Pointer to "struct ccs_domain_info".
1426 *
1427 * Caller holds ccs_read_lock().
1428 *
1429 * Returns true on success, false otherwise.
1430 */
1431 static bool ccs_read_domain2(struct ccs_io_buffer *head,
1432 struct ccs_domain_info *domain)
1433 {
1434 struct list_head *pos;
1435 /* Print ACL entries in the domain. */
1436 list_for_each_cookie(pos, head->read_var2, &domain->acl_info_list) {
1437 struct ccs_acl_info *ptr
1438 = list_entry(pos, struct ccs_acl_info, list);
1439 if (!ccs_print_entry(head, ptr))
1440 return false;
1441 }
1442 return true;
1443 }
1444
1445 /**
1446 * ccs_read_domain - Read domain policy.
1447 *
1448 * @head: Pointer to "struct ccs_io_buffer".
1449 *
1450 * Caller holds ccs_read_lock().
1451 */
1452 static void ccs_read_domain(struct ccs_io_buffer *head)
1453 {
1454 struct list_head *pos;
1455 if (head->read_eof)
1456 return;
1457 list_for_each_cookie(pos, head->read_var1, &ccs_domain_list) {
1458 struct ccs_domain_info *domain =
1459 list_entry(pos, struct ccs_domain_info, list);
1460 switch (head->read_step) {
1461 u8 i;
1462 const char *w[CCS_MAX_DOMAIN_INFO_FLAGS];
1463 case 0:
1464 if (domain->is_deleted && !head->read_single_domain)
1465 continue;
1466 /* Print domainname and flags. */
1467 for (i = 0; i < CCS_MAX_DOMAIN_INFO_FLAGS; i++)
1468 w[i] = domain->flags[i] ? ccs_dif[i] : "";
1469 if (!ccs_io_printf(head, "%s\n" CCS_KEYWORD_USE_PROFILE
1470 "%u\n%s%s%s%s%s\n",
1471 domain->domainname->name,
1472 domain->profile,
1473 w[CCS_DIF_QUOTA_WARNED],
1474 w[CCS_DIF_IGNORE_GLOBAL],
1475 w[CCS_DIF_IGNORE_GLOBAL_ALLOW_READ],
1476 w[CCS_DIF_IGNORE_GLOBAL_ALLOW_ENV],
1477 w[CCS_DIF_TRANSITION_FAILED]))
1478 return;
1479 head->read_step++;
1480 /* fall through */
1481 case 1:
1482 if (!ccs_read_domain2(head, domain))
1483 return;
1484 head->read_step++;
1485 /* fall through */
1486 case 2:
1487 if (!ccs_io_printf(head, "\n"))
1488 return;
1489 head->read_step = 0;
1490 if (head->read_single_domain)
1491 goto out;
1492 }
1493 }
1494 out:
1495 head->read_eof = true;
1496 }
1497
1498 /**
1499 * ccs_write_domain_profile - Assign profile for specified domain.
1500 *
1501 * @head: Pointer to "struct ccs_io_buffer".
1502 *
1503 * Returns 0 on success, -EINVAL otherwise.
1504 *
1505 * This is equivalent to doing
1506 *
1507 * ( echo "select " $domainname; echo "use_profile " $profile ) |
1508 * /usr/sbin/ccs-loadpolicy -d
1509 *
1510 * Caller holds ccs_read_lock().
1511 */
1512 static int ccs_write_domain_profile(struct ccs_io_buffer *head)
1513 {
1514 char *data = head->write_buf;
1515 char *cp = strchr(data, ' ');
1516 struct ccs_domain_info *domain;
1517 unsigned int profile;
1518 if (!cp)
1519 return -EINVAL;
1520 *cp = '\0';
1521 profile = simple_strtoul(data, NULL, 10);
1522 if (profile >= CCS_MAX_PROFILES)
1523 return -EINVAL;
1524 domain = ccs_find_domain(cp + 1);
1525 if (domain && (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile]))
1526 domain->profile = (u8) profile;
1527 return 0;
1528 }
1529
1530 /**
1531 * ccs_read_domain_profile - Read only domainname and profile.
1532 *
1533 * @head: Pointer to "struct ccs_io_buffer".
1534 *
1535 * This is equivalent to doing
1536 *
1537 * grep -A 1 '^<kernel>' /proc/ccs/domain_policy |
1538 * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
1539 * domainname = $0; } else if ( $1 == "use_profile" ) {
1540 * print $2 " " domainname; domainname = ""; } } ; '
1541 *
1542 * Caller holds ccs_read_lock().
1543 */
1544 static void ccs_read_domain_profile(struct ccs_io_buffer *head)
1545 {
1546 struct list_head *pos;
1547 if (head->read_eof)
1548 return;
1549 list_for_each_cookie(pos, head->read_var1, &ccs_domain_list) {
1550 struct ccs_domain_info *domain;
1551 domain = list_entry(pos, struct ccs_domain_info, list);
1552 if (domain->is_deleted)
1553 continue;
1554 if (!ccs_io_printf(head, "%u %s\n", domain->profile,
1555 domain->domainname->name))
1556 return;
1557 }
1558 head->read_eof = true;
1559 }
1560
1561 /**
1562 * ccs_write_pid: Specify PID to obtain domainname.
1563 *
1564 * @head: Pointer to "struct ccs_io_buffer".
1565 *
1566 * Returns 0.
1567 */
1568 static int ccs_write_pid(struct ccs_io_buffer *head)
1569 {
1570 head->read_eof = false;
1571 return 0;
1572 }
1573
1574 /**
1575 * ccs_read_pid - Read information of a process.
1576 *
1577 * @head: Pointer to "struct ccs_io_buffer".
1578 *
1579 * Returns the domainname which the specified PID is in or
1580 * process information of the specified PID on success,
1581 * empty string otherwise.
1582 *
1583 * Caller holds ccs_read_lock().
1584 */
1585 static void ccs_read_pid(struct ccs_io_buffer *head)
1586 {
1587 char *buf = head->write_buf;
1588 bool task_info = false;
1589 bool global_pid = false;
1590 unsigned int pid;
1591 struct task_struct *p;
1592 struct ccs_domain_info *domain = NULL;
1593 u32 ccs_flags = 0;
1594 /* Accessing write_buf is safe because head->io_sem is held. */
1595 if (!buf) {
1596 head->read_eof = true;
1597 return; /* Do nothing if open(O_RDONLY). */
1598 }
1599 if (head->read_avail || head->read_eof)
1600 return;
1601 head->read_eof = true;
1602 if (ccs_str_starts(&buf, "info "))
1603 task_info = true;
1604 if (ccs_str_starts(&buf, "global-pid "))
1605 global_pid = true;
1606 pid = (unsigned int) simple_strtoul(buf, NULL, 10);
1607 ccs_tasklist_lock();
1608 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1609 if (global_pid)
1610 p = ccsecurity_exports.find_task_by_pid_ns(pid, &init_pid_ns);
1611 else
1612 p = ccsecurity_exports.find_task_by_vpid(pid);
1613 #else
1614 p = find_task_by_pid(pid);
1615 #endif
1616 if (p) {
1617 domain = ccs_task_domain(p);
1618 ccs_flags = p->ccs_flags;
1619 }
1620 ccs_tasklist_unlock();
1621 if (!domain)
1622 return;
1623 if (!task_info)
1624 ccs_io_printf(head, "%u %u %s", pid, domain->profile,
1625 domain->domainname->name);
1626 else
1627 ccs_io_printf(head, "%u manager=%s execute_handler=%s "
1628 "state[0]=%u state[1]=%u state[2]=%u", pid,
1629 ccs_yesno(ccs_flags &
1630 CCS_TASK_IS_MANAGER),
1631 ccs_yesno(ccs_flags &
1632 CCS_TASK_IS_EXECUTE_HANDLER),
1633 (u8) (ccs_flags >> 24),
1634 (u8) (ccs_flags >> 16),
1635 (u8) (ccs_flags >> 8));
1636 }
1637
1638 static const char *ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {
1639 [CCS_TRANSITION_CONTROL_NO_INITIALIZE]
1640 = CCS_KEYWORD_NO_INITIALIZE_DOMAIN,
1641 [CCS_TRANSITION_CONTROL_INITIALIZE] = CCS_KEYWORD_INITIALIZE_DOMAIN,
1642 [CCS_TRANSITION_CONTROL_NO_KEEP] = CCS_KEYWORD_NO_KEEP_DOMAIN,
1643 [CCS_TRANSITION_CONTROL_KEEP] = CCS_KEYWORD_KEEP_DOMAIN
1644 };
1645
1646 static const char *ccs_group_name[CCS_MAX_GROUP] = {
1647 [CCS_PATH_GROUP] = CCS_KEYWORD_PATH_GROUP,
1648 [CCS_NUMBER_GROUP] = CCS_KEYWORD_NUMBER_GROUP,
1649 [CCS_ADDRESS_GROUP] = CCS_KEYWORD_ADDRESS_GROUP
1650 };
1651
1652 /**
1653 * ccs_write_exception - Write exception policy.
1654 *
1655 * @head: Pointer to "struct ccs_io_buffer".
1656 *
1657 * Returns 0 on success, negative value otherwise.
1658 */
1659 static int ccs_write_exception(struct ccs_io_buffer *head)
1660 {
1661 char *data = head->write_buf;
1662 const bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);
1663 u8 i;
1664 static const struct {
1665 const char *keyword;
1666 int (*write) (char *, const bool);
1667 } ccs_callback[4] = {
1668 { CCS_KEYWORD_AGGREGATOR, ccs_write_aggregator },
1669 { CCS_KEYWORD_FILE_PATTERN, ccs_write_pattern },
1670 { CCS_KEYWORD_DENY_REWRITE, ccs_write_no_rewrite },
1671 { CCS_KEYWORD_DENY_AUTOBIND, ccs_write_reserved_port }
1672 };
1673 for (i = 0; i < 4; i++) {
1674 if (ccs_str_starts(&data, ccs_callback[i].keyword))
1675 return ccs_callback[i].write(data, is_delete);
1676 }
1677 for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++) {
1678 if (ccs_str_starts(&data, ccs_transition_type[i]))
1679 return ccs_write_transition_control(data, is_delete,
1680 i);
1681 }
1682 for (i = 0; i < CCS_MAX_GROUP; i++) {
1683 if (ccs_str_starts(&data, ccs_group_name[i]))
1684 return ccs_write_group(data, is_delete, i);
1685 }
1686 return ccs_write_domain2(data, &ccs_global_domain, is_delete);
1687 }
1688
1689 /**
1690 * ccs_read_group - Read "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group" list.
1691 *
1692 * @head: Pointer to "struct ccs_io_buffer".
1693 * @idx: Index number.
1694 *
1695 * Returns true on success, false otherwise.
1696 *
1697 * Caller holds ccs_read_lock().
1698 */
1699 static bool ccs_read_group(struct ccs_io_buffer *head, const int idx)
1700 {
1701 struct list_head *gpos;
1702 struct list_head *mpos;
1703 const char *w[3] = { "", "", "" };
1704 w[0] = ccs_group_name[idx];
1705 list_for_each_cookie(gpos, head->read_var1, &ccs_group_list[idx]) {
1706 struct ccs_group *group =
1707 list_entry(gpos, struct ccs_group, head.list);
1708 w[1] = group->group_name->name;
1709 list_for_each_cookie(mpos, head->read_var2,
1710 &group->member_list) {
1711 char buffer[128];
1712 struct ccs_acl_head *ptr =
1713 list_entry(mpos, struct ccs_acl_head, list);
1714 if (ptr->is_deleted)
1715 continue;
1716 w[2] = buffer;
1717 if (idx == CCS_PATH_GROUP) {
1718 w[2] = container_of(ptr, struct ccs_path_group,
1719 head)->member_name->name;
1720 } else if (idx == CCS_NUMBER_GROUP) {
1721 ccs_print_number(buffer, sizeof(buffer),
1722 &container_of
1723 (ptr, struct ccs_number_group,
1724 head)->number);
1725 } else if (idx == CCS_ADDRESS_GROUP) {
1726 struct ccs_address_group *member =
1727 container_of(ptr, typeof(*member),
1728 head);
1729 if (member->is_ipv6)
1730 ccs_print_ipv6(buffer, sizeof(buffer),
1731 member->min.ipv6,
1732 member->max.ipv6);
1733 else
1734 ccs_print_ipv4(buffer, sizeof(buffer),
1735 member->min.ipv4,
1736 member->max.ipv4);
1737 }
1738 if (!ccs_io_printf(head, "%s%s %s\n", w[0], w[1],
1739 w[2]))
1740 return false;
1741 }
1742 }
1743 return true;
1744 }
1745
1746 /**
1747 * ccs_read_policy - Read "struct ccs_..._entry" list.
1748 *
1749 * @head: Pointer to "struct ccs_io_buffer".
1750 * @idx: Index number.
1751 *
1752 * Returns true on success, false otherwise.
1753 *
1754 * Caller holds ccs_read_lock().
1755 */
1756 static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx)
1757 {
1758 struct list_head *pos;
1759 list_for_each_cookie(pos, head->read_var2, &ccs_policy_list[idx]) {
1760 const char *w[4] = { "", "", "", "" };
1761 char buffer[16];
1762 struct ccs_acl_head *acl = container_of(pos, typeof(*acl),
1763 list);
1764 if (acl->is_deleted)
1765 continue;
1766 switch (idx) {
1767 case CCS_ID_TRANSITION_CONTROL:
1768 {
1769 struct ccs_transition_control *ptr =
1770 container_of(acl, typeof(*ptr), head);
1771 w[0] = ccs_transition_type[ptr->type];
1772 w[1] = ptr->program ? ptr->program->name
1773 : "any";
1774 w[2] = " from ";
1775 w[3] = ptr->domainname ? ptr->domainname->name
1776 : "any";
1777 }
1778 break;
1779 case CCS_ID_AGGREGATOR:
1780 {
1781 struct ccs_aggregator *ptr =
1782 container_of(acl, typeof(*ptr), head);
1783 w[0] = CCS_KEYWORD_AGGREGATOR;
1784 w[1] = ptr->original_name->name;
1785 w[2] = " ";
1786 w[3] = ptr->aggregated_name->name;
1787 }
1788 break;
1789 case CCS_ID_PATTERN:
1790 {
1791 struct ccs_pattern *ptr =
1792 container_of(acl, typeof(*ptr), head);
1793 w[0] = CCS_KEYWORD_FILE_PATTERN;
1794 w[1] = ptr->pattern->name;
1795 }
1796 break;
1797 case CCS_ID_NO_REWRITE:
1798 {
1799 struct ccs_no_rewrite *ptr =
1800 container_of(acl, typeof(*ptr), head);
1801 w[0] = CCS_KEYWORD_DENY_REWRITE;
1802 w[1] = ptr->pattern->name;
1803 }
1804 break;
1805 case CCS_ID_RESERVEDPORT:
1806 {
1807 struct ccs_reserved *ptr =
1808 container_of(acl, typeof(*ptr), head);
1809 const u16 min_port = ptr->min_port;
1810 const u16 max_port = ptr->max_port;
1811 w[0] = CCS_KEYWORD_DENY_AUTOBIND;
1812 snprintf(buffer, sizeof(buffer) - 1, "%u%c%u",
1813 min_port, min_port != max_port ?
1814 '-' : '\0', max_port);
1815 buffer[sizeof(buffer) - 1] = '\0';
1816 w[1] = buffer;
1817 }
1818 break;
1819 default:
1820 continue;
1821 }
1822 if (!ccs_io_printf(head, "%s%s%s%s\n", w[0], w[1], w[2], w[3]))
1823 return false;
1824 }
1825 return true;
1826 }
1827
1828 static void ccs_read_global_domain(struct ccs_io_buffer *head)
1829 {
1830 if (!head->read_eof)
1831 head->read_eof = ccs_read_domain2(head, &ccs_global_domain);
1832 }
1833
1834 /**
1835 * ccs_read_exception - Read exception policy.
1836 *
1837 * @head: Pointer to "struct ccs_io_buffer".
1838 *
1839 * Caller holds ccs_read_lock().
1840 */
1841 static void ccs_read_exception(struct ccs_io_buffer *head)
1842 {
1843 if (head->read_eof)
1844 return;
1845 while (head->read_step < CCS_MAX_POLICY &&
1846 ccs_read_policy(head, head->read_step))
1847 head->read_step++;
1848 if (head->read_step < CCS_MAX_POLICY)
1849 return;
1850 while (head->read_step < CCS_MAX_POLICY + CCS_MAX_GROUP &&
1851 ccs_read_group(head, head->read_step - CCS_MAX_POLICY))
1852 head->read_step++;
1853 if (head->read_step < CCS_MAX_POLICY + CCS_MAX_GROUP)
1854 return;
1855 head->read = ccs_read_global_domain;
1856 }
1857
1858 /* Wait queue for ccs_query_list. */
1859 static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
1860
1861 /* Lock for manipulating ccs_query_list. */
1862 static DEFINE_SPINLOCK(ccs_query_list_lock);
1863
1864 /* Structure for query. */
1865 struct ccs_query_entry {
1866 struct list_head list;
1867 char *query;
1868 int query_len;
1869 unsigned int serial;
1870 int timer;
1871 int answer;
1872 };
1873
1874 /* The list for "struct ccs_query_entry". */
1875 static LIST_HEAD(ccs_query_list);
1876
1877 /* Number of "struct file" referring /proc/ccs/query interface. */
1878 static atomic_t ccs_query_observers = ATOMIC_INIT(0);
1879
1880 static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
1881 {
1882 va_list args;
1883 const int pos = strlen(buffer);
1884 va_start(args, fmt);
1885 vsnprintf(buffer + pos, len - pos - 1, fmt, args);
1886 va_end(args);
1887 }
1888
1889 static void ccs_truncate(char *str)
1890 {
1891 while (* (unsigned char *) str > (unsigned char) ' ')
1892 str++;
1893 *str = '\0';
1894 }
1895
1896 /**
1897 * ccs_supervisor - Ask for the supervisor's decision.
1898 *
1899 * @r: Pointer to "struct ccs_request_info".
1900 * @fmt: The printf()'s format string, followed by parameters.
1901 *
1902 * Returns 0 if the supervisor decided to permit the access request which
1903 * violated the policy in enforcing mode, CCS_RETRY_REQUEST if the supervisor
1904 * decided to retry the access request which violated the policy in enforcing
1905 * mode, 0 if it is not in enforcing mode, -EPERM otherwise.
1906 */
1907 int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)
1908 {
1909 va_list args;
1910 int error = -EPERM;
1911 int pos;
1912 int len;
1913 static unsigned int ccs_serial;
1914 struct ccs_query_entry *ccs_query_entry = NULL;
1915 bool quota_exceeded = false;
1916 char *header;
1917 struct ccs_domain_info * const domain = ccs_current_domain();
1918 va_start(args, fmt);
1919 len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 80;
1920 va_end(args);
1921 if (r->mode == CCS_CONFIG_LEARNING) {
1922 char *buffer;
1923 char *realpath = NULL;
1924 char *argv0 = NULL;
1925 char *symlink = NULL;
1926 char *handler = NULL;
1927 const struct ccs_preference *pref;
1928 if (!ccs_domain_quota_ok(r))
1929 return 0;
1930 header = ccs_init_log(&len, r);
1931 if (!header)
1932 return 0;
1933 pref = ccs_profile(r->profile)->learning;
1934 /* strstr() will return NULL if ordering is wrong. */
1935 if (r->param_type == CCS_TYPE_PATH_ACL &&
1936 r->param.path.operation == CCS_TYPE_EXECUTE) {
1937 if (pref->learning_exec_argv0) {
1938 argv0 = strstr(header, " argv[]={ \"");
1939 if (argv0) {
1940 argv0 += 10;
1941 ccs_truncate(argv0);
1942 }
1943 }
1944 if (pref->learning_exec_realpath) {
1945 realpath = strstr(header,
1946 " exec={ realpath=\"");
1947 if (realpath) {
1948 realpath += 8;
1949 ccs_truncate(realpath);
1950 }
1951 }
1952 } else if (r->param_type == CCS_TYPE_PATH_ACL &&
1953 r->param.path.operation == CCS_TYPE_SYMLINK &&
1954 pref->learning_symlink_target) {
1955 symlink = strstr(header, " symlink.target=\"");
1956 if (symlink)
1957 ccs_truncate(symlink + 1);
1958 }
1959 handler = strstr(header, "type=execute_handler");
1960 if (handler)
1961 ccs_truncate(handler);
1962 buffer = kmalloc(len, CCS_GFP_FLAGS);
1963 if (buffer) {
1964 va_start(args, fmt);
1965 vsnprintf(buffer, len - 1, fmt, args);
1966 va_end(args);
1967 if (handler || realpath || argv0 || symlink) {
1968 ccs_addprintf(buffer, len, " if");
1969 if (handler)
1970 ccs_addprintf(buffer, len, " task.%s",
1971 handler);
1972 if (realpath)
1973 ccs_addprintf(buffer, len, " exec.%s",
1974 realpath);
1975 if (argv0)
1976 ccs_addprintf(buffer, len,
1977 " exec.argv[0]=%s",
1978 argv0);
1979 if (symlink)
1980 ccs_addprintf(buffer, len, "%s",
1981 symlink);
1982 }
1983 ccs_normalize_line(buffer);
1984 ccs_write_domain2(buffer, domain, false);
1985 kfree(buffer);
1986 }
1987 kfree(header);
1988 return 0;
1989 }
1990 if (r->mode != CCS_CONFIG_ENFORCING)
1991 return 0;
1992 if (!atomic_read(&ccs_query_observers)) {
1993 int i;
1994 if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)
1995 return -EPERM;
1996 for (i = 0; i < ccs_profile(domain->profile)->enforcing->
1997 enforcing_penalty; i++) {
1998 set_current_state(TASK_INTERRUPTIBLE);
1999 schedule_timeout(HZ / 10);
2000 }
2001 return -EPERM;
2002 }
2003 header = ccs_init_log(&len, r);
2004 if (!header)
2005 goto out;
2006 ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), CCS_GFP_FLAGS);
2007 if (!ccs_query_entry)
2008 goto out;
2009 len = ccs_round2(len);
2010 ccs_query_entry->query = kzalloc(len, CCS_GFP_FLAGS);
2011 if (!ccs_query_entry->query)
2012 goto out;
2013 INIT_LIST_HEAD(&ccs_query_entry->list);
2014 spin_lock(&ccs_query_list_lock);
2015 if (ccs_quota_for_query && ccs_query_memory_size + len +
2016 sizeof(*ccs_query_entry) >= ccs_quota_for_query) {
2017 quota_exceeded = true;
2018 } else {
2019 ccs_query_memory_size += len + sizeof(*ccs_query_entry);
2020 ccs_query_entry->serial = ccs_serial++;
2021 }
2022 spin_unlock(&ccs_query_list_lock);
2023 if (quota_exceeded)
2024 goto out;
2025 snprintf(ccs_query_entry->query, len - 1, "Q%u-%hu\n%s",
2026 ccs_query_entry->serial, r->retry, header);
2027 kfree(header);
2028 header = NULL;
2029 ccs_addprintf(ccs_query_entry->query, len, fmt, args);
2030 ccs_query_entry->query_len = strlen(ccs_query_entry->query) + 1;
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 = CCS_RETRY_REQUEST;
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, CCS_GFP_FLAGS);
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.2");
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), CCS_GFP_FLAGS);
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;
2256 head->read = ccs_read_domain;
2257 break;
2258 case CCS_EXCEPTIONPOLICY: /* /proc/ccs/exception_policy */
2259 head->write = ccs_write_exception;
2260 head->read = ccs_read_exception;
2261 break;
2262 #ifdef CONFIG_CCSECURITY_AUDIT
2263 case CCS_GRANTLOG: /* /proc/ccs/grant_log */
2264 case CCS_REJECTLOG: /* /proc/ccs/reject_log */
2265 head->poll = ccs_poll_log;
2266 head->read = ccs_read_log;
2267 break;
2268 #endif
2269 case CCS_SELFDOMAIN: /* /proc/ccs/self_domain */
2270 head->read = ccs_read_self_domain;
2271 break;
2272 case CCS_DOMAIN_STATUS: /* /proc/ccs/.domain_status */
2273 head->write = ccs_write_domain_profile;
2274 head->read = ccs_read_domain_profile;
2275 break;
2276 case CCS_EXECUTE_HANDLER: /* /proc/ccs/.execute_handler */
2277 /* Allow execute_handler to read process's status. */
2278 if (!(current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {
2279 kfree(head);
2280 return -EPERM;
2281 }
2282 /* fall through */
2283 case CCS_PROCESS_STATUS: /* /proc/ccs/.process_status */
2284 head->write = ccs_write_pid;
2285 head->read = ccs_read_pid;
2286 break;
2287 case CCS_VERSION: /* /proc/ccs/version */
2288 head->read = ccs_read_version;
2289 head->readbuf_size = 128;
2290 break;
2291 case CCS_MEMINFO: /* /proc/ccs/meminfo */
2292 head->write = ccs_write_memory_quota;
2293 head->read = ccs_read_memory_counter;
2294 head->readbuf_size = 512;
2295 break;
2296 case CCS_PROFILE: /* /proc/ccs/profile */
2297 head->write = ccs_write_profile;
2298 head->read = ccs_read_profile;
2299 break;
2300 case CCS_QUERY: /* /proc/ccs/query */
2301 head->poll = ccs_poll_query;
2302 head->write = ccs_write_answer;
2303 head->read = ccs_read_query;
2304 break;
2305 case CCS_MANAGER: /* /proc/ccs/manager */
2306 head->write = ccs_write_manager;
2307 head->read = ccs_read_manager;
2308 break;
2309 }
2310 if (!(file->f_mode & FMODE_READ)) {
2311 /*
2312 * No need to allocate read_buf since it is not opened
2313 * for reading.
2314 */
2315 head->read = NULL;
2316 head->poll = NULL;
2317 } else if (!head->poll) {
2318 /* Don't allocate read_buf for poll() access. */
2319 if (!head->readbuf_size)
2320 head->readbuf_size = 4096;
2321 head->read_buf = kzalloc(head->readbuf_size, CCS_GFP_FLAGS);
2322 if (!head->read_buf) {
2323 kfree(head);
2324 return -ENOMEM;
2325 }
2326 }
2327 if (!(file->f_mode & FMODE_WRITE)) {
2328 /*
2329 * No need to allocate write_buf since it is not opened
2330 * for writing.
2331 */
2332 head->write = NULL;
2333 } else if (head->write) {
2334 head->writebuf_size = 4096;
2335 head->write_buf = kzalloc(head->writebuf_size, CCS_GFP_FLAGS);
2336 if (!head->write_buf) {
2337 kfree(head->read_buf);
2338 kfree(head);
2339 return -ENOMEM;
2340 }
2341 }
2342 if (type != CCS_QUERY &&
2343 type != CCS_GRANTLOG && type != CCS_REJECTLOG)
2344 head->reader_idx = ccs_lock();
2345 file->private_data = head;
2346 /*
2347 * Call the handler now if the file is /proc/ccs/self_domain
2348 * so that the user can use "cat < /proc/ccs/self_domain" to
2349 * know the current process's domainname.
2350 */
2351 if (type == CCS_SELFDOMAIN)
2352 ccs_read_control(file, NULL, 0);
2353 /*
2354 * If the file is /proc/ccs/query , increment the observer counter.
2355 * The obserber counter is used by ccs_supervisor() to see if
2356 * there is some process monitoring /proc/ccs/query.
2357 */
2358 else if (type == CCS_QUERY)
2359 atomic_inc(&ccs_query_observers);
2360 return 0;
2361 }
2362
2363 /**
2364 * ccs_poll_control - poll() for /proc/ccs/ interface.
2365 *
2366 * @file: Pointer to "struct file".
2367 * @wait: Pointer to "poll_table".
2368 *
2369 * Waits for read readiness.
2370 * /proc/ccs/query is handled by /usr/sbin/ccs-queryd and
2371 * /proc/ccs/grant_log and /proc/ccs/reject_log are handled by
2372 * /usr/sbin/ccs-auditd .
2373 */
2374 int ccs_poll_control(struct file *file, poll_table *wait)
2375 {
2376 struct ccs_io_buffer *head = file->private_data;
2377 if (!head->poll)
2378 return -ENOSYS;
2379 return head->poll(file, wait);
2380 }
2381
2382 /**
2383 * ccs_read_control - read() for /proc/ccs/ interface.
2384 *
2385 * @file: Pointer to "struct file".
2386 * @buffer: Poiner to buffer to write to.
2387 * @buffer_len: Size of @buffer.
2388 *
2389 * Returns bytes read on success, negative value otherwise.
2390 */
2391 int ccs_read_control(struct file *file, char __user *buffer,
2392 const int buffer_len)
2393 {
2394 int len = 0;
2395 struct ccs_io_buffer *head = file->private_data;
2396 char *cp;
2397 int idx;
2398 if (!head->read)
2399 return -ENOSYS;
2400 if (!access_ok(VERIFY_WRITE, buffer, buffer_len))
2401 return -EFAULT;
2402 if (mutex_lock_interruptible(&head->io_sem))
2403 return -EINTR;
2404 idx = ccs_read_lock();
2405 while (1) {
2406 /* Call the policy handler. */
2407 head->read(head);
2408 /* Write to buffer. */
2409 len = head->read_avail;
2410 if (len || head->poll || head->read_eof)
2411 break;
2412 len = head->readbuf_size * 2;
2413 cp = kzalloc(len, CCS_GFP_FLAGS);
2414 if (!cp) {
2415 len = -ENOMEM;
2416 goto out;
2417 }
2418 kfree(head->read_buf);
2419 head->read_buf = cp;
2420 head->readbuf_size = len;
2421 }
2422 if (len > buffer_len)
2423 len = buffer_len;
2424 if (!len)
2425 goto out;
2426 /* head->read_buf changes by some functions. */
2427 cp = head->read_buf;
2428 if (copy_to_user(buffer, cp, len)) {
2429 len = -EFAULT;
2430 goto out;
2431 }
2432 head->read_avail -= len;
2433 memmove(cp, cp + len, head->read_avail);
2434 out:
2435 ccs_read_unlock(idx);
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 int idx;
2457 if (!head->write)
2458 return -ENOSYS;
2459 if (!access_ok(VERIFY_READ, buffer, buffer_len))
2460 return -EFAULT;
2461 if (mutex_lock_interruptible(&head->io_sem))
2462 return -EINTR;
2463 idx = ccs_read_lock();
2464 /* Don't allow updating policies by non manager programs. */
2465 if (head->write != ccs_write_pid && head->write != ccs_write_domain &&
2466 !ccs_manager()) {
2467 ccs_read_unlock(idx);
2468 mutex_unlock(&head->io_sem);
2469 return -EPERM;
2470 }
2471 /* Read a line and dispatch it to the policy handler. */
2472 while (avail_len > 0) {
2473 char c;
2474 if (head->write_avail >= head->writebuf_size - 1) {
2475 const int len = head->writebuf_size * 2;
2476 char *cp = kzalloc(len, CCS_GFP_FLAGS);
2477 if (!cp) {
2478 error = -ENOMEM;
2479 break;
2480 }
2481 memmove(cp, cp0, head->write_avail);
2482 kfree(cp0);
2483 head->write_buf = cp;
2484 cp0 = cp;
2485 head->writebuf_size = len;
2486 }
2487 if (get_user(c, buffer)) {
2488 error = -EFAULT;
2489 break;
2490 }
2491 buffer++;
2492 avail_len--;
2493 cp0[head->write_avail++] = c;
2494 if (c != '\n')
2495 continue;
2496 cp0[head->write_avail - 1] = '\0';
2497 head->write_avail = 0;
2498 ccs_normalize_line(cp0);
2499 head->write(head);
2500 }
2501 ccs_read_unlock(idx);
2502 mutex_unlock(&head->io_sem);
2503 return error;
2504 }
2505
2506 /**
2507 * ccs_close_control - close() for /proc/ccs/ interface.
2508 *
2509 * @file: Pointer to "struct file".
2510 *
2511 * Releases memory and returns 0.
2512 */
2513 int ccs_close_control(struct file *file)
2514 {
2515 struct ccs_io_buffer *head = file->private_data;
2516 const bool is_write = head->write_buf != NULL;
2517 const u8 type = head->type;
2518 /*
2519 * If the file is /proc/ccs/query , decrement the observer counter.
2520 */
2521 if (type == CCS_QUERY)
2522 atomic_dec(&ccs_query_observers);
2523 if (type != CCS_QUERY &&
2524 type != CCS_GRANTLOG && type != CCS_REJECTLOG)
2525 ccs_unlock(head->reader_idx);
2526 /* Release memory used for policy I/O. */
2527 kfree(head->read_buf);
2528 head->read_buf = NULL;
2529 kfree(head->write_buf);
2530 head->write_buf = NULL;
2531 kfree(head);
2532 head = NULL;
2533 file->private_data = NULL;
2534 if (is_write)
2535 ccs_run_gc();
2536 return 0;
2537 }
2538
2539 void __init ccs_policy_io_init(void)
2540 {
2541 ccsecurity_ops.check_profile = ccs_check_profile;
2542 }

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