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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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