blob: 790b9872cc378938e7a9841ef6e401558cdd181a [file] [log] [blame]
Tetsuo Handa2066a362011-07-08 13:21:37 +09001/*
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/**
Tetsuo Handa2ca9bf42011-07-08 13:23:44 +090014 * tomoyo_scan_exec_realpath - Check "exec.realpath" parameter of "struct tomoyo_condition".
15 *
16 * @file: Pointer to "struct file".
17 * @ptr: Pointer to "struct tomoyo_name_union".
18 * @match: True if "exec.realpath=", false if "exec.realpath!=".
19 *
20 * Returns true on success, false otherwise.
21 */
22static bool tomoyo_scan_exec_realpath(struct file *file,
23 const struct tomoyo_name_union *ptr,
24 const bool match)
25{
26 bool result;
27 struct tomoyo_path_info exe;
28 if (!file)
29 return false;
30 exe.name = tomoyo_realpath_from_path(&file->f_path);
31 if (!exe.name)
32 return false;
33 tomoyo_fill_path_info(&exe);
34 result = tomoyo_compare_name_union(&exe, ptr);
35 kfree(exe.name);
36 return result == match;
37}
38
39/**
40 * tomoyo_get_dqword - tomoyo_get_name() for a quoted string.
41 *
42 * @start: String to save.
43 *
44 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
45 */
46static const struct tomoyo_path_info *tomoyo_get_dqword(char *start)
47{
48 char *cp = start + strlen(start) - 1;
49 if (cp == start || *start++ != '"' || *cp != '"')
50 return NULL;
51 *cp = '\0';
52 if (*start && !tomoyo_correct_word(start))
53 return NULL;
54 return tomoyo_get_name(start);
55}
56
57/**
58 * tomoyo_parse_name_union_quoted - Parse a quoted word.
59 *
60 * @param: Pointer to "struct tomoyo_acl_param".
61 * @ptr: Pointer to "struct tomoyo_name_union".
62 *
63 * Returns true on success, false otherwise.
64 */
65static bool tomoyo_parse_name_union_quoted(struct tomoyo_acl_param *param,
66 struct tomoyo_name_union *ptr)
67{
68 char *filename = param->data;
69 if (*filename == '@')
70 return tomoyo_parse_name_union(param, ptr);
71 ptr->filename = tomoyo_get_dqword(filename);
72 return ptr->filename != NULL;
73}
74
75/**
Tetsuo Handa2066a362011-07-08 13:21:37 +090076 * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry.
77 *
78 * @a: Pointer to "struct tomoyo_condition".
79 * @b: Pointer to "struct tomoyo_condition".
80 *
81 * Returns true if @a == @b, false otherwise.
82 */
83static inline bool tomoyo_same_condition(const struct tomoyo_condition *a,
84 const struct tomoyo_condition *b)
85{
86 return a->size == b->size && a->condc == b->condc &&
87 a->numbers_count == b->numbers_count &&
Tetsuo Handa2ca9bf42011-07-08 13:23:44 +090088 a->names_count == b->names_count &&
Tetsuo Handa2066a362011-07-08 13:21:37 +090089 !memcmp(a + 1, b + 1, a->size - sizeof(*a));
90}
91
92/**
93 * tomoyo_condition_type - Get condition type.
94 *
95 * @word: Keyword string.
96 *
97 * Returns one of values in "enum tomoyo_conditions_index" on success,
98 * TOMOYO_MAX_CONDITION_KEYWORD otherwise.
99 */
100static u8 tomoyo_condition_type(const char *word)
101{
102 u8 i;
103 for (i = 0; i < TOMOYO_MAX_CONDITION_KEYWORD; i++) {
104 if (!strcmp(word, tomoyo_condition_keyword[i]))
105 break;
106 }
107 return i;
108}
109
110/* Define this to enable debug mode. */
111/* #define DEBUG_CONDITION */
112
113#ifdef DEBUG_CONDITION
114#define dprintk printk
115#else
116#define dprintk(...) do { } while (0)
117#endif
118
119/**
120 * tomoyo_commit_condition - Commit "struct tomoyo_condition".
121 *
122 * @entry: Pointer to "struct tomoyo_condition".
123 *
124 * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
125 *
126 * This function merges duplicated entries. This function returns NULL if
127 * @entry is not duplicated but memory quota for policy has exceeded.
128 */
129static struct tomoyo_condition *tomoyo_commit_condition
130(struct tomoyo_condition *entry)
131{
132 struct tomoyo_condition *ptr;
133 bool found = false;
134 if (mutex_lock_interruptible(&tomoyo_policy_lock)) {
135 dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
136 ptr = NULL;
137 found = true;
138 goto out;
139 }
140 list_for_each_entry_rcu(ptr, &tomoyo_condition_list, head.list) {
141 if (!tomoyo_same_condition(ptr, entry))
142 continue;
143 /* Same entry found. Share this entry. */
144 atomic_inc(&ptr->head.users);
145 found = true;
146 break;
147 }
148 if (!found) {
149 if (tomoyo_memory_ok(entry)) {
150 atomic_set(&entry->head.users, 1);
151 list_add_rcu(&entry->head.list,
152 &tomoyo_condition_list);
153 } else {
154 found = true;
155 ptr = NULL;
156 }
157 }
158 mutex_unlock(&tomoyo_policy_lock);
159out:
160 if (found) {
161 tomoyo_del_condition(&entry->head.list);
162 kfree(entry);
163 entry = ptr;
164 }
165 return entry;
166}
167
168/**
169 * tomoyo_get_condition - Parse condition part.
170 *
171 * @param: Pointer to "struct tomoyo_acl_param".
172 *
173 * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
174 */
175struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param)
176{
177 struct tomoyo_condition *entry = NULL;
178 struct tomoyo_condition_element *condp = NULL;
179 struct tomoyo_number_union *numbers_p = NULL;
Tetsuo Handa2ca9bf42011-07-08 13:23:44 +0900180 struct tomoyo_name_union *names_p = NULL;
Tetsuo Handa2066a362011-07-08 13:21:37 +0900181 struct tomoyo_condition e = { };
182 char * const start_of_string = param->data;
183 char * const end_of_string = start_of_string + strlen(start_of_string);
184 char *pos;
185rerun:
186 pos = start_of_string;
187 while (1) {
188 u8 left = -1;
189 u8 right = -1;
190 char *left_word = pos;
191 char *cp;
192 char *right_word;
193 bool is_not;
194 if (!*left_word)
195 break;
196 /*
197 * Since left-hand condition does not allow use of "path_group"
198 * or "number_group" and environment variable's names do not
199 * accept '=', it is guaranteed that the original line consists
200 * of one or more repetition of $left$operator$right blocks
201 * where "$left is free from '=' and ' '" and "$operator is
202 * either '=' or '!='" and "$right is free from ' '".
203 * Therefore, we can reconstruct the original line at the end
204 * of dry run even if we overwrite $operator with '\0'.
205 */
206 cp = strchr(pos, ' ');
207 if (cp) {
208 *cp = '\0'; /* Will restore later. */
209 pos = cp + 1;
210 } else {
211 pos = "";
212 }
213 right_word = strchr(left_word, '=');
214 if (!right_word || right_word == left_word)
215 goto out;
216 is_not = *(right_word - 1) == '!';
217 if (is_not)
218 *(right_word++ - 1) = '\0'; /* Will restore later. */
219 else if (*(right_word + 1) != '=')
220 *right_word++ = '\0'; /* Will restore later. */
221 else
222 goto out;
223 dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word,
224 is_not ? "!" : "", right_word);
225 left = tomoyo_condition_type(left_word);
226 dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word,
227 left);
228 if (left == TOMOYO_MAX_CONDITION_KEYWORD) {
229 if (!numbers_p) {
230 e.numbers_count++;
231 } else {
232 e.numbers_count--;
233 left = TOMOYO_NUMBER_UNION;
234 param->data = left_word;
235 if (*left_word == '@' ||
236 !tomoyo_parse_number_union(param,
237 numbers_p++))
238 goto out;
239 }
240 }
241 if (!condp)
242 e.condc++;
243 else
244 e.condc--;
Tetsuo Handa2ca9bf42011-07-08 13:23:44 +0900245 if (left == TOMOYO_EXEC_REALPATH ||
246 left == TOMOYO_SYMLINK_TARGET) {
247 if (!names_p) {
248 e.names_count++;
249 } else {
250 e.names_count--;
251 right = TOMOYO_NAME_UNION;
252 param->data = right_word;
253 if (!tomoyo_parse_name_union_quoted(param,
254 names_p++))
255 goto out;
256 }
257 goto store_value;
258 }
Tetsuo Handa2066a362011-07-08 13:21:37 +0900259 right = tomoyo_condition_type(right_word);
260 if (right == TOMOYO_MAX_CONDITION_KEYWORD) {
261 if (!numbers_p) {
262 e.numbers_count++;
263 } else {
264 e.numbers_count--;
265 right = TOMOYO_NUMBER_UNION;
266 param->data = right_word;
267 if (!tomoyo_parse_number_union(param,
268 numbers_p++))
269 goto out;
270 }
271 }
Tetsuo Handa2ca9bf42011-07-08 13:23:44 +0900272store_value:
Tetsuo Handa2066a362011-07-08 13:21:37 +0900273 if (!condp) {
274 dprintk(KERN_WARNING "%u: dry_run left=%u right=%u "
275 "match=%u\n", __LINE__, left, right, !is_not);
276 continue;
277 }
278 condp->left = left;
279 condp->right = right;
280 condp->equals = !is_not;
281 dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
282 __LINE__, condp->left, condp->right,
283 condp->equals);
284 condp++;
285 }
Tetsuo Handa2ca9bf42011-07-08 13:23:44 +0900286 dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u\n",
287 __LINE__, e.condc, e.numbers_count, e.names_count);
Tetsuo Handa2066a362011-07-08 13:21:37 +0900288 if (entry) {
Tetsuo Handa2ca9bf42011-07-08 13:23:44 +0900289 BUG_ON(e.names_count | e.numbers_count | e.condc);
Tetsuo Handa2066a362011-07-08 13:21:37 +0900290 return tomoyo_commit_condition(entry);
291 }
292 e.size = sizeof(*entry)
293 + e.condc * sizeof(struct tomoyo_condition_element)
Tetsuo Handa2ca9bf42011-07-08 13:23:44 +0900294 + e.numbers_count * sizeof(struct tomoyo_number_union)
295 + e.names_count * sizeof(struct tomoyo_name_union);
Tetsuo Handa2066a362011-07-08 13:21:37 +0900296 entry = kzalloc(e.size, GFP_NOFS);
297 if (!entry)
298 return NULL;
299 *entry = e;
300 condp = (struct tomoyo_condition_element *) (entry + 1);
301 numbers_p = (struct tomoyo_number_union *) (condp + e.condc);
Tetsuo Handa2ca9bf42011-07-08 13:23:44 +0900302 names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count);
Tetsuo Handa2066a362011-07-08 13:21:37 +0900303 {
304 bool flag = false;
305 for (pos = start_of_string; pos < end_of_string; pos++) {
306 if (*pos)
307 continue;
308 if (flag) /* Restore " ". */
309 *pos = ' ';
310 else if (*(pos + 1) == '=') /* Restore "!=". */
311 *pos = '!';
312 else /* Restore "=". */
313 *pos = '=';
314 flag = !flag;
315 }
316 }
317 goto rerun;
318out:
319 dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
320 if (entry) {
321 tomoyo_del_condition(&entry->head.list);
322 kfree(entry);
323 }
324 return NULL;
325}
326
327/**
Tetsuo Handa8761afd2011-07-08 13:22:41 +0900328 * tomoyo_get_attributes - Revalidate "struct inode".
329 *
330 * @obj: Pointer to "struct tomoyo_obj_info".
331 *
332 * Returns nothing.
333 */
334void tomoyo_get_attributes(struct tomoyo_obj_info *obj)
335{
336 u8 i;
337 struct dentry *dentry = NULL;
338
339 for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) {
340 struct inode *inode;
341 switch (i) {
342 case TOMOYO_PATH1:
343 dentry = obj->path1.dentry;
344 if (!dentry)
345 continue;
346 break;
347 case TOMOYO_PATH2:
348 dentry = obj->path2.dentry;
349 if (!dentry)
350 continue;
351 break;
352 default:
353 if (!dentry)
354 continue;
355 dentry = dget_parent(dentry);
356 break;
357 }
358 inode = dentry->d_inode;
359 if (inode) {
360 struct tomoyo_mini_stat *stat = &obj->stat[i];
361 stat->uid = inode->i_uid;
362 stat->gid = inode->i_gid;
363 stat->ino = inode->i_ino;
364 stat->mode = inode->i_mode;
365 stat->dev = inode->i_sb->s_dev;
366 stat->rdev = inode->i_rdev;
367 obj->stat_valid[i] = true;
368 }
369 if (i & 1) /* i == TOMOYO_PATH1_PARENT ||
370 i == TOMOYO_PATH2_PARENT */
371 dput(dentry);
372 }
373}
374
375/**
Tetsuo Handa2066a362011-07-08 13:21:37 +0900376 * tomoyo_condition - Check condition part.
377 *
378 * @r: Pointer to "struct tomoyo_request_info".
379 * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
380 *
381 * Returns true on success, false otherwise.
382 *
383 * Caller holds tomoyo_read_lock().
384 */
385bool tomoyo_condition(struct tomoyo_request_info *r,
386 const struct tomoyo_condition *cond)
387{
388 u32 i;
389 unsigned long min_v[2] = { 0, 0 };
390 unsigned long max_v[2] = { 0, 0 };
391 const struct tomoyo_condition_element *condp;
392 const struct tomoyo_number_union *numbers_p;
Tetsuo Handa2ca9bf42011-07-08 13:23:44 +0900393 const struct tomoyo_name_union *names_p;
Tetsuo Handa8761afd2011-07-08 13:22:41 +0900394 struct tomoyo_obj_info *obj;
Tetsuo Handa2066a362011-07-08 13:21:37 +0900395 u16 condc;
396 if (!cond)
397 return true;
398 condc = cond->condc;
Tetsuo Handa8761afd2011-07-08 13:22:41 +0900399 obj = r->obj;
Tetsuo Handa2066a362011-07-08 13:21:37 +0900400 condp = (struct tomoyo_condition_element *) (cond + 1);
401 numbers_p = (const struct tomoyo_number_union *) (condp + condc);
Tetsuo Handa2ca9bf42011-07-08 13:23:44 +0900402 names_p = (const struct tomoyo_name_union *)
403 (numbers_p + cond->numbers_count);
Tetsuo Handa2066a362011-07-08 13:21:37 +0900404 for (i = 0; i < condc; i++) {
405 const bool match = condp->equals;
406 const u8 left = condp->left;
407 const u8 right = condp->right;
Tetsuo Handa8761afd2011-07-08 13:22:41 +0900408 bool is_bitop[2] = { false, false };
Tetsuo Handa2066a362011-07-08 13:21:37 +0900409 u8 j;
410 condp++;
Tetsuo Handa2ca9bf42011-07-08 13:23:44 +0900411 /* Check string expressions. */
412 if (right == TOMOYO_NAME_UNION) {
413 const struct tomoyo_name_union *ptr = names_p++;
414 switch (left) {
415 struct tomoyo_path_info *symlink;
416 struct tomoyo_execve *ee;
417 struct file *file;
418 case TOMOYO_SYMLINK_TARGET:
419 symlink = obj ? obj->symlink_target : NULL;
420 if (!symlink ||
421 !tomoyo_compare_name_union(symlink, ptr)
422 == match)
423 goto out;
424 break;
425 case TOMOYO_EXEC_REALPATH:
426 ee = r->ee;
427 file = ee ? ee->bprm->file : NULL;
428 if (!tomoyo_scan_exec_realpath(file, ptr,
429 match))
430 goto out;
431 break;
432 }
433 continue;
434 }
Tetsuo Handa2066a362011-07-08 13:21:37 +0900435 /* Check numeric or bit-op expressions. */
436 for (j = 0; j < 2; j++) {
437 const u8 index = j ? right : left;
438 unsigned long value = 0;
439 switch (index) {
440 case TOMOYO_TASK_UID:
441 value = current_uid();
442 break;
443 case TOMOYO_TASK_EUID:
444 value = current_euid();
445 break;
446 case TOMOYO_TASK_SUID:
447 value = current_suid();
448 break;
449 case TOMOYO_TASK_FSUID:
450 value = current_fsuid();
451 break;
452 case TOMOYO_TASK_GID:
453 value = current_gid();
454 break;
455 case TOMOYO_TASK_EGID:
456 value = current_egid();
457 break;
458 case TOMOYO_TASK_SGID:
459 value = current_sgid();
460 break;
461 case TOMOYO_TASK_FSGID:
462 value = current_fsgid();
463 break;
464 case TOMOYO_TASK_PID:
465 value = tomoyo_sys_getpid();
466 break;
467 case TOMOYO_TASK_PPID:
468 value = tomoyo_sys_getppid();
469 break;
Tetsuo Handa8761afd2011-07-08 13:22:41 +0900470 case TOMOYO_TYPE_IS_SOCKET:
471 value = S_IFSOCK;
472 break;
473 case TOMOYO_TYPE_IS_SYMLINK:
474 value = S_IFLNK;
475 break;
476 case TOMOYO_TYPE_IS_FILE:
477 value = S_IFREG;
478 break;
479 case TOMOYO_TYPE_IS_BLOCK_DEV:
480 value = S_IFBLK;
481 break;
482 case TOMOYO_TYPE_IS_DIRECTORY:
483 value = S_IFDIR;
484 break;
485 case TOMOYO_TYPE_IS_CHAR_DEV:
486 value = S_IFCHR;
487 break;
488 case TOMOYO_TYPE_IS_FIFO:
489 value = S_IFIFO;
490 break;
491 case TOMOYO_MODE_SETUID:
492 value = S_ISUID;
493 break;
494 case TOMOYO_MODE_SETGID:
495 value = S_ISGID;
496 break;
497 case TOMOYO_MODE_STICKY:
498 value = S_ISVTX;
499 break;
500 case TOMOYO_MODE_OWNER_READ:
501 value = S_IRUSR;
502 break;
503 case TOMOYO_MODE_OWNER_WRITE:
504 value = S_IWUSR;
505 break;
506 case TOMOYO_MODE_OWNER_EXECUTE:
507 value = S_IXUSR;
508 break;
509 case TOMOYO_MODE_GROUP_READ:
510 value = S_IRGRP;
511 break;
512 case TOMOYO_MODE_GROUP_WRITE:
513 value = S_IWGRP;
514 break;
515 case TOMOYO_MODE_GROUP_EXECUTE:
516 value = S_IXGRP;
517 break;
518 case TOMOYO_MODE_OTHERS_READ:
519 value = S_IROTH;
520 break;
521 case TOMOYO_MODE_OTHERS_WRITE:
522 value = S_IWOTH;
523 break;
524 case TOMOYO_MODE_OTHERS_EXECUTE:
525 value = S_IXOTH;
526 break;
Tetsuo Handa2066a362011-07-08 13:21:37 +0900527 case TOMOYO_NUMBER_UNION:
528 /* Fetch values later. */
529 break;
530 default:
Tetsuo Handa8761afd2011-07-08 13:22:41 +0900531 if (!obj)
532 goto out;
533 if (!obj->validate_done) {
534 tomoyo_get_attributes(obj);
535 obj->validate_done = true;
536 }
537 {
538 u8 stat_index;
539 struct tomoyo_mini_stat *stat;
540 switch (index) {
541 case TOMOYO_PATH1_UID:
542 case TOMOYO_PATH1_GID:
543 case TOMOYO_PATH1_INO:
544 case TOMOYO_PATH1_MAJOR:
545 case TOMOYO_PATH1_MINOR:
546 case TOMOYO_PATH1_TYPE:
547 case TOMOYO_PATH1_DEV_MAJOR:
548 case TOMOYO_PATH1_DEV_MINOR:
549 case TOMOYO_PATH1_PERM:
550 stat_index = TOMOYO_PATH1;
551 break;
552 case TOMOYO_PATH2_UID:
553 case TOMOYO_PATH2_GID:
554 case TOMOYO_PATH2_INO:
555 case TOMOYO_PATH2_MAJOR:
556 case TOMOYO_PATH2_MINOR:
557 case TOMOYO_PATH2_TYPE:
558 case TOMOYO_PATH2_DEV_MAJOR:
559 case TOMOYO_PATH2_DEV_MINOR:
560 case TOMOYO_PATH2_PERM:
561 stat_index = TOMOYO_PATH2;
562 break;
563 case TOMOYO_PATH1_PARENT_UID:
564 case TOMOYO_PATH1_PARENT_GID:
565 case TOMOYO_PATH1_PARENT_INO:
566 case TOMOYO_PATH1_PARENT_PERM:
567 stat_index =
568 TOMOYO_PATH1_PARENT;
569 break;
570 case TOMOYO_PATH2_PARENT_UID:
571 case TOMOYO_PATH2_PARENT_GID:
572 case TOMOYO_PATH2_PARENT_INO:
573 case TOMOYO_PATH2_PARENT_PERM:
574 stat_index =
575 TOMOYO_PATH2_PARENT;
576 break;
577 default:
578 goto out;
579 }
580 if (!obj->stat_valid[stat_index])
581 goto out;
582 stat = &obj->stat[stat_index];
583 switch (index) {
584 case TOMOYO_PATH1_UID:
585 case TOMOYO_PATH2_UID:
586 case TOMOYO_PATH1_PARENT_UID:
587 case TOMOYO_PATH2_PARENT_UID:
588 value = stat->uid;
589 break;
590 case TOMOYO_PATH1_GID:
591 case TOMOYO_PATH2_GID:
592 case TOMOYO_PATH1_PARENT_GID:
593 case TOMOYO_PATH2_PARENT_GID:
594 value = stat->gid;
595 break;
596 case TOMOYO_PATH1_INO:
597 case TOMOYO_PATH2_INO:
598 case TOMOYO_PATH1_PARENT_INO:
599 case TOMOYO_PATH2_PARENT_INO:
600 value = stat->ino;
601 break;
602 case TOMOYO_PATH1_MAJOR:
603 case TOMOYO_PATH2_MAJOR:
604 value = MAJOR(stat->dev);
605 break;
606 case TOMOYO_PATH1_MINOR:
607 case TOMOYO_PATH2_MINOR:
608 value = MINOR(stat->dev);
609 break;
610 case TOMOYO_PATH1_TYPE:
611 case TOMOYO_PATH2_TYPE:
612 value = stat->mode & S_IFMT;
613 break;
614 case TOMOYO_PATH1_DEV_MAJOR:
615 case TOMOYO_PATH2_DEV_MAJOR:
616 value = MAJOR(stat->rdev);
617 break;
618 case TOMOYO_PATH1_DEV_MINOR:
619 case TOMOYO_PATH2_DEV_MINOR:
620 value = MINOR(stat->rdev);
621 break;
622 case TOMOYO_PATH1_PERM:
623 case TOMOYO_PATH2_PERM:
624 case TOMOYO_PATH1_PARENT_PERM:
625 case TOMOYO_PATH2_PARENT_PERM:
626 value = stat->mode & S_IALLUGO;
627 break;
628 }
629 }
Tetsuo Handa2066a362011-07-08 13:21:37 +0900630 break;
631 }
632 max_v[j] = value;
633 min_v[j] = value;
Tetsuo Handa8761afd2011-07-08 13:22:41 +0900634 switch (index) {
635 case TOMOYO_MODE_SETUID:
636 case TOMOYO_MODE_SETGID:
637 case TOMOYO_MODE_STICKY:
638 case TOMOYO_MODE_OWNER_READ:
639 case TOMOYO_MODE_OWNER_WRITE:
640 case TOMOYO_MODE_OWNER_EXECUTE:
641 case TOMOYO_MODE_GROUP_READ:
642 case TOMOYO_MODE_GROUP_WRITE:
643 case TOMOYO_MODE_GROUP_EXECUTE:
644 case TOMOYO_MODE_OTHERS_READ:
645 case TOMOYO_MODE_OTHERS_WRITE:
646 case TOMOYO_MODE_OTHERS_EXECUTE:
647 is_bitop[j] = true;
648 }
Tetsuo Handa2066a362011-07-08 13:21:37 +0900649 }
650 if (left == TOMOYO_NUMBER_UNION) {
651 /* Fetch values now. */
652 const struct tomoyo_number_union *ptr = numbers_p++;
653 min_v[0] = ptr->values[0];
654 max_v[0] = ptr->values[1];
655 }
656 if (right == TOMOYO_NUMBER_UNION) {
657 /* Fetch values now. */
658 const struct tomoyo_number_union *ptr = numbers_p++;
659 if (ptr->group) {
660 if (tomoyo_number_matches_group(min_v[0],
661 max_v[0],
662 ptr->group)
663 == match)
664 continue;
665 } else {
666 if ((min_v[0] <= ptr->values[1] &&
667 max_v[0] >= ptr->values[0]) == match)
668 continue;
669 }
670 goto out;
671 }
Tetsuo Handa8761afd2011-07-08 13:22:41 +0900672 /*
673 * Bit operation is valid only when counterpart value
674 * represents permission.
675 */
676 if (is_bitop[0] && is_bitop[1]) {
677 goto out;
678 } else if (is_bitop[0]) {
679 switch (right) {
680 case TOMOYO_PATH1_PERM:
681 case TOMOYO_PATH1_PARENT_PERM:
682 case TOMOYO_PATH2_PERM:
683 case TOMOYO_PATH2_PARENT_PERM:
684 if (!(max_v[0] & max_v[1]) == !match)
685 continue;
686 }
687 goto out;
688 } else if (is_bitop[1]) {
689 switch (left) {
690 case TOMOYO_PATH1_PERM:
691 case TOMOYO_PATH1_PARENT_PERM:
692 case TOMOYO_PATH2_PERM:
693 case TOMOYO_PATH2_PARENT_PERM:
694 if (!(max_v[0] & max_v[1]) == !match)
695 continue;
696 }
697 goto out;
698 }
Tetsuo Handa2066a362011-07-08 13:21:37 +0900699 /* Normal value range comparison. */
700 if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match)
701 continue;
702out:
703 return false;
704 }
705 return true;
706}