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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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