Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
condition.c
Go to the documentation of this file.
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 
24 static bool tomoyo_argv(const unsigned int index, const char *arg_ptr,
25  const int argc, const struct tomoyo_argv *argv,
26  u8 *checked)
27 {
28  int i;
29  struct tomoyo_path_info arg;
30  arg.name = arg_ptr;
31  for (i = 0; i < argc; argv++, checked++, i++) {
32  bool result;
33  if (index != argv->index)
34  continue;
35  *checked = 1;
37  result = tomoyo_path_matches_pattern(&arg, argv->value);
38  if (argv->is_not)
39  result = !result;
40  if (!result)
41  return false;
42  }
43  return true;
44 }
45 
57 static bool tomoyo_envp(const char *env_name, const char *env_value,
58  const int envc, const struct tomoyo_envp *envp,
59  u8 *checked)
60 {
61  int i;
62  struct tomoyo_path_info name;
63  struct tomoyo_path_info value;
64  name.name = env_name;
66  value.name = env_value;
68  for (i = 0; i < envc; envp++, checked++, i++) {
69  bool result;
71  continue;
72  *checked = 1;
73  if (envp->value) {
75  envp->value);
76  if (envp->is_not)
77  result = !result;
78  } else {
79  result = true;
80  if (!envp->is_not)
81  result = !result;
82  }
83  if (!result)
84  return false;
85  }
86  return true;
87 }
88 
100 static bool tomoyo_scan_bprm(struct tomoyo_execve *ee,
101  const u16 argc, const struct tomoyo_argv *argv,
102  const u16 envc, const struct tomoyo_envp *envp)
103 {
104  struct linux_binprm *bprm = ee->bprm;
105  struct tomoyo_page_dump *dump = &ee->dump;
106  char *arg_ptr = ee->tmp;
107  int arg_len = 0;
108  unsigned long pos = bprm->p;
109  int offset = pos % PAGE_SIZE;
110  int argv_count = bprm->argc;
111  int envp_count = bprm->envc;
112  bool result = true;
113  u8 local_checked[32];
114  u8 *checked;
115  if (argc + envc <= sizeof(local_checked)) {
116  checked = local_checked;
117  memset(local_checked, 0, sizeof(local_checked));
118  } else {
119  checked = kzalloc(argc + envc, GFP_NOFS);
120  if (!checked)
121  return false;
122  }
123  while (argv_count || envp_count) {
124  if (!tomoyo_dump_page(bprm, pos, dump)) {
125  result = false;
126  goto out;
127  }
128  pos += PAGE_SIZE - offset;
129  while (offset < PAGE_SIZE) {
130  /* Read. */
131  const char *kaddr = dump->data;
132  const unsigned char c = kaddr[offset++];
133  if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) {
134  if (c == '\\') {
135  arg_ptr[arg_len++] = '\\';
136  arg_ptr[arg_len++] = '\\';
137  } else if (c > ' ' && c < 127) {
138  arg_ptr[arg_len++] = c;
139  } else {
140  arg_ptr[arg_len++] = '\\';
141  arg_ptr[arg_len++] = (c >> 6) + '0';
142  arg_ptr[arg_len++] =
143  ((c >> 3) & 7) + '0';
144  arg_ptr[arg_len++] = (c & 7) + '0';
145  }
146  } else {
147  arg_ptr[arg_len] = '\0';
148  }
149  if (c)
150  continue;
151  /* Check. */
152  if (argv_count) {
153  if (!tomoyo_argv(bprm->argc - argv_count,
154  arg_ptr, argc, argv,
155  checked)) {
156  result = false;
157  break;
158  }
159  argv_count--;
160  } else if (envp_count) {
161  char *cp = strchr(arg_ptr, '=');
162  if (cp) {
163  *cp = '\0';
164  if (!tomoyo_envp(arg_ptr, cp + 1,
165  envc, envp,
166  checked + argc)) {
167  result = false;
168  break;
169  }
170  }
171  envp_count--;
172  } else {
173  break;
174  }
175  arg_len = 0;
176  }
177  offset = 0;
178  if (!result)
179  break;
180  }
181 out:
182  if (result) {
183  int i;
184  /* Check not-yet-checked entries. */
185  for (i = 0; i < argc; i++) {
186  if (checked[i])
187  continue;
188  /*
189  * Return true only if all unchecked indexes in
190  * bprm->argv[] are not matched.
191  */
192  if (argv[i].is_not)
193  continue;
194  result = false;
195  break;
196  }
197  for (i = 0; i < envc; envp++, i++) {
198  if (checked[argc + i])
199  continue;
200  /*
201  * Return true only if all unchecked environ variables
202  * in bprm->envp[] are either undefined or not matched.
203  */
204  if ((!envp->value && !envp->is_not) ||
205  (envp->value && envp->is_not))
206  continue;
207  result = false;
208  break;
209  }
210  }
211  if (checked != local_checked)
212  kfree(checked);
213  return result;
214 }
215 
225 static bool tomoyo_scan_exec_realpath(struct file *file,
226  const struct tomoyo_name_union *ptr,
227  const bool match)
228 {
229  bool result;
230  struct tomoyo_path_info exe;
231  if (!file)
232  return false;
233  exe.name = tomoyo_realpath_from_path(&file->f_path);
234  if (!exe.name)
235  return false;
236  tomoyo_fill_path_info(&exe);
237  result = tomoyo_compare_name_union(&exe, ptr);
238  kfree(exe.name);
239  return result == match;
240 }
241 
249 static const struct tomoyo_path_info *tomoyo_get_dqword(char *start)
250 {
251  char *cp = start + strlen(start) - 1;
252  if (cp == start || *start++ != '"' || *cp != '"')
253  return NULL;
254  *cp = '\0';
255  if (*start && !tomoyo_correct_word(start))
256  return NULL;
257  return tomoyo_get_name(start);
258 }
259 
268 static bool tomoyo_parse_name_union_quoted(struct tomoyo_acl_param *param,
269  struct tomoyo_name_union *ptr)
270 {
271  char *filename = param->data;
272  if (*filename == '@')
273  return tomoyo_parse_name_union(param, ptr);
274  ptr->filename = tomoyo_get_dqword(filename);
275  return ptr->filename != NULL;
276 }
277 
287 static bool tomoyo_parse_argv(char *left, char *right,
288  struct tomoyo_argv *argv)
289 {
290  if (tomoyo_parse_ulong(&argv->index, &left) !=
291  TOMOYO_VALUE_TYPE_DECIMAL || *left++ != ']' || *left)
292  return false;
293  argv->value = tomoyo_get_dqword(right);
294  return argv->value != NULL;
295 }
296 
306 static bool tomoyo_parse_envp(char *left, char *right,
307  struct tomoyo_envp *envp)
308 {
309  const struct tomoyo_path_info *name;
310  const struct tomoyo_path_info *value;
311  char *cp = left + strlen(left) - 1;
312  if (*cp-- != ']' || *cp != '"')
313  goto out;
314  *cp = '\0';
315  if (!tomoyo_correct_word(left))
316  goto out;
317  name = tomoyo_get_name(left);
318  if (!name)
319  goto out;
320  if (!strcmp(right, "NULL")) {
321  value = NULL;
322  } else {
323  value = tomoyo_get_dqword(right);
324  if (!value) {
325  tomoyo_put_name(name);
326  goto out;
327  }
328  }
329  envp->name = name;
330  envp->value = value;
331  return true;
332 out:
333  return false;
334 }
335 
344 static inline bool tomoyo_same_condition(const struct tomoyo_condition *a,
345  const struct tomoyo_condition *b)
346 {
347  return a->size == b->size && a->condc == b->condc &&
348  a->numbers_count == b->numbers_count &&
349  a->names_count == b->names_count &&
350  a->argc == b->argc && a->envc == b->envc &&
351  a->grant_log == b->grant_log && a->transit == b->transit &&
352  !memcmp(a + 1, b + 1, a->size - sizeof(*a));
353 }
354 
363 static u8 tomoyo_condition_type(const char *word)
364 {
365  u8 i;
366  for (i = 0; i < TOMOYO_MAX_CONDITION_KEYWORD; i++) {
367  if (!strcmp(word, tomoyo_condition_keyword[i]))
368  break;
369  }
370  return i;
371 }
372 
373 /* Define this to enable debug mode. */
374 /* #define DEBUG_CONDITION */
375 
376 #ifdef DEBUG_CONDITION
377 #define dprintk printk
378 #else
379 #define dprintk(...) do { } while (0)
380 #endif
381 
392 static struct tomoyo_condition *tomoyo_commit_condition
393 (struct tomoyo_condition *entry)
394 {
395  struct tomoyo_condition *ptr;
396  bool found = false;
398  dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
399  ptr = NULL;
400  found = true;
401  goto out;
402  }
404  if (!tomoyo_same_condition(ptr, entry) ||
405  atomic_read(&ptr->head.users) == TOMOYO_GC_IN_PROGRESS)
406  continue;
407  /* Same entry found. Share this entry. */
408  atomic_inc(&ptr->head.users);
409  found = true;
410  break;
411  }
412  if (!found) {
413  if (tomoyo_memory_ok(entry)) {
414  atomic_set(&entry->head.users, 1);
415  list_add(&entry->head.list, &tomoyo_condition_list);
416  } else {
417  found = true;
418  ptr = NULL;
419  }
420  }
422 out:
423  if (found) {
424  tomoyo_del_condition(&entry->head.list);
425  kfree(entry);
426  entry = ptr;
427  }
428  return entry;
429 }
430 
439 static char *tomoyo_get_transit_preference(struct tomoyo_acl_param *param,
440  struct tomoyo_condition *e)
441 {
442  char * const pos = param->data;
443  bool flag;
444  if (*pos == '<') {
445  e->transit = tomoyo_get_domainname(param);
446  goto done;
447  }
448  {
449  char *cp = strchr(pos, ' ');
450  if (cp)
451  *cp = '\0';
452  flag = tomoyo_correct_path(pos) || !strcmp(pos, "keep") ||
453  !strcmp(pos, "initialize") || !strcmp(pos, "reset") ||
454  !strcmp(pos, "child") || !strcmp(pos, "parent");
455  if (cp)
456  *cp = ' ';
457  }
458  if (!flag)
459  return pos;
461 done:
462  if (e->transit)
463  return param->data;
464  /*
465  * Return a bad read-only condition string that will let
466  * tomoyo_get_condition() return NULL.
467  */
468  return "/";
469 }
470 
479 {
480  struct tomoyo_condition *entry = NULL;
481  struct tomoyo_condition_element *condp = NULL;
482  struct tomoyo_number_union *numbers_p = NULL;
483  struct tomoyo_name_union *names_p = NULL;
484  struct tomoyo_argv *argv = NULL;
485  struct tomoyo_envp *envp = NULL;
486  struct tomoyo_condition e = { };
487  char * const start_of_string =
488  tomoyo_get_transit_preference(param, &e);
489  char * const end_of_string = start_of_string + strlen(start_of_string);
490  char *pos;
491 rerun:
492  pos = start_of_string;
493  while (1) {
494  u8 left = -1;
495  u8 right = -1;
496  char *left_word = pos;
497  char *cp;
498  char *right_word;
499  bool is_not;
500  if (!*left_word)
501  break;
502  /*
503  * Since left-hand condition does not allow use of "path_group"
504  * or "number_group" and environment variable's names do not
505  * accept '=', it is guaranteed that the original line consists
506  * of one or more repetition of $left$operator$right blocks
507  * where "$left is free from '=' and ' '" and "$operator is
508  * either '=' or '!='" and "$right is free from ' '".
509  * Therefore, we can reconstruct the original line at the end
510  * of dry run even if we overwrite $operator with '\0'.
511  */
512  cp = strchr(pos, ' ');
513  if (cp) {
514  *cp = '\0'; /* Will restore later. */
515  pos = cp + 1;
516  } else {
517  pos = "";
518  }
519  right_word = strchr(left_word, '=');
520  if (!right_word || right_word == left_word)
521  goto out;
522  is_not = *(right_word - 1) == '!';
523  if (is_not)
524  *(right_word++ - 1) = '\0'; /* Will restore later. */
525  else if (*(right_word + 1) != '=')
526  *right_word++ = '\0'; /* Will restore later. */
527  else
528  goto out;
529  dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word,
530  is_not ? "!" : "", right_word);
531  if (!strcmp(left_word, "grant_log")) {
532  if (entry) {
533  if (is_not ||
535  goto out;
536  else if (!strcmp(right_word, "yes"))
538  else if (!strcmp(right_word, "no"))
539  entry->grant_log = TOMOYO_GRANTLOG_NO;
540  else
541  goto out;
542  }
543  continue;
544  }
545  if (!strncmp(left_word, "exec.argv[", 10)) {
546  if (!argv) {
547  e.argc++;
548  e.condc++;
549  } else {
550  e.argc--;
551  e.condc--;
552  left = TOMOYO_ARGV_ENTRY;
553  argv->is_not = is_not;
554  if (!tomoyo_parse_argv(left_word + 10,
555  right_word, argv++))
556  goto out;
557  }
558  goto store_value;
559  }
560  if (!strncmp(left_word, "exec.envp[\"", 11)) {
561  if (!envp) {
562  e.envc++;
563  e.condc++;
564  } else {
565  e.envc--;
566  e.condc--;
567  left = TOMOYO_ENVP_ENTRY;
568  envp->is_not = is_not;
569  if (!tomoyo_parse_envp(left_word + 11,
570  right_word, envp++))
571  goto out;
572  }
573  goto store_value;
574  }
575  left = tomoyo_condition_type(left_word);
576  dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word,
577  left);
578  if (left == TOMOYO_MAX_CONDITION_KEYWORD) {
579  if (!numbers_p) {
580  e.numbers_count++;
581  } else {
582  e.numbers_count--;
583  left = TOMOYO_NUMBER_UNION;
584  param->data = left_word;
585  if (*left_word == '@' ||
587  numbers_p++))
588  goto out;
589  }
590  }
591  if (!condp)
592  e.condc++;
593  else
594  e.condc--;
595  if (left == TOMOYO_EXEC_REALPATH ||
596  left == TOMOYO_SYMLINK_TARGET) {
597  if (!names_p) {
598  e.names_count++;
599  } else {
600  e.names_count--;
601  right = TOMOYO_NAME_UNION;
602  param->data = right_word;
603  if (!tomoyo_parse_name_union_quoted(param,
604  names_p++))
605  goto out;
606  }
607  goto store_value;
608  }
609  right = tomoyo_condition_type(right_word);
610  if (right == TOMOYO_MAX_CONDITION_KEYWORD) {
611  if (!numbers_p) {
612  e.numbers_count++;
613  } else {
614  e.numbers_count--;
615  right = TOMOYO_NUMBER_UNION;
616  param->data = right_word;
617  if (!tomoyo_parse_number_union(param,
618  numbers_p++))
619  goto out;
620  }
621  }
622 store_value:
623  if (!condp) {
624  dprintk(KERN_WARNING "%u: dry_run left=%u right=%u "
625  "match=%u\n", __LINE__, left, right, !is_not);
626  continue;
627  }
628  condp->left = left;
629  condp->right = right;
630  condp->equals = !is_not;
631  dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
632  __LINE__, condp->left, condp->right,
633  condp->equals);
634  condp++;
635  }
636  dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n",
637  __LINE__, e.condc, e.numbers_count, e.names_count, e.argc,
638  e.envc);
639  if (entry) {
640  BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc |
641  e.condc);
642  return tomoyo_commit_condition(entry);
643  }
644  e.size = sizeof(*entry)
645  + e.condc * sizeof(struct tomoyo_condition_element)
646  + e.numbers_count * sizeof(struct tomoyo_number_union)
647  + e.names_count * sizeof(struct tomoyo_name_union)
648  + e.argc * sizeof(struct tomoyo_argv)
649  + e.envc * sizeof(struct tomoyo_envp);
650  entry = kzalloc(e.size, GFP_NOFS);
651  if (!entry)
652  goto out2;
653  *entry = e;
654  e.transit = NULL;
655  condp = (struct tomoyo_condition_element *) (entry + 1);
656  numbers_p = (struct tomoyo_number_union *) (condp + e.condc);
657  names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count);
658  argv = (struct tomoyo_argv *) (names_p + e.names_count);
659  envp = (struct tomoyo_envp *) (argv + e.argc);
660  {
661  bool flag = false;
662  for (pos = start_of_string; pos < end_of_string; pos++) {
663  if (*pos)
664  continue;
665  if (flag) /* Restore " ". */
666  *pos = ' ';
667  else if (*(pos + 1) == '=') /* Restore "!=". */
668  *pos = '!';
669  else /* Restore "=". */
670  *pos = '=';
671  flag = !flag;
672  }
673  }
674  goto rerun;
675 out:
676  dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
677  if (entry) {
678  tomoyo_del_condition(&entry->head.list);
679  kfree(entry);
680  }
681 out2:
682  tomoyo_put_name(e.transit);
683  return NULL;
684 }
685 
694 {
695  u8 i;
696  struct dentry *dentry = NULL;
697 
698  for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) {
699  struct inode *inode;
700  switch (i) {
701  case TOMOYO_PATH1:
702  dentry = obj->path1.dentry;
703  if (!dentry)
704  continue;
705  break;
706  case TOMOYO_PATH2:
707  dentry = obj->path2.dentry;
708  if (!dentry)
709  continue;
710  break;
711  default:
712  if (!dentry)
713  continue;
714  dentry = dget_parent(dentry);
715  break;
716  }
717  inode = dentry->d_inode;
718  if (inode) {
719  struct tomoyo_mini_stat *stat = &obj->stat[i];
720  stat->uid = inode->i_uid;
721  stat->gid = inode->i_gid;
722  stat->ino = inode->i_ino;
723  stat->mode = inode->i_mode;
724  stat->dev = inode->i_sb->s_dev;
725  stat->rdev = inode->i_rdev;
726  obj->stat_valid[i] = true;
727  }
728  if (i & 1) /* i == TOMOYO_PATH1_PARENT ||
729  i == TOMOYO_PATH2_PARENT */
730  dput(dentry);
731  }
732 }
733 
745  const struct tomoyo_condition *cond)
746 {
747  u32 i;
748  unsigned long min_v[2] = { 0, 0 };
749  unsigned long max_v[2] = { 0, 0 };
750  const struct tomoyo_condition_element *condp;
751  const struct tomoyo_number_union *numbers_p;
752  const struct tomoyo_name_union *names_p;
753  const struct tomoyo_argv *argv;
754  const struct tomoyo_envp *envp;
755  struct tomoyo_obj_info *obj;
756  u16 condc;
757  u16 argc;
758  u16 envc;
759  struct linux_binprm *bprm = NULL;
760  if (!cond)
761  return true;
762  condc = cond->condc;
763  argc = cond->argc;
764  envc = cond->envc;
765  obj = r->obj;
766  if (r->ee)
767  bprm = r->ee->bprm;
768  if (!bprm && (argc || envc))
769  return false;
770  condp = (struct tomoyo_condition_element *) (cond + 1);
771  numbers_p = (const struct tomoyo_number_union *) (condp + condc);
772  names_p = (const struct tomoyo_name_union *)
773  (numbers_p + cond->numbers_count);
774  argv = (const struct tomoyo_argv *) (names_p + cond->names_count);
775  envp = (const struct tomoyo_envp *) (argv + argc);
776  for (i = 0; i < condc; i++) {
777  const bool match = condp->equals;
778  const u8 left = condp->left;
779  const u8 right = condp->right;
780  bool is_bitop[2] = { false, false };
781  u8 j;
782  condp++;
783  /* Check argv[] and envp[] later. */
784  if (left == TOMOYO_ARGV_ENTRY || left == TOMOYO_ENVP_ENTRY)
785  continue;
786  /* Check string expressions. */
787  if (right == TOMOYO_NAME_UNION) {
788  const struct tomoyo_name_union *ptr = names_p++;
789  switch (left) {
790  struct tomoyo_path_info *symlink;
791  struct tomoyo_execve *ee;
792  struct file *file;
794  symlink = obj ? obj->symlink_target : NULL;
795  if (!symlink ||
796  !tomoyo_compare_name_union(symlink, ptr)
797  == match)
798  goto out;
799  break;
801  ee = r->ee;
802  file = ee ? ee->bprm->file : NULL;
803  if (!tomoyo_scan_exec_realpath(file, ptr,
804  match))
805  goto out;
806  break;
807  }
808  continue;
809  }
810  /* Check numeric or bit-op expressions. */
811  for (j = 0; j < 2; j++) {
812  const u8 index = j ? right : left;
813  unsigned long value = 0;
814  switch (index) {
815  case TOMOYO_TASK_UID:
816  value = from_kuid(&init_user_ns, current_uid());
817  break;
818  case TOMOYO_TASK_EUID:
819  value = from_kuid(&init_user_ns, current_euid());
820  break;
821  case TOMOYO_TASK_SUID:
822  value = from_kuid(&init_user_ns, current_suid());
823  break;
824  case TOMOYO_TASK_FSUID:
825  value = from_kuid(&init_user_ns, current_fsuid());
826  break;
827  case TOMOYO_TASK_GID:
828  value = from_kgid(&init_user_ns, current_gid());
829  break;
830  case TOMOYO_TASK_EGID:
831  value = from_kgid(&init_user_ns, current_egid());
832  break;
833  case TOMOYO_TASK_SGID:
834  value = from_kgid(&init_user_ns, current_sgid());
835  break;
836  case TOMOYO_TASK_FSGID:
837  value = from_kgid(&init_user_ns, current_fsgid());
838  break;
839  case TOMOYO_TASK_PID:
840  value = tomoyo_sys_getpid();
841  break;
842  case TOMOYO_TASK_PPID:
843  value = tomoyo_sys_getppid();
844  break;
846  value = S_IFSOCK;
847  break;
849  value = S_IFLNK;
850  break;
851  case TOMOYO_TYPE_IS_FILE:
852  value = S_IFREG;
853  break;
855  value = S_IFBLK;
856  break;
858  value = S_IFDIR;
859  break;
861  value = S_IFCHR;
862  break;
863  case TOMOYO_TYPE_IS_FIFO:
864  value = S_IFIFO;
865  break;
866  case TOMOYO_MODE_SETUID:
867  value = S_ISUID;
868  break;
869  case TOMOYO_MODE_SETGID:
870  value = S_ISGID;
871  break;
872  case TOMOYO_MODE_STICKY:
873  value = S_ISVTX;
874  break;
876  value = S_IRUSR;
877  break;
879  value = S_IWUSR;
880  break;
882  value = S_IXUSR;
883  break;
885  value = S_IRGRP;
886  break;
888  value = S_IWGRP;
889  break;
891  value = S_IXGRP;
892  break;
894  value = S_IROTH;
895  break;
897  value = S_IWOTH;
898  break;
900  value = S_IXOTH;
901  break;
902  case TOMOYO_EXEC_ARGC:
903  if (!bprm)
904  goto out;
905  value = bprm->argc;
906  break;
907  case TOMOYO_EXEC_ENVC:
908  if (!bprm)
909  goto out;
910  value = bprm->envc;
911  break;
912  case TOMOYO_NUMBER_UNION:
913  /* Fetch values later. */
914  break;
915  default:
916  if (!obj)
917  goto out;
918  if (!obj->validate_done) {
920  obj->validate_done = true;
921  }
922  {
923  u8 stat_index;
924  struct tomoyo_mini_stat *stat;
925  switch (index) {
926  case TOMOYO_PATH1_UID:
927  case TOMOYO_PATH1_GID:
928  case TOMOYO_PATH1_INO:
929  case TOMOYO_PATH1_MAJOR:
930  case TOMOYO_PATH1_MINOR:
931  case TOMOYO_PATH1_TYPE:
934  case TOMOYO_PATH1_PERM:
935  stat_index = TOMOYO_PATH1;
936  break;
937  case TOMOYO_PATH2_UID:
938  case TOMOYO_PATH2_GID:
939  case TOMOYO_PATH2_INO:
940  case TOMOYO_PATH2_MAJOR:
941  case TOMOYO_PATH2_MINOR:
942  case TOMOYO_PATH2_TYPE:
945  case TOMOYO_PATH2_PERM:
946  stat_index = TOMOYO_PATH2;
947  break;
952  stat_index =
954  break;
959  stat_index =
961  break;
962  default:
963  goto out;
964  }
965  if (!obj->stat_valid[stat_index])
966  goto out;
967  stat = &obj->stat[stat_index];
968  switch (index) {
969  case TOMOYO_PATH1_UID:
970  case TOMOYO_PATH2_UID:
973  value = from_kuid(&init_user_ns, stat->uid);
974  break;
975  case TOMOYO_PATH1_GID:
976  case TOMOYO_PATH2_GID:
979  value = from_kgid(&init_user_ns, stat->gid);
980  break;
981  case TOMOYO_PATH1_INO:
982  case TOMOYO_PATH2_INO:
985  value = stat->ino;
986  break;
987  case TOMOYO_PATH1_MAJOR:
988  case TOMOYO_PATH2_MAJOR:
989  value = MAJOR(stat->dev);
990  break;
991  case TOMOYO_PATH1_MINOR:
992  case TOMOYO_PATH2_MINOR:
993  value = MINOR(stat->dev);
994  break;
995  case TOMOYO_PATH1_TYPE:
996  case TOMOYO_PATH2_TYPE:
997  value = stat->mode & S_IFMT;
998  break;
1001  value = MAJOR(stat->rdev);
1002  break;
1005  value = MINOR(stat->rdev);
1006  break;
1007  case TOMOYO_PATH1_PERM:
1008  case TOMOYO_PATH2_PERM:
1011  value = stat->mode & S_IALLUGO;
1012  break;
1013  }
1014  }
1015  break;
1016  }
1017  max_v[j] = value;
1018  min_v[j] = value;
1019  switch (index) {
1020  case TOMOYO_MODE_SETUID:
1021  case TOMOYO_MODE_SETGID:
1022  case TOMOYO_MODE_STICKY:
1032  is_bitop[j] = true;
1033  }
1034  }
1035  if (left == TOMOYO_NUMBER_UNION) {
1036  /* Fetch values now. */
1037  const struct tomoyo_number_union *ptr = numbers_p++;
1038  min_v[0] = ptr->values[0];
1039  max_v[0] = ptr->values[1];
1040  }
1041  if (right == TOMOYO_NUMBER_UNION) {
1042  /* Fetch values now. */
1043  const struct tomoyo_number_union *ptr = numbers_p++;
1044  if (ptr->group) {
1045  if (tomoyo_number_matches_group(min_v[0],
1046  max_v[0],
1047  ptr->group)
1048  == match)
1049  continue;
1050  } else {
1051  if ((min_v[0] <= ptr->values[1] &&
1052  max_v[0] >= ptr->values[0]) == match)
1053  continue;
1054  }
1055  goto out;
1056  }
1057  /*
1058  * Bit operation is valid only when counterpart value
1059  * represents permission.
1060  */
1061  if (is_bitop[0] && is_bitop[1]) {
1062  goto out;
1063  } else if (is_bitop[0]) {
1064  switch (right) {
1065  case TOMOYO_PATH1_PERM:
1067  case TOMOYO_PATH2_PERM:
1069  if (!(max_v[0] & max_v[1]) == !match)
1070  continue;
1071  }
1072  goto out;
1073  } else if (is_bitop[1]) {
1074  switch (left) {
1075  case TOMOYO_PATH1_PERM:
1077  case TOMOYO_PATH2_PERM:
1079  if (!(max_v[0] & max_v[1]) == !match)
1080  continue;
1081  }
1082  goto out;
1083  }
1084  /* Normal value range comparison. */
1085  if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match)
1086  continue;
1087 out:
1088  return false;
1089  }
1090  /* Check argv[] and envp[] now. */
1091  if (r->ee && (argc || envc))
1092  return tomoyo_scan_bprm(r->ee, argc, argv, envc, envp);
1093  return true;
1094 }