]> git.karo-electronics.de Git - linux-beck.git/blob - security/tomoyo/condition.c
TOMOYO: Allow using executable's realpath and symlink's target as conditions.
[linux-beck.git] / security / tomoyo / condition.c
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". */
11 LIST_HEAD(tomoyo_condition_list);
12
13 /**
14  * 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  */
22 static 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  */
46 static 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  */
65 static 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 /**
76  * 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  */
83 static 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 &&
88                 a->names_count == b->names_count &&
89                 !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  */
100 static 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  */
129 static 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);
159 out:
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  */
175 struct 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;
180         struct tomoyo_name_union *names_p = NULL;
181         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;
185 rerun:
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--;
245                 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                 }
259                 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                 }
272 store_value:
273                 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         }
286         dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u\n",
287                 __LINE__, e.condc, e.numbers_count, e.names_count);
288         if (entry) {
289                 BUG_ON(e.names_count | e.numbers_count | e.condc);
290                 return tomoyo_commit_condition(entry);
291         }
292         e.size = sizeof(*entry)
293                 + e.condc * sizeof(struct tomoyo_condition_element)
294                 + e.numbers_count * sizeof(struct tomoyo_number_union)
295                 + e.names_count * sizeof(struct tomoyo_name_union);
296         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);
302         names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count);
303         {
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;
318 out:
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 /**
328  * tomoyo_get_attributes - Revalidate "struct inode".
329  *
330  * @obj: Pointer to "struct tomoyo_obj_info".
331  *
332  * Returns nothing.
333  */
334 void 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 /**
376  * 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  */
385 bool 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;
393         const struct tomoyo_name_union *names_p;
394         struct tomoyo_obj_info *obj;
395         u16 condc;
396         if (!cond)
397                 return true;
398         condc = cond->condc;
399         obj = r->obj;
400         condp = (struct tomoyo_condition_element *) (cond + 1);
401         numbers_p = (const struct tomoyo_number_union *) (condp + condc);
402         names_p = (const struct tomoyo_name_union *)
403                 (numbers_p + cond->numbers_count);
404         for (i = 0; i < condc; i++) {
405                 const bool match = condp->equals;
406                 const u8 left = condp->left;
407                 const u8 right = condp->right;
408                 bool is_bitop[2] = { false, false };
409                 u8 j;
410                 condp++;
411                 /* 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                 }
435                 /* 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;
470                         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;
527                         case TOMOYO_NUMBER_UNION:
528                                 /* Fetch values later. */
529                                 break;
530                         default:
531                                 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                                 }
630                                 break;
631                         }
632                         max_v[j] = value;
633                         min_v[j] = value;
634                         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                         }
649                 }
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                 }
672                 /*
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                 }
699                 /* Normal value range comparison. */
700                 if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match)
701                         continue;
702 out:
703                 return false;
704         }
705         return true;
706 }