0001
0002
0003
0004
0005
0006
0007
0008 #include "common.h"
0009 #include <linux/slab.h>
0010
0011
0012 LIST_HEAD(tomoyo_condition_list);
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 static bool tomoyo_argv(const unsigned int index, const char *arg_ptr,
0026 const int argc, const struct tomoyo_argv *argv,
0027 u8 *checked)
0028 {
0029 int i;
0030 struct tomoyo_path_info arg;
0031
0032 arg.name = arg_ptr;
0033 for (i = 0; i < argc; argv++, checked++, i++) {
0034 bool result;
0035
0036 if (index != argv->index)
0037 continue;
0038 *checked = 1;
0039 tomoyo_fill_path_info(&arg);
0040 result = tomoyo_path_matches_pattern(&arg, argv->value);
0041 if (argv->is_not)
0042 result = !result;
0043 if (!result)
0044 return false;
0045 }
0046 return true;
0047 }
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060 static bool tomoyo_envp(const char *env_name, const char *env_value,
0061 const int envc, const struct tomoyo_envp *envp,
0062 u8 *checked)
0063 {
0064 int i;
0065 struct tomoyo_path_info name;
0066 struct tomoyo_path_info value;
0067
0068 name.name = env_name;
0069 tomoyo_fill_path_info(&name);
0070 value.name = env_value;
0071 tomoyo_fill_path_info(&value);
0072 for (i = 0; i < envc; envp++, checked++, i++) {
0073 bool result;
0074
0075 if (!tomoyo_path_matches_pattern(&name, envp->name))
0076 continue;
0077 *checked = 1;
0078 if (envp->value) {
0079 result = tomoyo_path_matches_pattern(&value,
0080 envp->value);
0081 if (envp->is_not)
0082 result = !result;
0083 } else {
0084 result = true;
0085 if (!envp->is_not)
0086 result = !result;
0087 }
0088 if (!result)
0089 return false;
0090 }
0091 return true;
0092 }
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105 static bool tomoyo_scan_bprm(struct tomoyo_execve *ee,
0106 const u16 argc, const struct tomoyo_argv *argv,
0107 const u16 envc, const struct tomoyo_envp *envp)
0108 {
0109 struct linux_binprm *bprm = ee->bprm;
0110 struct tomoyo_page_dump *dump = &ee->dump;
0111 char *arg_ptr = ee->tmp;
0112 int arg_len = 0;
0113 unsigned long pos = bprm->p;
0114 int offset = pos % PAGE_SIZE;
0115 int argv_count = bprm->argc;
0116 int envp_count = bprm->envc;
0117 bool result = true;
0118 u8 local_checked[32];
0119 u8 *checked;
0120
0121 if (argc + envc <= sizeof(local_checked)) {
0122 checked = local_checked;
0123 memset(local_checked, 0, sizeof(local_checked));
0124 } else {
0125 checked = kzalloc(argc + envc, GFP_NOFS);
0126 if (!checked)
0127 return false;
0128 }
0129 while (argv_count || envp_count) {
0130 if (!tomoyo_dump_page(bprm, pos, dump)) {
0131 result = false;
0132 goto out;
0133 }
0134 pos += PAGE_SIZE - offset;
0135 while (offset < PAGE_SIZE) {
0136
0137 const char *kaddr = dump->data;
0138 const unsigned char c = kaddr[offset++];
0139
0140 if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) {
0141 if (c == '\\') {
0142 arg_ptr[arg_len++] = '\\';
0143 arg_ptr[arg_len++] = '\\';
0144 } else if (c > ' ' && c < 127) {
0145 arg_ptr[arg_len++] = c;
0146 } else {
0147 arg_ptr[arg_len++] = '\\';
0148 arg_ptr[arg_len++] = (c >> 6) + '0';
0149 arg_ptr[arg_len++] =
0150 ((c >> 3) & 7) + '0';
0151 arg_ptr[arg_len++] = (c & 7) + '0';
0152 }
0153 } else {
0154 arg_ptr[arg_len] = '\0';
0155 }
0156 if (c)
0157 continue;
0158
0159 if (argv_count) {
0160 if (!tomoyo_argv(bprm->argc - argv_count,
0161 arg_ptr, argc, argv,
0162 checked)) {
0163 result = false;
0164 break;
0165 }
0166 argv_count--;
0167 } else if (envp_count) {
0168 char *cp = strchr(arg_ptr, '=');
0169
0170 if (cp) {
0171 *cp = '\0';
0172 if (!tomoyo_envp(arg_ptr, cp + 1,
0173 envc, envp,
0174 checked + argc)) {
0175 result = false;
0176 break;
0177 }
0178 }
0179 envp_count--;
0180 } else {
0181 break;
0182 }
0183 arg_len = 0;
0184 }
0185 offset = 0;
0186 if (!result)
0187 break;
0188 }
0189 out:
0190 if (result) {
0191 int i;
0192
0193
0194 for (i = 0; i < argc; i++) {
0195 if (checked[i])
0196 continue;
0197
0198
0199
0200
0201 if (argv[i].is_not)
0202 continue;
0203 result = false;
0204 break;
0205 }
0206 for (i = 0; i < envc; envp++, i++) {
0207 if (checked[argc + i])
0208 continue;
0209
0210
0211
0212
0213 if ((!envp->value && !envp->is_not) ||
0214 (envp->value && envp->is_not))
0215 continue;
0216 result = false;
0217 break;
0218 }
0219 }
0220 if (checked != local_checked)
0221 kfree(checked);
0222 return result;
0223 }
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234 static bool tomoyo_scan_exec_realpath(struct file *file,
0235 const struct tomoyo_name_union *ptr,
0236 const bool match)
0237 {
0238 bool result;
0239 struct tomoyo_path_info exe;
0240
0241 if (!file)
0242 return false;
0243 exe.name = tomoyo_realpath_from_path(&file->f_path);
0244 if (!exe.name)
0245 return false;
0246 tomoyo_fill_path_info(&exe);
0247 result = tomoyo_compare_name_union(&exe, ptr);
0248 kfree(exe.name);
0249 return result == match;
0250 }
0251
0252
0253
0254
0255
0256
0257
0258
0259 static const struct tomoyo_path_info *tomoyo_get_dqword(char *start)
0260 {
0261 char *cp = start + strlen(start) - 1;
0262
0263 if (cp == start || *start++ != '"' || *cp != '"')
0264 return NULL;
0265 *cp = '\0';
0266 if (*start && !tomoyo_correct_word(start))
0267 return NULL;
0268 return tomoyo_get_name(start);
0269 }
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279 static bool tomoyo_parse_name_union_quoted(struct tomoyo_acl_param *param,
0280 struct tomoyo_name_union *ptr)
0281 {
0282 char *filename = param->data;
0283
0284 if (*filename == '@')
0285 return tomoyo_parse_name_union(param, ptr);
0286 ptr->filename = tomoyo_get_dqword(filename);
0287 return ptr->filename != NULL;
0288 }
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299 static bool tomoyo_parse_argv(char *left, char *right,
0300 struct tomoyo_argv *argv)
0301 {
0302 if (tomoyo_parse_ulong(&argv->index, &left) !=
0303 TOMOYO_VALUE_TYPE_DECIMAL || *left++ != ']' || *left)
0304 return false;
0305 argv->value = tomoyo_get_dqword(right);
0306 return argv->value != NULL;
0307 }
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318 static bool tomoyo_parse_envp(char *left, char *right,
0319 struct tomoyo_envp *envp)
0320 {
0321 const struct tomoyo_path_info *name;
0322 const struct tomoyo_path_info *value;
0323 char *cp = left + strlen(left) - 1;
0324
0325 if (*cp-- != ']' || *cp != '"')
0326 goto out;
0327 *cp = '\0';
0328 if (!tomoyo_correct_word(left))
0329 goto out;
0330 name = tomoyo_get_name(left);
0331 if (!name)
0332 goto out;
0333 if (!strcmp(right, "NULL")) {
0334 value = NULL;
0335 } else {
0336 value = tomoyo_get_dqword(right);
0337 if (!value) {
0338 tomoyo_put_name(name);
0339 goto out;
0340 }
0341 }
0342 envp->name = name;
0343 envp->value = value;
0344 return true;
0345 out:
0346 return false;
0347 }
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357 static inline bool tomoyo_same_condition(const struct tomoyo_condition *a,
0358 const struct tomoyo_condition *b)
0359 {
0360 return a->size == b->size && a->condc == b->condc &&
0361 a->numbers_count == b->numbers_count &&
0362 a->names_count == b->names_count &&
0363 a->argc == b->argc && a->envc == b->envc &&
0364 a->grant_log == b->grant_log && a->transit == b->transit &&
0365 !memcmp(a + 1, b + 1, a->size - sizeof(*a));
0366 }
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376 static u8 tomoyo_condition_type(const char *word)
0377 {
0378 u8 i;
0379
0380 for (i = 0; i < TOMOYO_MAX_CONDITION_KEYWORD; i++) {
0381 if (!strcmp(word, tomoyo_condition_keyword[i]))
0382 break;
0383 }
0384 return i;
0385 }
0386
0387
0388
0389
0390 #ifdef DEBUG_CONDITION
0391 #define dprintk printk
0392 #else
0393 #define dprintk(...) do { } while (0)
0394 #endif
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406 static struct tomoyo_condition *tomoyo_commit_condition
0407 (struct tomoyo_condition *entry)
0408 {
0409 struct tomoyo_condition *ptr;
0410 bool found = false;
0411
0412 if (mutex_lock_interruptible(&tomoyo_policy_lock)) {
0413 dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
0414 ptr = NULL;
0415 found = true;
0416 goto out;
0417 }
0418 list_for_each_entry(ptr, &tomoyo_condition_list, head.list) {
0419 if (!tomoyo_same_condition(ptr, entry) ||
0420 atomic_read(&ptr->head.users) == TOMOYO_GC_IN_PROGRESS)
0421 continue;
0422
0423 atomic_inc(&ptr->head.users);
0424 found = true;
0425 break;
0426 }
0427 if (!found) {
0428 if (tomoyo_memory_ok(entry)) {
0429 atomic_set(&entry->head.users, 1);
0430 list_add(&entry->head.list, &tomoyo_condition_list);
0431 } else {
0432 found = true;
0433 ptr = NULL;
0434 }
0435 }
0436 mutex_unlock(&tomoyo_policy_lock);
0437 out:
0438 if (found) {
0439 tomoyo_del_condition(&entry->head.list);
0440 kfree(entry);
0441 entry = ptr;
0442 }
0443 return entry;
0444 }
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454 static char *tomoyo_get_transit_preference(struct tomoyo_acl_param *param,
0455 struct tomoyo_condition *e)
0456 {
0457 char * const pos = param->data;
0458 bool flag;
0459
0460 if (*pos == '<') {
0461 e->transit = tomoyo_get_domainname(param);
0462 goto done;
0463 }
0464 {
0465 char *cp = strchr(pos, ' ');
0466
0467 if (cp)
0468 *cp = '\0';
0469 flag = tomoyo_correct_path(pos) || !strcmp(pos, "keep") ||
0470 !strcmp(pos, "initialize") || !strcmp(pos, "reset") ||
0471 !strcmp(pos, "child") || !strcmp(pos, "parent");
0472 if (cp)
0473 *cp = ' ';
0474 }
0475 if (!flag)
0476 return pos;
0477 e->transit = tomoyo_get_name(tomoyo_read_token(param));
0478 done:
0479 if (e->transit)
0480 return param->data;
0481
0482
0483
0484
0485 return "/";
0486 }
0487
0488
0489
0490
0491
0492
0493
0494
0495 struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param)
0496 {
0497 struct tomoyo_condition *entry = NULL;
0498 struct tomoyo_condition_element *condp = NULL;
0499 struct tomoyo_number_union *numbers_p = NULL;
0500 struct tomoyo_name_union *names_p = NULL;
0501 struct tomoyo_argv *argv = NULL;
0502 struct tomoyo_envp *envp = NULL;
0503 struct tomoyo_condition e = { };
0504 char * const start_of_string =
0505 tomoyo_get_transit_preference(param, &e);
0506 char * const end_of_string = start_of_string + strlen(start_of_string);
0507 char *pos;
0508
0509 rerun:
0510 pos = start_of_string;
0511 while (1) {
0512 u8 left = -1;
0513 u8 right = -1;
0514 char *left_word = pos;
0515 char *cp;
0516 char *right_word;
0517 bool is_not;
0518
0519 if (!*left_word)
0520 break;
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531 cp = strchr(pos, ' ');
0532 if (cp) {
0533 *cp = '\0';
0534 pos = cp + 1;
0535 } else {
0536 pos = "";
0537 }
0538 right_word = strchr(left_word, '=');
0539 if (!right_word || right_word == left_word)
0540 goto out;
0541 is_not = *(right_word - 1) == '!';
0542 if (is_not)
0543 *(right_word++ - 1) = '\0';
0544 else if (*(right_word + 1) != '=')
0545 *right_word++ = '\0';
0546 else
0547 goto out;
0548 dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word,
0549 is_not ? "!" : "", right_word);
0550 if (!strcmp(left_word, "grant_log")) {
0551 if (entry) {
0552 if (is_not ||
0553 entry->grant_log != TOMOYO_GRANTLOG_AUTO)
0554 goto out;
0555 else if (!strcmp(right_word, "yes"))
0556 entry->grant_log = TOMOYO_GRANTLOG_YES;
0557 else if (!strcmp(right_word, "no"))
0558 entry->grant_log = TOMOYO_GRANTLOG_NO;
0559 else
0560 goto out;
0561 }
0562 continue;
0563 }
0564 if (!strncmp(left_word, "exec.argv[", 10)) {
0565 if (!argv) {
0566 e.argc++;
0567 e.condc++;
0568 } else {
0569 e.argc--;
0570 e.condc--;
0571 left = TOMOYO_ARGV_ENTRY;
0572 argv->is_not = is_not;
0573 if (!tomoyo_parse_argv(left_word + 10,
0574 right_word, argv++))
0575 goto out;
0576 }
0577 goto store_value;
0578 }
0579 if (!strncmp(left_word, "exec.envp[\"", 11)) {
0580 if (!envp) {
0581 e.envc++;
0582 e.condc++;
0583 } else {
0584 e.envc--;
0585 e.condc--;
0586 left = TOMOYO_ENVP_ENTRY;
0587 envp->is_not = is_not;
0588 if (!tomoyo_parse_envp(left_word + 11,
0589 right_word, envp++))
0590 goto out;
0591 }
0592 goto store_value;
0593 }
0594 left = tomoyo_condition_type(left_word);
0595 dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word,
0596 left);
0597 if (left == TOMOYO_MAX_CONDITION_KEYWORD) {
0598 if (!numbers_p) {
0599 e.numbers_count++;
0600 } else {
0601 e.numbers_count--;
0602 left = TOMOYO_NUMBER_UNION;
0603 param->data = left_word;
0604 if (*left_word == '@' ||
0605 !tomoyo_parse_number_union(param,
0606 numbers_p++))
0607 goto out;
0608 }
0609 }
0610 if (!condp)
0611 e.condc++;
0612 else
0613 e.condc--;
0614 if (left == TOMOYO_EXEC_REALPATH ||
0615 left == TOMOYO_SYMLINK_TARGET) {
0616 if (!names_p) {
0617 e.names_count++;
0618 } else {
0619 e.names_count--;
0620 right = TOMOYO_NAME_UNION;
0621 param->data = right_word;
0622 if (!tomoyo_parse_name_union_quoted(param,
0623 names_p++))
0624 goto out;
0625 }
0626 goto store_value;
0627 }
0628 right = tomoyo_condition_type(right_word);
0629 if (right == TOMOYO_MAX_CONDITION_KEYWORD) {
0630 if (!numbers_p) {
0631 e.numbers_count++;
0632 } else {
0633 e.numbers_count--;
0634 right = TOMOYO_NUMBER_UNION;
0635 param->data = right_word;
0636 if (!tomoyo_parse_number_union(param,
0637 numbers_p++))
0638 goto out;
0639 }
0640 }
0641 store_value:
0642 if (!condp) {
0643 dprintk(KERN_WARNING "%u: dry_run left=%u right=%u match=%u\n",
0644 __LINE__, left, right, !is_not);
0645 continue;
0646 }
0647 condp->left = left;
0648 condp->right = right;
0649 condp->equals = !is_not;
0650 dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
0651 __LINE__, condp->left, condp->right,
0652 condp->equals);
0653 condp++;
0654 }
0655 dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n",
0656 __LINE__, e.condc, e.numbers_count, e.names_count, e.argc,
0657 e.envc);
0658 if (entry) {
0659 BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc |
0660 e.condc);
0661 return tomoyo_commit_condition(entry);
0662 }
0663 e.size = sizeof(*entry)
0664 + e.condc * sizeof(struct tomoyo_condition_element)
0665 + e.numbers_count * sizeof(struct tomoyo_number_union)
0666 + e.names_count * sizeof(struct tomoyo_name_union)
0667 + e.argc * sizeof(struct tomoyo_argv)
0668 + e.envc * sizeof(struct tomoyo_envp);
0669 entry = kzalloc(e.size, GFP_NOFS);
0670 if (!entry)
0671 goto out2;
0672 *entry = e;
0673 e.transit = NULL;
0674 condp = (struct tomoyo_condition_element *) (entry + 1);
0675 numbers_p = (struct tomoyo_number_union *) (condp + e.condc);
0676 names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count);
0677 argv = (struct tomoyo_argv *) (names_p + e.names_count);
0678 envp = (struct tomoyo_envp *) (argv + e.argc);
0679 {
0680 bool flag = false;
0681
0682 for (pos = start_of_string; pos < end_of_string; pos++) {
0683 if (*pos)
0684 continue;
0685 if (flag)
0686 *pos = ' ';
0687 else if (*(pos + 1) == '=')
0688 *pos = '!';
0689 else
0690 *pos = '=';
0691 flag = !flag;
0692 }
0693 }
0694 goto rerun;
0695 out:
0696 dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
0697 if (entry) {
0698 tomoyo_del_condition(&entry->head.list);
0699 kfree(entry);
0700 }
0701 out2:
0702 tomoyo_put_name(e.transit);
0703 return NULL;
0704 }
0705
0706
0707
0708
0709
0710
0711
0712
0713 void tomoyo_get_attributes(struct tomoyo_obj_info *obj)
0714 {
0715 u8 i;
0716 struct dentry *dentry = NULL;
0717
0718 for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) {
0719 struct inode *inode;
0720
0721 switch (i) {
0722 case TOMOYO_PATH1:
0723 dentry = obj->path1.dentry;
0724 if (!dentry)
0725 continue;
0726 break;
0727 case TOMOYO_PATH2:
0728 dentry = obj->path2.dentry;
0729 if (!dentry)
0730 continue;
0731 break;
0732 default:
0733 if (!dentry)
0734 continue;
0735 dentry = dget_parent(dentry);
0736 break;
0737 }
0738 inode = d_backing_inode(dentry);
0739 if (inode) {
0740 struct tomoyo_mini_stat *stat = &obj->stat[i];
0741
0742 stat->uid = inode->i_uid;
0743 stat->gid = inode->i_gid;
0744 stat->ino = inode->i_ino;
0745 stat->mode = inode->i_mode;
0746 stat->dev = inode->i_sb->s_dev;
0747 stat->rdev = inode->i_rdev;
0748 obj->stat_valid[i] = true;
0749 }
0750 if (i & 1)
0751 dput(dentry);
0752 }
0753 }
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765 bool tomoyo_condition(struct tomoyo_request_info *r,
0766 const struct tomoyo_condition *cond)
0767 {
0768 u32 i;
0769 unsigned long min_v[2] = { 0, 0 };
0770 unsigned long max_v[2] = { 0, 0 };
0771 const struct tomoyo_condition_element *condp;
0772 const struct tomoyo_number_union *numbers_p;
0773 const struct tomoyo_name_union *names_p;
0774 const struct tomoyo_argv *argv;
0775 const struct tomoyo_envp *envp;
0776 struct tomoyo_obj_info *obj;
0777 u16 condc;
0778 u16 argc;
0779 u16 envc;
0780 struct linux_binprm *bprm = NULL;
0781
0782 if (!cond)
0783 return true;
0784 condc = cond->condc;
0785 argc = cond->argc;
0786 envc = cond->envc;
0787 obj = r->obj;
0788 if (r->ee)
0789 bprm = r->ee->bprm;
0790 if (!bprm && (argc || envc))
0791 return false;
0792 condp = (struct tomoyo_condition_element *) (cond + 1);
0793 numbers_p = (const struct tomoyo_number_union *) (condp + condc);
0794 names_p = (const struct tomoyo_name_union *)
0795 (numbers_p + cond->numbers_count);
0796 argv = (const struct tomoyo_argv *) (names_p + cond->names_count);
0797 envp = (const struct tomoyo_envp *) (argv + argc);
0798 for (i = 0; i < condc; i++) {
0799 const bool match = condp->equals;
0800 const u8 left = condp->left;
0801 const u8 right = condp->right;
0802 bool is_bitop[2] = { false, false };
0803 u8 j;
0804
0805 condp++;
0806
0807 if (left == TOMOYO_ARGV_ENTRY || left == TOMOYO_ENVP_ENTRY)
0808 continue;
0809
0810 if (right == TOMOYO_NAME_UNION) {
0811 const struct tomoyo_name_union *ptr = names_p++;
0812 struct tomoyo_path_info *symlink;
0813 struct tomoyo_execve *ee;
0814 struct file *file;
0815
0816 switch (left) {
0817 case TOMOYO_SYMLINK_TARGET:
0818 symlink = obj ? obj->symlink_target : NULL;
0819 if (!symlink ||
0820 !tomoyo_compare_name_union(symlink, ptr)
0821 == match)
0822 goto out;
0823 break;
0824 case TOMOYO_EXEC_REALPATH:
0825 ee = r->ee;
0826 file = ee ? ee->bprm->file : NULL;
0827 if (!tomoyo_scan_exec_realpath(file, ptr,
0828 match))
0829 goto out;
0830 break;
0831 }
0832 continue;
0833 }
0834
0835 for (j = 0; j < 2; j++) {
0836 const u8 index = j ? right : left;
0837 unsigned long value = 0;
0838
0839 switch (index) {
0840 case TOMOYO_TASK_UID:
0841 value = from_kuid(&init_user_ns, current_uid());
0842 break;
0843 case TOMOYO_TASK_EUID:
0844 value = from_kuid(&init_user_ns, current_euid());
0845 break;
0846 case TOMOYO_TASK_SUID:
0847 value = from_kuid(&init_user_ns, current_suid());
0848 break;
0849 case TOMOYO_TASK_FSUID:
0850 value = from_kuid(&init_user_ns, current_fsuid());
0851 break;
0852 case TOMOYO_TASK_GID:
0853 value = from_kgid(&init_user_ns, current_gid());
0854 break;
0855 case TOMOYO_TASK_EGID:
0856 value = from_kgid(&init_user_ns, current_egid());
0857 break;
0858 case TOMOYO_TASK_SGID:
0859 value = from_kgid(&init_user_ns, current_sgid());
0860 break;
0861 case TOMOYO_TASK_FSGID:
0862 value = from_kgid(&init_user_ns, current_fsgid());
0863 break;
0864 case TOMOYO_TASK_PID:
0865 value = tomoyo_sys_getpid();
0866 break;
0867 case TOMOYO_TASK_PPID:
0868 value = tomoyo_sys_getppid();
0869 break;
0870 case TOMOYO_TYPE_IS_SOCKET:
0871 value = S_IFSOCK;
0872 break;
0873 case TOMOYO_TYPE_IS_SYMLINK:
0874 value = S_IFLNK;
0875 break;
0876 case TOMOYO_TYPE_IS_FILE:
0877 value = S_IFREG;
0878 break;
0879 case TOMOYO_TYPE_IS_BLOCK_DEV:
0880 value = S_IFBLK;
0881 break;
0882 case TOMOYO_TYPE_IS_DIRECTORY:
0883 value = S_IFDIR;
0884 break;
0885 case TOMOYO_TYPE_IS_CHAR_DEV:
0886 value = S_IFCHR;
0887 break;
0888 case TOMOYO_TYPE_IS_FIFO:
0889 value = S_IFIFO;
0890 break;
0891 case TOMOYO_MODE_SETUID:
0892 value = S_ISUID;
0893 break;
0894 case TOMOYO_MODE_SETGID:
0895 value = S_ISGID;
0896 break;
0897 case TOMOYO_MODE_STICKY:
0898 value = S_ISVTX;
0899 break;
0900 case TOMOYO_MODE_OWNER_READ:
0901 value = 0400;
0902 break;
0903 case TOMOYO_MODE_OWNER_WRITE:
0904 value = 0200;
0905 break;
0906 case TOMOYO_MODE_OWNER_EXECUTE:
0907 value = 0100;
0908 break;
0909 case TOMOYO_MODE_GROUP_READ:
0910 value = 0040;
0911 break;
0912 case TOMOYO_MODE_GROUP_WRITE:
0913 value = 0020;
0914 break;
0915 case TOMOYO_MODE_GROUP_EXECUTE:
0916 value = 0010;
0917 break;
0918 case TOMOYO_MODE_OTHERS_READ:
0919 value = 0004;
0920 break;
0921 case TOMOYO_MODE_OTHERS_WRITE:
0922 value = 0002;
0923 break;
0924 case TOMOYO_MODE_OTHERS_EXECUTE:
0925 value = 0001;
0926 break;
0927 case TOMOYO_EXEC_ARGC:
0928 if (!bprm)
0929 goto out;
0930 value = bprm->argc;
0931 break;
0932 case TOMOYO_EXEC_ENVC:
0933 if (!bprm)
0934 goto out;
0935 value = bprm->envc;
0936 break;
0937 case TOMOYO_NUMBER_UNION:
0938
0939 break;
0940 default:
0941 if (!obj)
0942 goto out;
0943 if (!obj->validate_done) {
0944 tomoyo_get_attributes(obj);
0945 obj->validate_done = true;
0946 }
0947 {
0948 u8 stat_index;
0949 struct tomoyo_mini_stat *stat;
0950
0951 switch (index) {
0952 case TOMOYO_PATH1_UID:
0953 case TOMOYO_PATH1_GID:
0954 case TOMOYO_PATH1_INO:
0955 case TOMOYO_PATH1_MAJOR:
0956 case TOMOYO_PATH1_MINOR:
0957 case TOMOYO_PATH1_TYPE:
0958 case TOMOYO_PATH1_DEV_MAJOR:
0959 case TOMOYO_PATH1_DEV_MINOR:
0960 case TOMOYO_PATH1_PERM:
0961 stat_index = TOMOYO_PATH1;
0962 break;
0963 case TOMOYO_PATH2_UID:
0964 case TOMOYO_PATH2_GID:
0965 case TOMOYO_PATH2_INO:
0966 case TOMOYO_PATH2_MAJOR:
0967 case TOMOYO_PATH2_MINOR:
0968 case TOMOYO_PATH2_TYPE:
0969 case TOMOYO_PATH2_DEV_MAJOR:
0970 case TOMOYO_PATH2_DEV_MINOR:
0971 case TOMOYO_PATH2_PERM:
0972 stat_index = TOMOYO_PATH2;
0973 break;
0974 case TOMOYO_PATH1_PARENT_UID:
0975 case TOMOYO_PATH1_PARENT_GID:
0976 case TOMOYO_PATH1_PARENT_INO:
0977 case TOMOYO_PATH1_PARENT_PERM:
0978 stat_index =
0979 TOMOYO_PATH1_PARENT;
0980 break;
0981 case TOMOYO_PATH2_PARENT_UID:
0982 case TOMOYO_PATH2_PARENT_GID:
0983 case TOMOYO_PATH2_PARENT_INO:
0984 case TOMOYO_PATH2_PARENT_PERM:
0985 stat_index =
0986 TOMOYO_PATH2_PARENT;
0987 break;
0988 default:
0989 goto out;
0990 }
0991 if (!obj->stat_valid[stat_index])
0992 goto out;
0993 stat = &obj->stat[stat_index];
0994 switch (index) {
0995 case TOMOYO_PATH1_UID:
0996 case TOMOYO_PATH2_UID:
0997 case TOMOYO_PATH1_PARENT_UID:
0998 case TOMOYO_PATH2_PARENT_UID:
0999 value = from_kuid(&init_user_ns, stat->uid);
1000 break;
1001 case TOMOYO_PATH1_GID:
1002 case TOMOYO_PATH2_GID:
1003 case TOMOYO_PATH1_PARENT_GID:
1004 case TOMOYO_PATH2_PARENT_GID:
1005 value = from_kgid(&init_user_ns, stat->gid);
1006 break;
1007 case TOMOYO_PATH1_INO:
1008 case TOMOYO_PATH2_INO:
1009 case TOMOYO_PATH1_PARENT_INO:
1010 case TOMOYO_PATH2_PARENT_INO:
1011 value = stat->ino;
1012 break;
1013 case TOMOYO_PATH1_MAJOR:
1014 case TOMOYO_PATH2_MAJOR:
1015 value = MAJOR(stat->dev);
1016 break;
1017 case TOMOYO_PATH1_MINOR:
1018 case TOMOYO_PATH2_MINOR:
1019 value = MINOR(stat->dev);
1020 break;
1021 case TOMOYO_PATH1_TYPE:
1022 case TOMOYO_PATH2_TYPE:
1023 value = stat->mode & S_IFMT;
1024 break;
1025 case TOMOYO_PATH1_DEV_MAJOR:
1026 case TOMOYO_PATH2_DEV_MAJOR:
1027 value = MAJOR(stat->rdev);
1028 break;
1029 case TOMOYO_PATH1_DEV_MINOR:
1030 case TOMOYO_PATH2_DEV_MINOR:
1031 value = MINOR(stat->rdev);
1032 break;
1033 case TOMOYO_PATH1_PERM:
1034 case TOMOYO_PATH2_PERM:
1035 case TOMOYO_PATH1_PARENT_PERM:
1036 case TOMOYO_PATH2_PARENT_PERM:
1037 value = stat->mode & S_IALLUGO;
1038 break;
1039 }
1040 }
1041 break;
1042 }
1043 max_v[j] = value;
1044 min_v[j] = value;
1045 switch (index) {
1046 case TOMOYO_MODE_SETUID:
1047 case TOMOYO_MODE_SETGID:
1048 case TOMOYO_MODE_STICKY:
1049 case TOMOYO_MODE_OWNER_READ:
1050 case TOMOYO_MODE_OWNER_WRITE:
1051 case TOMOYO_MODE_OWNER_EXECUTE:
1052 case TOMOYO_MODE_GROUP_READ:
1053 case TOMOYO_MODE_GROUP_WRITE:
1054 case TOMOYO_MODE_GROUP_EXECUTE:
1055 case TOMOYO_MODE_OTHERS_READ:
1056 case TOMOYO_MODE_OTHERS_WRITE:
1057 case TOMOYO_MODE_OTHERS_EXECUTE:
1058 is_bitop[j] = true;
1059 }
1060 }
1061 if (left == TOMOYO_NUMBER_UNION) {
1062
1063 const struct tomoyo_number_union *ptr = numbers_p++;
1064
1065 min_v[0] = ptr->values[0];
1066 max_v[0] = ptr->values[1];
1067 }
1068 if (right == TOMOYO_NUMBER_UNION) {
1069
1070 const struct tomoyo_number_union *ptr = numbers_p++;
1071
1072 if (ptr->group) {
1073 if (tomoyo_number_matches_group(min_v[0],
1074 max_v[0],
1075 ptr->group)
1076 == match)
1077 continue;
1078 } else {
1079 if ((min_v[0] <= ptr->values[1] &&
1080 max_v[0] >= ptr->values[0]) == match)
1081 continue;
1082 }
1083 goto out;
1084 }
1085
1086
1087
1088
1089 if (is_bitop[0] && is_bitop[1]) {
1090 goto out;
1091 } else if (is_bitop[0]) {
1092 switch (right) {
1093 case TOMOYO_PATH1_PERM:
1094 case TOMOYO_PATH1_PARENT_PERM:
1095 case TOMOYO_PATH2_PERM:
1096 case TOMOYO_PATH2_PARENT_PERM:
1097 if (!(max_v[0] & max_v[1]) == !match)
1098 continue;
1099 }
1100 goto out;
1101 } else if (is_bitop[1]) {
1102 switch (left) {
1103 case TOMOYO_PATH1_PERM:
1104 case TOMOYO_PATH1_PARENT_PERM:
1105 case TOMOYO_PATH2_PERM:
1106 case TOMOYO_PATH2_PARENT_PERM:
1107 if (!(max_v[0] & max_v[1]) == !match)
1108 continue;
1109 }
1110 goto out;
1111 }
1112
1113 if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match)
1114 continue;
1115 out:
1116 return false;
1117 }
1118
1119 if (r->ee && (argc || envc))
1120 return tomoyo_scan_bprm(r->ee, argc, argv, envc, envp);
1121 return true;
1122 }