Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * security/tomoyo/condition.c
0004  *
0005  * Copyright (C) 2005-2011  NTT DATA CORPORATION
0006  */
0007 
0008 #include "common.h"
0009 #include <linux/slab.h>
0010 
0011 /* List of "struct tomoyo_condition". */
0012 LIST_HEAD(tomoyo_condition_list);
0013 
0014 /**
0015  * tomoyo_argv - Check argv[] in "struct linux_binbrm".
0016  *
0017  * @index:   Index number of @arg_ptr.
0018  * @arg_ptr: Contents of argv[@index].
0019  * @argc:    Length of @argv.
0020  * @argv:    Pointer to "struct tomoyo_argv".
0021  * @checked: Set to true if @argv[@index] was found.
0022  *
0023  * Returns true on success, false otherwise.
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  * tomoyo_envp - Check envp[] in "struct linux_binbrm".
0051  *
0052  * @env_name:  The name of environment variable.
0053  * @env_value: The value of environment variable.
0054  * @envc:      Length of @envp.
0055  * @envp:      Pointer to "struct tomoyo_envp".
0056  * @checked:   Set to true if @envp[@env_name] was found.
0057  *
0058  * Returns true on success, false otherwise.
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  * tomoyo_scan_bprm - Scan "struct linux_binprm".
0096  *
0097  * @ee:   Pointer to "struct tomoyo_execve".
0098  * @argc: Length of @argc.
0099  * @argv: Pointer to "struct tomoyo_argv".
0100  * @envc: Length of @envp.
0101  * @envp: Pointer to "struct tomoyo_envp".
0102  *
0103  * Returns true on success, false otherwise.
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             /* Read. */
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             /* Check. */
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         /* Check not-yet-checked entries. */
0194         for (i = 0; i < argc; i++) {
0195             if (checked[i])
0196                 continue;
0197             /*
0198              * Return true only if all unchecked indexes in
0199              * bprm->argv[] are not matched.
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              * Return true only if all unchecked environ variables
0211              * in bprm->envp[] are either undefined or not matched.
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  * tomoyo_scan_exec_realpath - Check "exec.realpath" parameter of "struct tomoyo_condition".
0227  *
0228  * @file:  Pointer to "struct file".
0229  * @ptr:   Pointer to "struct tomoyo_name_union".
0230  * @match: True if "exec.realpath=", false if "exec.realpath!=".
0231  *
0232  * Returns true on success, false otherwise.
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  * tomoyo_get_dqword - tomoyo_get_name() for a quoted string.
0254  *
0255  * @start: String to save.
0256  *
0257  * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
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  * tomoyo_parse_name_union_quoted - Parse a quoted word.
0273  *
0274  * @param: Pointer to "struct tomoyo_acl_param".
0275  * @ptr:   Pointer to "struct tomoyo_name_union".
0276  *
0277  * Returns true on success, false otherwise.
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  * tomoyo_parse_argv - Parse an argv[] condition part.
0292  *
0293  * @left:  Lefthand value.
0294  * @right: Righthand value.
0295  * @argv:  Pointer to "struct tomoyo_argv".
0296  *
0297  * Returns true on success, false otherwise.
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  * tomoyo_parse_envp - Parse an envp[] condition part.
0311  *
0312  * @left:  Lefthand value.
0313  * @right: Righthand value.
0314  * @envp:  Pointer to "struct tomoyo_envp".
0315  *
0316  * Returns true on success, false otherwise.
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  * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry.
0351  *
0352  * @a: Pointer to "struct tomoyo_condition".
0353  * @b: Pointer to "struct tomoyo_condition".
0354  *
0355  * Returns true if @a == @b, false otherwise.
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  * tomoyo_condition_type - Get condition type.
0370  *
0371  * @word: Keyword string.
0372  *
0373  * Returns one of values in "enum tomoyo_conditions_index" on success,
0374  * TOMOYO_MAX_CONDITION_KEYWORD otherwise.
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 /* Define this to enable debug mode. */
0388 /* #define DEBUG_CONDITION */
0389 
0390 #ifdef DEBUG_CONDITION
0391 #define dprintk printk
0392 #else
0393 #define dprintk(...) do { } while (0)
0394 #endif
0395 
0396 /**
0397  * tomoyo_commit_condition - Commit "struct tomoyo_condition".
0398  *
0399  * @entry: Pointer to "struct tomoyo_condition".
0400  *
0401  * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
0402  *
0403  * This function merges duplicated entries. This function returns NULL if
0404  * @entry is not duplicated but memory quota for policy has exceeded.
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         /* Same entry found. Share this entry. */
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  * tomoyo_get_transit_preference - Parse domain transition preference for execve().
0448  *
0449  * @param: Pointer to "struct tomoyo_acl_param".
0450  * @e:     Pointer to "struct tomoyo_condition".
0451  *
0452  * Returns the condition string part.
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      * Return a bad read-only condition string that will let
0483      * tomoyo_get_condition() return NULL.
0484      */
0485     return "/";
0486 }
0487 
0488 /**
0489  * tomoyo_get_condition - Parse condition part.
0490  *
0491  * @param: Pointer to "struct tomoyo_acl_param".
0492  *
0493  * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
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          * Since left-hand condition does not allow use of "path_group"
0523          * or "number_group" and environment variable's names do not
0524          * accept '=', it is guaranteed that the original line consists
0525          * of one or more repetition of $left$operator$right blocks
0526          * where "$left is free from '=' and ' '" and "$operator is
0527          * either '=' or '!='" and "$right is free from ' '".
0528          * Therefore, we can reconstruct the original line at the end
0529          * of dry run even if we overwrite $operator with '\0'.
0530          */
0531         cp = strchr(pos, ' ');
0532         if (cp) {
0533             *cp = '\0'; /* Will restore later. */
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'; /* Will restore later. */
0544         else if (*(right_word + 1) != '=')
0545             *right_word++ = '\0'; /* Will restore later. */
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) /* Restore " ". */
0686                 *pos = ' ';
0687             else if (*(pos + 1) == '=') /* Restore "!=". */
0688                 *pos = '!';
0689             else /* Restore "=". */
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  * tomoyo_get_attributes - Revalidate "struct inode".
0708  *
0709  * @obj: Pointer to "struct tomoyo_obj_info".
0710  *
0711  * Returns nothing.
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) /* TOMOYO_PATH1_PARENT or TOMOYO_PATH2_PARENT */
0751             dput(dentry);
0752     }
0753 }
0754 
0755 /**
0756  * tomoyo_condition - Check condition part.
0757  *
0758  * @r:    Pointer to "struct tomoyo_request_info".
0759  * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
0760  *
0761  * Returns true on success, false otherwise.
0762  *
0763  * Caller holds tomoyo_read_lock().
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         /* Check argv[] and envp[] later. */
0807         if (left == TOMOYO_ARGV_ENTRY || left == TOMOYO_ENVP_ENTRY)
0808             continue;
0809         /* Check string expressions. */
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         /* Check numeric or bit-op expressions. */
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                 /* Fetch values later. */
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             /* Fetch values now. */
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             /* Fetch values now. */
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          * Bit operation is valid only when counterpart value
1087          * represents permission.
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         /* Normal value range comparison. */
1113         if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match)
1114             continue;
1115 out:
1116         return false;
1117     }
1118     /* Check argv[] and envp[] now. */
1119     if (r->ee && (argc || envc))
1120         return tomoyo_scan_bprm(r->ee, argc, argv, envc, envp);
1121     return true;
1122 }