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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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