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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3109 - (show annotations) (download) (as text)
Fri Oct 16 05:02:23 2009 UTC (14 years, 7 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: 75878 byte(s)


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

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