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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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