2 * security/tomoyo/condition.c
4 * Copyright (C) 2005-2011 NTT DATA CORPORATION
8 #include <linux/slab.h>
10 /* List of "struct tomoyo_condition". */
11 LIST_HEAD(tomoyo_condition_list
);
14 * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry.
16 * @a: Pointer to "struct tomoyo_condition".
17 * @b: Pointer to "struct tomoyo_condition".
19 * Returns true if @a == @b, false otherwise.
21 static inline bool tomoyo_same_condition(const struct tomoyo_condition
*a
,
22 const struct tomoyo_condition
*b
)
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
));
30 * tomoyo_condition_type - Get condition type.
32 * @word: Keyword string.
34 * Returns one of values in "enum tomoyo_conditions_index" on success,
35 * TOMOYO_MAX_CONDITION_KEYWORD otherwise.
37 static u8
tomoyo_condition_type(const char *word
)
40 for (i
= 0; i
< TOMOYO_MAX_CONDITION_KEYWORD
; i
++) {
41 if (!strcmp(word
, tomoyo_condition_keyword
[i
]))
47 /* Define this to enable debug mode. */
48 /* #define DEBUG_CONDITION */
50 #ifdef DEBUG_CONDITION
51 #define dprintk printk
53 #define dprintk(...) do { } while (0)
57 * tomoyo_commit_condition - Commit "struct tomoyo_condition".
59 * @entry: Pointer to "struct tomoyo_condition".
61 * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
63 * This function merges duplicated entries. This function returns NULL if
64 * @entry is not duplicated but memory quota for policy has exceeded.
66 static struct tomoyo_condition
*tomoyo_commit_condition
67 (struct tomoyo_condition
*entry
)
69 struct tomoyo_condition
*ptr
;
71 if (mutex_lock_interruptible(&tomoyo_policy_lock
)) {
72 dprintk(KERN_WARNING
"%u: %s failed\n", __LINE__
, __func__
);
77 list_for_each_entry_rcu(ptr
, &tomoyo_condition_list
, head
.list
) {
78 if (!tomoyo_same_condition(ptr
, entry
))
80 /* Same entry found. Share this entry. */
81 atomic_inc(&ptr
->head
.users
);
86 if (tomoyo_memory_ok(entry
)) {
87 atomic_set(&entry
->head
.users
, 1);
88 list_add_rcu(&entry
->head
.list
,
89 &tomoyo_condition_list
);
95 mutex_unlock(&tomoyo_policy_lock
);
98 tomoyo_del_condition(&entry
->head
.list
);
106 * tomoyo_get_condition - Parse condition part.
108 * @param: Pointer to "struct tomoyo_acl_param".
110 * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
112 struct tomoyo_condition
*tomoyo_get_condition(struct tomoyo_acl_param
*param
)
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
);
122 pos
= start_of_string
;
126 char *left_word
= pos
;
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'.
142 cp
= strchr(pos
, ' ');
144 *cp
= '\0'; /* Will restore later. */
149 right_word
= strchr(left_word
, '=');
150 if (!right_word
|| right_word
== left_word
)
152 is_not
= *(right_word
- 1) == '!';
154 *(right_word
++ - 1) = '\0'; /* Will restore later. */
155 else if (*(right_word
+ 1) != '=')
156 *right_word
++ = '\0'; /* Will restore later. */
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
,
164 if (left
== TOMOYO_MAX_CONDITION_KEYWORD
) {
169 left
= TOMOYO_NUMBER_UNION
;
170 param
->data
= left_word
;
171 if (*left_word
== '@' ||
172 !tomoyo_parse_number_union(param
,
181 right
= tomoyo_condition_type(right_word
);
182 if (right
== TOMOYO_MAX_CONDITION_KEYWORD
) {
187 right
= TOMOYO_NUMBER_UNION
;
188 param
->data
= right_word
;
189 if (!tomoyo_parse_number_union(param
,
195 dprintk(KERN_WARNING
"%u: dry_run left=%u right=%u "
196 "match=%u\n", __LINE__
, left
, right
, !is_not
);
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
,
207 dprintk(KERN_INFO
"%u: cond=%u numbers=%u\n",
208 __LINE__
, e
.condc
, e
.numbers_count
);
210 BUG_ON(e
.numbers_count
| e
.condc
);
211 return tomoyo_commit_condition(entry
);
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
);
220 condp
= (struct tomoyo_condition_element
*) (entry
+ 1);
221 numbers_p
= (struct tomoyo_number_union
*) (condp
+ e
.condc
);
224 for (pos
= start_of_string
; pos
< end_of_string
; pos
++) {
227 if (flag
) /* Restore " ". */
229 else if (*(pos
+ 1) == '=') /* Restore "!=". */
231 else /* Restore "=". */
238 dprintk(KERN_WARNING
"%u: %s failed\n", __LINE__
, __func__
);
240 tomoyo_del_condition(&entry
->head
.list
);
247 * tomoyo_condition - Check condition part.
249 * @r: Pointer to "struct tomoyo_request_info".
250 * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
252 * Returns true on success, false otherwise.
254 * Caller holds tomoyo_read_lock().
256 bool tomoyo_condition(struct tomoyo_request_info
*r
,
257 const struct tomoyo_condition
*cond
)
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
;
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
;
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;
281 case TOMOYO_TASK_UID
:
282 value
= current_uid();
284 case TOMOYO_TASK_EUID
:
285 value
= current_euid();
287 case TOMOYO_TASK_SUID
:
288 value
= current_suid();
290 case TOMOYO_TASK_FSUID
:
291 value
= current_fsuid();
293 case TOMOYO_TASK_GID
:
294 value
= current_gid();
296 case TOMOYO_TASK_EGID
:
297 value
= current_egid();
299 case TOMOYO_TASK_SGID
:
300 value
= current_sgid();
302 case TOMOYO_TASK_FSGID
:
303 value
= current_fsgid();
305 case TOMOYO_TASK_PID
:
306 value
= tomoyo_sys_getpid();
308 case TOMOYO_TASK_PPID
:
309 value
= tomoyo_sys_getppid();
311 case TOMOYO_NUMBER_UNION
:
312 /* Fetch values later. */
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];
326 if (right
== TOMOYO_NUMBER_UNION
) {
327 /* Fetch values now. */
328 const struct tomoyo_number_union
*ptr
= numbers_p
++;
330 if (tomoyo_number_matches_group(min_v
[0],
336 if ((min_v
[0] <= ptr
->values
[1] &&
337 max_v
[0] >= ptr
->values
[0]) == match
)
342 /* Normal value range comparison. */
343 if ((min_v
[0] <= max_v
[1] && max_v
[0] >= min_v
[1]) == match
)