aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2011-07-08 00:21:37 -0400
committerJames Morris <jmorris@namei.org>2011-07-10 21:05:32 -0400
commit2066a36125fcbf5220990173b9d8e8bc49ad7538 (patch)
treec8ea3a6d92a8b4b68cda986601336e8e8f58553e /security/tomoyo
parent5c4274f13819b40e726f6ee4ef13b4952cff5010 (diff)
TOMOYO: Allow using UID/GID etc. of current thread as conditions.
This patch adds support for permission checks using current thread's UID/GID etc. in addition to pathnames. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/tomoyo')
-rw-r--r--security/tomoyo/Makefile2
-rw-r--r--security/tomoyo/audit.c32
-rw-r--r--security/tomoyo/common.c146
-rw-r--r--security/tomoyo/common.h97
-rw-r--r--security/tomoyo/condition.c349
-rw-r--r--security/tomoyo/domain.c21
-rw-r--r--security/tomoyo/gc.c39
-rw-r--r--security/tomoyo/util.c2
8 files changed, 651 insertions, 37 deletions
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile
index 04f676a940a..95278b71fc2 100644
--- a/security/tomoyo/Makefile
+++ b/security/tomoyo/Makefile
@@ -1,4 +1,4 @@
1obj-y = audit.o common.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o 1obj-y = audit.o common.o condition.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o
2 2
3$(obj)/policy/profile.conf: 3$(obj)/policy/profile.conf:
4 @mkdir -p $(obj)/policy/ 4 @mkdir -p $(obj)/policy/
diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c
index 967b5648dce..9381d0e7f78 100644
--- a/security/tomoyo/audit.c
+++ b/security/tomoyo/audit.c
@@ -25,7 +25,7 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r)
25 const pid_t gpid = task_pid_nr(current); 25 const pid_t gpid = task_pid_nr(current);
26 static const int tomoyo_buffer_len = 4096; 26 static const int tomoyo_buffer_len = 4096;
27 char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); 27 char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS);
28 pid_t ppid; 28 int pos;
29 if (!buffer) 29 if (!buffer)
30 return NULL; 30 return NULL;
31 { 31 {
@@ -33,21 +33,21 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r)
33 do_gettimeofday(&tv); 33 do_gettimeofday(&tv);
34 tomoyo_convert_time(tv.tv_sec, &stamp); 34 tomoyo_convert_time(tv.tv_sec, &stamp);
35 } 35 }
36 rcu_read_lock(); 36 pos = snprintf(buffer, tomoyo_buffer_len - 1,
37 ppid = task_tgid_vnr(current->real_parent); 37 "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s "
38 rcu_read_unlock(); 38 "granted=%s (global-pid=%u) task={ pid=%u ppid=%u "
39 snprintf(buffer, tomoyo_buffer_len - 1, 39 "uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u "
40 "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s " 40 "fsuid=%u fsgid=%u }", stamp.year, stamp.month,
41 "granted=%s (global-pid=%u) task={ pid=%u ppid=%u " 41 stamp.day, stamp.hour, stamp.min, stamp.sec, r->profile,
42 "uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u " 42 tomoyo_mode[r->mode], tomoyo_yesno(r->granted), gpid,
43 "fsuid=%u fsgid=%u }", 43 tomoyo_sys_getpid(), tomoyo_sys_getppid(),
44 stamp.year, stamp.month, stamp.day, stamp.hour, 44 current_uid(), current_gid(), current_euid(),
45 stamp.min, stamp.sec, r->profile, tomoyo_mode[r->mode], 45 current_egid(), current_suid(), current_sgid(),
46 tomoyo_yesno(r->granted), gpid, task_tgid_vnr(current), ppid, 46 current_fsuid(), current_fsgid());
47 current_uid(), current_gid(), current_euid(), current_egid(), 47 if (pos < tomoyo_buffer_len - 1)
48 current_suid(), current_sgid(), current_fsuid(), 48 return buffer;
49 current_fsgid()); 49 kfree(buffer);
50 return buffer; 50 return NULL;
51} 51}
52 52
53/** 53/**
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index b340137a921..32ce1705b85 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -48,6 +48,20 @@ const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX
48 [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file", 48 [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file",
49}; 49};
50 50
51/* String table for conditions. */
52const char * const tomoyo_condition_keyword[TOMOYO_MAX_CONDITION_KEYWORD] = {
53 [TOMOYO_TASK_UID] = "task.uid",
54 [TOMOYO_TASK_EUID] = "task.euid",
55 [TOMOYO_TASK_SUID] = "task.suid",
56 [TOMOYO_TASK_FSUID] = "task.fsuid",
57 [TOMOYO_TASK_GID] = "task.gid",
58 [TOMOYO_TASK_EGID] = "task.egid",
59 [TOMOYO_TASK_SGID] = "task.sgid",
60 [TOMOYO_TASK_FSGID] = "task.fsgid",
61 [TOMOYO_TASK_PID] = "task.pid",
62 [TOMOYO_TASK_PPID] = "task.ppid",
63};
64
51/* String table for PREFERENCE keyword. */ 65/* String table for PREFERENCE keyword. */
52static const char * const tomoyo_pref_keywords[TOMOYO_MAX_PREF] = { 66static const char * const tomoyo_pref_keywords[TOMOYO_MAX_PREF] = {
53 [TOMOYO_PREF_MAX_AUDIT_LOG] = "max_audit_log", 67 [TOMOYO_PREF_MAX_AUDIT_LOG] = "max_audit_log",
@@ -294,15 +308,16 @@ static void tomoyo_print_name_union(struct tomoyo_io_buffer *head,
294} 308}
295 309
296/** 310/**
297 * tomoyo_print_number_union - Print a tomoyo_number_union. 311 * tomoyo_print_number_union_nospace - Print a tomoyo_number_union without a space.
298 * 312 *
299 * @head: Pointer to "struct tomoyo_io_buffer". 313 * @head: Pointer to "struct tomoyo_io_buffer".
300 * @ptr: Pointer to "struct tomoyo_number_union". 314 * @ptr: Pointer to "struct tomoyo_number_union".
315 *
316 * Returns nothing.
301 */ 317 */
302static void tomoyo_print_number_union(struct tomoyo_io_buffer *head, 318static void tomoyo_print_number_union_nospace
303 const struct tomoyo_number_union *ptr) 319(struct tomoyo_io_buffer *head, const struct tomoyo_number_union *ptr)
304{ 320{
305 tomoyo_set_space(head);
306 if (ptr->group) { 321 if (ptr->group) {
307 tomoyo_set_string(head, "@"); 322 tomoyo_set_string(head, "@");
308 tomoyo_set_string(head, ptr->group->group_name->name); 323 tomoyo_set_string(head, ptr->group->group_name->name);
@@ -325,8 +340,8 @@ static void tomoyo_print_number_union(struct tomoyo_io_buffer *head,
325 "0%lo", min); 340 "0%lo", min);
326 break; 341 break;
327 default: 342 default:
328 tomoyo_addprintf(buffer, sizeof(buffer), 343 tomoyo_addprintf(buffer, sizeof(buffer), "%lu",
329 "%lu", min); 344 min);
330 break; 345 break;
331 } 346 }
332 if (min == max && min_type == max_type) 347 if (min == max && min_type == max_type)
@@ -340,6 +355,21 @@ static void tomoyo_print_number_union(struct tomoyo_io_buffer *head,
340} 355}
341 356
342/** 357/**
358 * tomoyo_print_number_union - Print a tomoyo_number_union.
359 *
360 * @head: Pointer to "struct tomoyo_io_buffer".
361 * @ptr: Pointer to "struct tomoyo_number_union".
362 *
363 * Returns nothing.
364 */
365static void tomoyo_print_number_union(struct tomoyo_io_buffer *head,
366 const struct tomoyo_number_union *ptr)
367{
368 tomoyo_set_space(head);
369 tomoyo_print_number_union_nospace(head, ptr);
370}
371
372/**
343 * tomoyo_assign_profile - Create a new profile. 373 * tomoyo_assign_profile - Create a new profile.
344 * 374 *
345 * @ns: Pointer to "struct tomoyo_policy_namespace". 375 * @ns: Pointer to "struct tomoyo_policy_namespace".
@@ -1004,6 +1034,91 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head)
1004} 1034}
1005 1035
1006/** 1036/**
1037 * tomoyo_print_condition - Print condition part.
1038 *
1039 * @head: Pointer to "struct tomoyo_io_buffer".
1040 * @cond: Pointer to "struct tomoyo_condition".
1041 *
1042 * Returns true on success, false otherwise.
1043 */
1044static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
1045 const struct tomoyo_condition *cond)
1046{
1047 switch (head->r.cond_step) {
1048 case 0:
1049 head->r.cond_index = 0;
1050 head->r.cond_step++;
1051 /* fall through */
1052 case 1:
1053 {
1054 const u16 condc = cond->condc;
1055 const struct tomoyo_condition_element *condp =
1056 (typeof(condp)) (cond + 1);
1057 const struct tomoyo_number_union *numbers_p =
1058 (typeof(numbers_p)) (condp + condc);
1059 u16 skip;
1060 for (skip = 0; skip < head->r.cond_index; skip++) {
1061 const u8 left = condp->left;
1062 const u8 right = condp->right;
1063 condp++;
1064 switch (left) {
1065 case TOMOYO_NUMBER_UNION:
1066 numbers_p++;
1067 break;
1068 }
1069 switch (right) {
1070 case TOMOYO_NUMBER_UNION:
1071 numbers_p++;
1072 break;
1073 }
1074 }
1075 while (head->r.cond_index < condc) {
1076 const u8 match = condp->equals;
1077 const u8 left = condp->left;
1078 const u8 right = condp->right;
1079 if (!tomoyo_flush(head))
1080 return false;
1081 condp++;
1082 head->r.cond_index++;
1083 tomoyo_set_space(head);
1084 switch (left) {
1085 case TOMOYO_NUMBER_UNION:
1086 tomoyo_print_number_union_nospace
1087 (head, numbers_p++);
1088 break;
1089 default:
1090 tomoyo_set_string(head,
1091 tomoyo_condition_keyword[left]);
1092 break;
1093 }
1094 tomoyo_set_string(head, match ? "=" : "!=");
1095 switch (right) {
1096 case TOMOYO_NUMBER_UNION:
1097 tomoyo_print_number_union_nospace
1098 (head, numbers_p++);
1099 break;
1100 default:
1101 tomoyo_set_string(head,
1102 tomoyo_condition_keyword[right]);
1103 break;
1104 }
1105 }
1106 }
1107 head->r.cond_step++;
1108 /* fall through */
1109 case 2:
1110 if (!tomoyo_flush(head))
1111 break;
1112 head->r.cond_step++;
1113 /* fall through */
1114 case 3:
1115 tomoyo_set_lf(head);
1116 return true;
1117 }
1118 return false;
1119}
1120
1121/**
1007 * tomoyo_set_group - Print "acl_group " header keyword and category name. 1122 * tomoyo_set_group - Print "acl_group " header keyword and category name.
1008 * 1123 *
1009 * @head: Pointer to "struct tomoyo_io_buffer". 1124 * @head: Pointer to "struct tomoyo_io_buffer".
@@ -1037,6 +1152,8 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
1037 bool first = true; 1152 bool first = true;
1038 u8 bit; 1153 u8 bit;
1039 1154
1155 if (head->r.print_cond_part)
1156 goto print_cond_part;
1040 if (acl->is_deleted) 1157 if (acl->is_deleted)
1041 return true; 1158 return true;
1042 if (!tomoyo_flush(head)) 1159 if (!tomoyo_flush(head))
@@ -1135,7 +1252,18 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
1135 tomoyo_print_name_union(head, &ptr->fs_type); 1252 tomoyo_print_name_union(head, &ptr->fs_type);
1136 tomoyo_print_number_union(head, &ptr->flags); 1253 tomoyo_print_number_union(head, &ptr->flags);
1137 } 1254 }
1138 tomoyo_set_lf(head); 1255 if (acl->cond) {
1256 head->r.print_cond_part = true;
1257 head->r.cond_step = 0;
1258 if (!tomoyo_flush(head))
1259 return false;
1260print_cond_part:
1261 if (!tomoyo_print_condition(head, acl->cond))
1262 return false;
1263 head->r.print_cond_part = false;
1264 } else {
1265 tomoyo_set_lf(head);
1266 }
1139 return true; 1267 return true;
1140} 1268}
1141 1269
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index beb7d0eb522..958d433b011 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -21,7 +21,8 @@
21#include <linux/list.h> 21#include <linux/list.h>
22#include <linux/cred.h> 22#include <linux/cred.h>
23#include <linux/poll.h> 23#include <linux/poll.h>
24struct linux_binprm; 24#include <linux/binfmts.h>
25#include <linux/highmem.h>
25 26
26/********** Constants definitions. **********/ 27/********** Constants definitions. **********/
27 28
@@ -41,6 +42,22 @@ struct linux_binprm;
41/* Group number is an integer between 0 and 255. */ 42/* Group number is an integer between 0 and 255. */
42#define TOMOYO_MAX_ACL_GROUPS 256 43#define TOMOYO_MAX_ACL_GROUPS 256
43 44
45/* Index numbers for "struct tomoyo_condition". */
46enum tomoyo_conditions_index {
47 TOMOYO_TASK_UID, /* current_uid() */
48 TOMOYO_TASK_EUID, /* current_euid() */
49 TOMOYO_TASK_SUID, /* current_suid() */
50 TOMOYO_TASK_FSUID, /* current_fsuid() */
51 TOMOYO_TASK_GID, /* current_gid() */
52 TOMOYO_TASK_EGID, /* current_egid() */
53 TOMOYO_TASK_SGID, /* current_sgid() */
54 TOMOYO_TASK_FSGID, /* current_fsgid() */
55 TOMOYO_TASK_PID, /* sys_getpid() */
56 TOMOYO_TASK_PPID, /* sys_getppid() */
57 TOMOYO_MAX_CONDITION_KEYWORD,
58 TOMOYO_NUMBER_UNION,
59};
60
44/* Index numbers for operation mode. */ 61/* Index numbers for operation mode. */
45enum tomoyo_mode_index { 62enum tomoyo_mode_index {
46 TOMOYO_CONFIG_DISABLED, 63 TOMOYO_CONFIG_DISABLED,
@@ -61,6 +78,7 @@ enum tomoyo_policy_id {
61 TOMOYO_ID_TRANSITION_CONTROL, 78 TOMOYO_ID_TRANSITION_CONTROL,
62 TOMOYO_ID_AGGREGATOR, 79 TOMOYO_ID_AGGREGATOR,
63 TOMOYO_ID_MANAGER, 80 TOMOYO_ID_MANAGER,
81 TOMOYO_ID_CONDITION,
64 TOMOYO_ID_NAME, 82 TOMOYO_ID_NAME,
65 TOMOYO_ID_ACL, 83 TOMOYO_ID_ACL,
66 TOMOYO_ID_DOMAIN, 84 TOMOYO_ID_DOMAIN,
@@ -370,9 +388,32 @@ struct tomoyo_number_group {
370 struct tomoyo_number_union number; 388 struct tomoyo_number_union number;
371}; 389};
372 390
391/* Structure for entries which follows "struct tomoyo_condition". */
392struct tomoyo_condition_element {
393 /* Left hand operand. */
394 u8 left;
395 /* Right hand operand. */
396 u8 right;
397 /* Equation operator. True if equals or overlaps, false otherwise. */
398 bool equals;
399};
400
401/* Structure for optional arguments. */
402struct tomoyo_condition {
403 struct tomoyo_shared_acl_head head;
404 u32 size; /* Memory size allocated for this entry. */
405 u16 condc; /* Number of conditions in this struct. */
406 u16 numbers_count; /* Number of "struct tomoyo_number_union values". */
407 /*
408 * struct tomoyo_condition_element condition[condc];
409 * struct tomoyo_number_union values[numbers_count];
410 */
411};
412
373/* Common header for individual entries. */ 413/* Common header for individual entries. */
374struct tomoyo_acl_info { 414struct tomoyo_acl_info {
375 struct list_head list; 415 struct list_head list;
416 struct tomoyo_condition *cond; /* Maybe NULL. */
376 bool is_deleted; 417 bool is_deleted;
377 u8 type; /* One of values in "enum tomoyo_acl_entry_type_index". */ 418 u8 type; /* One of values in "enum tomoyo_acl_entry_type_index". */
378} __packed; 419} __packed;
@@ -475,12 +516,15 @@ struct tomoyo_io_buffer {
475 unsigned int step; 516 unsigned int step;
476 unsigned int query_index; 517 unsigned int query_index;
477 u16 index; 518 u16 index;
519 u16 cond_index;
478 u8 acl_group_index; 520 u8 acl_group_index;
521 u8 cond_step;
479 u8 bit; 522 u8 bit;
480 u8 w_pos; 523 u8 w_pos;
481 bool eof; 524 bool eof;
482 bool print_this_domain_only; 525 bool print_this_domain_only;
483 bool print_transition_related_only; 526 bool print_transition_related_only;
527 bool print_cond_part;
484 const char *w[TOMOYO_MAX_IO_READ_QUEUE]; 528 const char *w[TOMOYO_MAX_IO_READ_QUEUE];
485 } r; 529 } r;
486 struct { 530 struct {
@@ -586,6 +630,8 @@ struct tomoyo_policy_namespace {
586 630
587bool tomoyo_compare_number_union(const unsigned long value, 631bool tomoyo_compare_number_union(const unsigned long value,
588 const struct tomoyo_number_union *ptr); 632 const struct tomoyo_number_union *ptr);
633bool tomoyo_condition(struct tomoyo_request_info *r,
634 const struct tomoyo_condition *cond);
589bool tomoyo_correct_domain(const unsigned char *domainname); 635bool tomoyo_correct_domain(const unsigned char *domainname);
590bool tomoyo_correct_path(const char *filename); 636bool tomoyo_correct_path(const char *filename);
591bool tomoyo_correct_word(const char *string); 637bool tomoyo_correct_word(const char *string);
@@ -664,6 +710,7 @@ ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer,
664 const int buffer_len); 710 const int buffer_len);
665ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, 711ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head,
666 const char __user *buffer, const int buffer_len); 712 const char __user *buffer, const int buffer_len);
713struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param);
667struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, 714struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
668 const bool transit); 715 const bool transit);
669struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); 716struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
@@ -675,6 +722,7 @@ struct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns,
675 const u8 profile); 722 const u8 profile);
676unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, 723unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
677 const u8 index); 724 const u8 index);
725u8 tomoyo_parse_ulong(unsigned long *result, char **str);
678void *tomoyo_commit_ok(void *data, const unsigned int size); 726void *tomoyo_commit_ok(void *data, const unsigned int size);
679void __init tomoyo_load_builtin_policy(void); 727void __init tomoyo_load_builtin_policy(void);
680void __init tomoyo_mm_init(void); 728void __init tomoyo_mm_init(void);
@@ -683,6 +731,7 @@ void tomoyo_check_acl(struct tomoyo_request_info *r,
683 const struct tomoyo_acl_info *)); 731 const struct tomoyo_acl_info *));
684void tomoyo_check_profile(void); 732void tomoyo_check_profile(void);
685void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp); 733void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp);
734void tomoyo_del_condition(struct list_head *element);
686void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); 735void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
687void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns); 736void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns);
688void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) 737void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
@@ -706,6 +755,8 @@ void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt,
706/********** External variable definitions. **********/ 755/********** External variable definitions. **********/
707 756
708extern bool tomoyo_policy_loaded; 757extern bool tomoyo_policy_loaded;
758extern const char * const tomoyo_condition_keyword
759[TOMOYO_MAX_CONDITION_KEYWORD];
709extern const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; 760extern const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS];
710extern const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX 761extern const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX
711 + TOMOYO_MAX_MAC_CATEGORY_INDEX]; 762 + TOMOYO_MAX_MAC_CATEGORY_INDEX];
@@ -715,6 +766,7 @@ extern const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX];
715extern const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION]; 766extern const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION];
716extern const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION]; 767extern const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION];
717extern const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION]; 768extern const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION];
769extern struct list_head tomoyo_condition_list;
718extern struct list_head tomoyo_domain_list; 770extern struct list_head tomoyo_domain_list;
719extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; 771extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
720extern struct list_head tomoyo_namespace_list; 772extern struct list_head tomoyo_namespace_list;
@@ -750,6 +802,36 @@ static inline void tomoyo_read_unlock(int idx)
750} 802}
751 803
752/** 804/**
805 * tomoyo_sys_getppid - Copy of getppid().
806 *
807 * Returns parent process's PID.
808 *
809 * Alpha does not have getppid() defined. To be able to build this module on
810 * Alpha, I have to copy getppid() from kernel/timer.c.
811 */
812static inline pid_t tomoyo_sys_getppid(void)
813{
814 pid_t pid;
815 rcu_read_lock();
816 pid = task_tgid_vnr(current->real_parent);
817 rcu_read_unlock();
818 return pid;
819}
820
821/**
822 * tomoyo_sys_getpid - Copy of getpid().
823 *
824 * Returns current thread's PID.
825 *
826 * Alpha does not have getpid() defined. To be able to build this module on
827 * Alpha, I have to copy getpid() from kernel/timer.c.
828 */
829static inline pid_t tomoyo_sys_getpid(void)
830{
831 return task_tgid_vnr(current);
832}
833
834/**
753 * tomoyo_pathcmp - strcmp() for "struct tomoyo_path_info" structure. 835 * tomoyo_pathcmp - strcmp() for "struct tomoyo_path_info" structure.
754 * 836 *
755 * @a: Pointer to "struct tomoyo_path_info". 837 * @a: Pointer to "struct tomoyo_path_info".
@@ -780,6 +862,19 @@ static inline void tomoyo_put_name(const struct tomoyo_path_info *name)
780} 862}
781 863
782/** 864/**
865 * tomoyo_put_condition - Drop reference on "struct tomoyo_condition".
866 *
867 * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
868 *
869 * Returns nothing.
870 */
871static inline void tomoyo_put_condition(struct tomoyo_condition *cond)
872{
873 if (cond)
874 atomic_dec(&cond->head.users);
875}
876
877/**
783 * tomoyo_put_group - Drop reference on "struct tomoyo_group". 878 * tomoyo_put_group - Drop reference on "struct tomoyo_group".
784 * 879 *
785 * @group: Pointer to "struct tomoyo_group". Maybe NULL. 880 * @group: Pointer to "struct tomoyo_group". Maybe NULL.
diff --git a/security/tomoyo/condition.c b/security/tomoyo/condition.c
new file mode 100644
index 00000000000..0692df3cddc
--- /dev/null
+++ b/security/tomoyo/condition.c
@@ -0,0 +1,349 @@
1/*
2 * security/tomoyo/condition.c
3 *
4 * Copyright (C) 2005-2011 NTT DATA CORPORATION
5 */
6
7#include "common.h"
8#include <linux/slab.h>
9
10/* List of "struct tomoyo_condition". */
11LIST_HEAD(tomoyo_condition_list);
12
13/**
14 * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry.
15 *
16 * @a: Pointer to "struct tomoyo_condition".
17 * @b: Pointer to "struct tomoyo_condition".
18 *
19 * Returns true if @a == @b, false otherwise.
20 */
21static inline bool tomoyo_same_condition(const struct tomoyo_condition *a,
22 const struct tomoyo_condition *b)
23{
24 return a->size == b->size && a->condc == b->condc &&
25 a->numbers_count == b->numbers_count &&
26 !memcmp(a + 1, b + 1, a->size - sizeof(*a));
27}
28
29/**
30 * tomoyo_condition_type - Get condition type.
31 *
32 * @word: Keyword string.
33 *
34 * Returns one of values in "enum tomoyo_conditions_index" on success,
35 * TOMOYO_MAX_CONDITION_KEYWORD otherwise.
36 */
37static u8 tomoyo_condition_type(const char *word)
38{
39 u8 i;
40 for (i = 0; i < TOMOYO_MAX_CONDITION_KEYWORD; i++) {
41 if (!strcmp(word, tomoyo_condition_keyword[i]))
42 break;
43 }
44 return i;
45}
46
47/* Define this to enable debug mode. */
48/* #define DEBUG_CONDITION */
49
50#ifdef DEBUG_CONDITION
51#define dprintk printk
52#else
53#define dprintk(...) do { } while (0)
54#endif
55
56/**
57 * tomoyo_commit_condition - Commit "struct tomoyo_condition".
58 *
59 * @entry: Pointer to "struct tomoyo_condition".
60 *
61 * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
62 *
63 * This function merges duplicated entries. This function returns NULL if
64 * @entry is not duplicated but memory quota for policy has exceeded.
65 */
66static struct tomoyo_condition *tomoyo_commit_condition
67(struct tomoyo_condition *entry)
68{
69 struct tomoyo_condition *ptr;
70 bool found = false;
71 if (mutex_lock_interruptible(&tomoyo_policy_lock)) {
72 dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
73 ptr = NULL;
74 found = true;
75 goto out;
76 }
77 list_for_each_entry_rcu(ptr, &tomoyo_condition_list, head.list) {
78 if (!tomoyo_same_condition(ptr, entry))
79 continue;
80 /* Same entry found. Share this entry. */
81 atomic_inc(&ptr->head.users);
82 found = true;
83 break;
84 }
85 if (!found) {
86 if (tomoyo_memory_ok(entry)) {
87 atomic_set(&entry->head.users, 1);
88 list_add_rcu(&entry->head.list,
89 &tomoyo_condition_list);
90 } else {
91 found = true;
92 ptr = NULL;
93 }
94 }
95 mutex_unlock(&tomoyo_policy_lock);
96out:
97 if (found) {
98 tomoyo_del_condition(&entry->head.list);
99 kfree(entry);
100 entry = ptr;
101 }
102 return entry;
103}
104
105/**
106 * tomoyo_get_condition - Parse condition part.
107 *
108 * @param: Pointer to "struct tomoyo_acl_param".
109 *
110 * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
111 */
112struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param)
113{
114 struct tomoyo_condition *entry = NULL;
115 struct tomoyo_condition_element *condp = NULL;
116 struct tomoyo_number_union *numbers_p = NULL;
117 struct tomoyo_condition e = { };
118 char * const start_of_string = param->data;
119 char * const end_of_string = start_of_string + strlen(start_of_string);
120 char *pos;
121rerun:
122 pos = start_of_string;
123 while (1) {
124 u8 left = -1;
125 u8 right = -1;
126 char *left_word = pos;
127 char *cp;
128 char *right_word;
129 bool is_not;
130 if (!*left_word)
131 break;
132 /*
133 * Since left-hand condition does not allow use of "path_group"
134 * or "number_group" and environment variable's names do not
135 * accept '=', it is guaranteed that the original line consists
136 * of one or more repetition of $left$operator$right blocks
137 * where "$left is free from '=' and ' '" and "$operator is
138 * either '=' or '!='" and "$right is free from ' '".
139 * Therefore, we can reconstruct the original line at the end
140 * of dry run even if we overwrite $operator with '\0'.
141 */
142 cp = strchr(pos, ' ');
143 if (cp) {
144 *cp = '\0'; /* Will restore later. */
145 pos = cp + 1;
146 } else {
147 pos = "";
148 }
149 right_word = strchr(left_word, '=');
150 if (!right_word || right_word == left_word)
151 goto out;
152 is_not = *(right_word - 1) == '!';
153 if (is_not)
154 *(right_word++ - 1) = '\0'; /* Will restore later. */
155 else if (*(right_word + 1) != '=')
156 *right_word++ = '\0'; /* Will restore later. */
157 else
158 goto out;
159 dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word,
160 is_not ? "!" : "", right_word);
161 left = tomoyo_condition_type(left_word);
162 dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word,
163 left);
164 if (left == TOMOYO_MAX_CONDITION_KEYWORD) {
165 if (!numbers_p) {
166 e.numbers_count++;
167 } else {
168 e.numbers_count--;
169 left = TOMOYO_NUMBER_UNION;
170 param->data = left_word;
171 if (*left_word == '@' ||
172 !tomoyo_parse_number_union(param,
173 numbers_p++))
174 goto out;
175 }
176 }
177 if (!condp)
178 e.condc++;
179 else
180 e.condc--;
181 right = tomoyo_condition_type(right_word);
182 if (right == TOMOYO_MAX_CONDITION_KEYWORD) {
183 if (!numbers_p) {
184 e.numbers_count++;
185 } else {
186 e.numbers_count--;
187 right = TOMOYO_NUMBER_UNION;
188 param->data = right_word;
189 if (!tomoyo_parse_number_union(param,
190 numbers_p++))
191 goto out;
192 }
193 }
194 if (!condp) {
195 dprintk(KERN_WARNING "%u: dry_run left=%u right=%u "
196 "match=%u\n", __LINE__, left, right, !is_not);
197 continue;
198 }
199 condp->left = left;
200 condp->right = right;
201 condp->equals = !is_not;
202 dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
203 __LINE__, condp->left, condp->right,
204 condp->equals);
205 condp++;
206 }
207 dprintk(KERN_INFO "%u: cond=%u numbers=%u\n",
208 __LINE__, e.condc, e.numbers_count);
209 if (entry) {
210 BUG_ON(e.numbers_count | e.condc);
211 return tomoyo_commit_condition(entry);
212 }
213 e.size = sizeof(*entry)
214 + e.condc * sizeof(struct tomoyo_condition_element)
215 + e.numbers_count * sizeof(struct tomoyo_number_union);
216 entry = kzalloc(e.size, GFP_NOFS);
217 if (!entry)
218 return NULL;
219 *entry = e;
220 condp = (struct tomoyo_condition_element *) (entry + 1);
221 numbers_p = (struct tomoyo_number_union *) (condp + e.condc);
222 {
223 bool flag = false;
224 for (pos = start_of_string; pos < end_of_string; pos++) {
225 if (*pos)
226 continue;
227 if (flag) /* Restore " ". */
228 *pos = ' ';
229 else if (*(pos + 1) == '=') /* Restore "!=". */
230 *pos = '!';
231 else /* Restore "=". */
232 *pos = '=';
233 flag = !flag;
234 }
235 }
236 goto rerun;
237out:
238 dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
239 if (entry) {
240 tomoyo_del_condition(&entry->head.list);
241 kfree(entry);
242 }
243 return NULL;
244}
245
246/**
247 * tomoyo_condition - Check condition part.
248 *
249 * @r: Pointer to "struct tomoyo_request_info".
250 * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
251 *
252 * Returns true on success, false otherwise.
253 *
254 * Caller holds tomoyo_read_lock().
255 */
256bool tomoyo_condition(struct tomoyo_request_info *r,
257 const struct tomoyo_condition *cond)
258{
259 u32 i;
260 unsigned long min_v[2] = { 0, 0 };
261 unsigned long max_v[2] = { 0, 0 };
262 const struct tomoyo_condition_element *condp;
263 const struct tomoyo_number_union *numbers_p;
264 u16 condc;
265 if (!cond)
266 return true;
267 condc = cond->condc;
268 condp = (struct tomoyo_condition_element *) (cond + 1);
269 numbers_p = (const struct tomoyo_number_union *) (condp + condc);
270 for (i = 0; i < condc; i++) {
271 const bool match = condp->equals;
272 const u8 left = condp->left;
273 const u8 right = condp->right;
274 u8 j;
275 condp++;
276 /* Check numeric or bit-op expressions. */
277 for (j = 0; j < 2; j++) {
278 const u8 index = j ? right : left;
279 unsigned long value = 0;
280 switch (index) {
281 case TOMOYO_TASK_UID:
282 value = current_uid();
283 break;
284 case TOMOYO_TASK_EUID:
285 value = current_euid();
286 break;
287 case TOMOYO_TASK_SUID:
288 value = current_suid();
289 break;
290 case TOMOYO_TASK_FSUID:
291 value = current_fsuid();
292 break;
293 case TOMOYO_TASK_GID:
294 value = current_gid();
295 break;
296 case TOMOYO_TASK_EGID:
297 value = current_egid();
298 break;
299 case TOMOYO_TASK_SGID:
300 value = current_sgid();
301 break;
302 case TOMOYO_TASK_FSGID:
303 value = current_fsgid();
304 break;
305 case TOMOYO_TASK_PID:
306 value = tomoyo_sys_getpid();
307 break;
308 case TOMOYO_TASK_PPID:
309 value = tomoyo_sys_getppid();
310 break;
311 case TOMOYO_NUMBER_UNION:
312 /* Fetch values later. */
313 break;
314 default:
315 break;
316 }
317 max_v[j] = value;
318 min_v[j] = value;
319 }
320 if (left == TOMOYO_NUMBER_UNION) {
321 /* Fetch values now. */
322 const struct tomoyo_number_union *ptr = numbers_p++;
323 min_v[0] = ptr->values[0];
324 max_v[0] = ptr->values[1];
325 }
326 if (right == TOMOYO_NUMBER_UNION) {
327 /* Fetch values now. */
328 const struct tomoyo_number_union *ptr = numbers_p++;
329 if (ptr->group) {
330 if (tomoyo_number_matches_group(min_v[0],
331 max_v[0],
332 ptr->group)
333 == match)
334 continue;
335 } else {
336 if ((min_v[0] <= ptr->values[1] &&
337 max_v[0] >= ptr->values[0]) == match)
338 continue;
339 }
340 goto out;
341 }
342 /* Normal value range comparison. */
343 if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match)
344 continue;
345out:
346 return false;
347 }
348 return true;
349}
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index 7893127d877..0f02c785209 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -69,7 +69,7 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
69static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a, 69static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a,
70 const struct tomoyo_acl_info *b) 70 const struct tomoyo_acl_info *b)
71{ 71{
72 return a->type == b->type; 72 return a->type == b->type && a->cond == b->cond;
73} 73}
74 74
75/** 75/**
@@ -100,8 +100,13 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
100 struct tomoyo_acl_info *entry; 100 struct tomoyo_acl_info *entry;
101 struct list_head * const list = param->list; 101 struct list_head * const list = param->list;
102 102
103 if (param->data[0]) {
104 new_entry->cond = tomoyo_get_condition(param);
105 if (!new_entry->cond)
106 return -EINVAL;
107 }
103 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 108 if (mutex_lock_interruptible(&tomoyo_policy_lock))
104 return error; 109 goto out;
105 list_for_each_entry_rcu(entry, list, list) { 110 list_for_each_entry_rcu(entry, list, list) {
106 if (!tomoyo_same_acl_head(entry, new_entry) || 111 if (!tomoyo_same_acl_head(entry, new_entry) ||
107 !check_duplicate(entry, new_entry)) 112 !check_duplicate(entry, new_entry))
@@ -122,6 +127,8 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
122 } 127 }
123 } 128 }
124 mutex_unlock(&tomoyo_policy_lock); 129 mutex_unlock(&tomoyo_policy_lock);
130out:
131 tomoyo_put_condition(new_entry->cond);
125 return error; 132 return error;
126} 133}
127 134
@@ -148,10 +155,12 @@ retry:
148 list_for_each_entry_rcu(ptr, list, list) { 155 list_for_each_entry_rcu(ptr, list, list) {
149 if (ptr->is_deleted || ptr->type != r->param_type) 156 if (ptr->is_deleted || ptr->type != r->param_type)
150 continue; 157 continue;
151 if (check_entry(r, ptr)) { 158 if (!check_entry(r, ptr))
152 r->granted = true; 159 continue;
153 return; 160 if (!tomoyo_condition(r, ptr->cond))
154 } 161 continue;
162 r->granted = true;
163 return;
155 } 164 }
156 if (!retried) { 165 if (!retried) {
157 retried = true; 166 retried = true;
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c
index 1e1a6c8c832..21fccd67c25 100644
--- a/security/tomoyo/gc.c
+++ b/security/tomoyo/gc.c
@@ -25,6 +25,7 @@ static const u8 tomoyo_element_size[TOMOYO_MAX_POLICY] = {
25 [TOMOYO_ID_TRANSITION_CONTROL] = 25 [TOMOYO_ID_TRANSITION_CONTROL] =
26 sizeof(struct tomoyo_transition_control), 26 sizeof(struct tomoyo_transition_control),
27 [TOMOYO_ID_MANAGER] = sizeof(struct tomoyo_manager), 27 [TOMOYO_ID_MANAGER] = sizeof(struct tomoyo_manager),
28 /* [TOMOYO_ID_CONDITION] = "struct tomoyo_condition"->size, */
28 /* [TOMOYO_ID_NAME] = "struct tomoyo_name"->size, */ 29 /* [TOMOYO_ID_NAME] = "struct tomoyo_name"->size, */
29 /* [TOMOYO_ID_ACL] = 30 /* [TOMOYO_ID_ACL] =
30 tomoyo_acl_size["struct tomoyo_acl_info"->type], */ 31 tomoyo_acl_size["struct tomoyo_acl_info"->type], */
@@ -162,6 +163,10 @@ static bool tomoyo_add_to_gc(const int type, struct list_head *element)
162 entry->size = strlen(container_of(element, 163 entry->size = strlen(container_of(element,
163 typeof(struct tomoyo_name), 164 typeof(struct tomoyo_name),
164 head.list)->entry.name) + 1; 165 head.list)->entry.name) + 1;
166 else if (type == TOMOYO_ID_CONDITION)
167 entry->size =
168 container_of(element, typeof(struct tomoyo_condition),
169 head.list)->size;
165 else 170 else
166 entry->size = tomoyo_element_size[type]; 171 entry->size = tomoyo_element_size[type];
167 entry->element = element; 172 entry->element = element;
@@ -246,6 +251,7 @@ static void tomoyo_del_acl(struct list_head *element)
246{ 251{
247 struct tomoyo_acl_info *acl = 252 struct tomoyo_acl_info *acl =
248 container_of(element, typeof(*acl), list); 253 container_of(element, typeof(*acl), list);
254 tomoyo_put_condition(acl->cond);
249 switch (acl->type) { 255 switch (acl->type) {
250 case TOMOYO_TYPE_PATH_ACL: 256 case TOMOYO_TYPE_PATH_ACL:
251 { 257 {
@@ -338,6 +344,27 @@ static bool tomoyo_del_domain(struct list_head *element)
338 return true; 344 return true;
339} 345}
340 346
347/**
348 * tomoyo_del_condition - Delete members in "struct tomoyo_condition".
349 *
350 * @element: Pointer to "struct list_head".
351 *
352 * Returns nothing.
353 */
354void tomoyo_del_condition(struct list_head *element)
355{
356 struct tomoyo_condition *cond = container_of(element, typeof(*cond),
357 head.list);
358 const u16 condc = cond->condc;
359 const u16 numbers_count = cond->numbers_count;
360 unsigned int i;
361 const struct tomoyo_condition_element *condp
362 = (const struct tomoyo_condition_element *) (cond + 1);
363 struct tomoyo_number_union *numbers_p
364 = (struct tomoyo_number_union *) (condp + condc);
365 for (i = 0; i < numbers_count; i++)
366 tomoyo_put_number_union(numbers_p++);
367}
341 368
342/** 369/**
343 * tomoyo_del_name - Delete members in "struct tomoyo_name". 370 * tomoyo_del_name - Delete members in "struct tomoyo_name".
@@ -494,15 +521,18 @@ static void tomoyo_collect_entry(void)
494 } 521 }
495 } 522 }
496 } 523 }
497 for (i = 0; i < TOMOYO_MAX_HASH; i++) { 524 id = TOMOYO_ID_CONDITION;
498 struct list_head *list = &tomoyo_name_list[i]; 525 for (i = 0; i < TOMOYO_MAX_HASH + 1; i++) {
526 struct list_head *list = !i ?
527 &tomoyo_condition_list : &tomoyo_name_list[i - 1];
499 struct tomoyo_shared_acl_head *ptr; 528 struct tomoyo_shared_acl_head *ptr;
500 list_for_each_entry(ptr, list, list) { 529 list_for_each_entry(ptr, list, list) {
501 if (atomic_read(&ptr->users)) 530 if (atomic_read(&ptr->users))
502 continue; 531 continue;
503 if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->list)) 532 if (!tomoyo_add_to_gc(id, &ptr->list))
504 goto unlock; 533 goto unlock;
505 } 534 }
535 id = TOMOYO_ID_NAME;
506 } 536 }
507unlock: 537unlock:
508 tomoyo_read_unlock(idx); 538 tomoyo_read_unlock(idx);
@@ -557,6 +587,9 @@ static bool tomoyo_kfree_entry(void)
557 case TOMOYO_ID_MANAGER: 587 case TOMOYO_ID_MANAGER:
558 tomoyo_del_manager(element); 588 tomoyo_del_manager(element);
559 break; 589 break;
590 case TOMOYO_ID_CONDITION:
591 tomoyo_del_condition(element);
592 break;
560 case TOMOYO_ID_NAME: 593 case TOMOYO_ID_NAME:
561 /* 594 /*
562 * Thirdly, defer until all "struct tomoyo_io_buffer" 595 * Thirdly, defer until all "struct tomoyo_io_buffer"
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
index 7ff54c95e1f..e25f7ffd5ba 100644
--- a/security/tomoyo/util.c
+++ b/security/tomoyo/util.c
@@ -138,7 +138,7 @@ char *tomoyo_read_token(struct tomoyo_acl_param *param)
138 * The @src is updated to point the first character after the value 138 * The @src is updated to point the first character after the value
139 * on success. 139 * on success.
140 */ 140 */
141static u8 tomoyo_parse_ulong(unsigned long *result, char **str) 141u8 tomoyo_parse_ulong(unsigned long *result, char **str)
142{ 142{
143 const char *cp = *str; 143 const char *cp = *str;
144 char *ep; 144 char *ep;