linux/security/tomoyo/condition.c
<<
>>
Prefs
   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". */
  11LIST_HEAD(tomoyo_condition_list);
  12
  13/**
  14 * tomoyo_argv - Check argv[] in "struct linux_binbrm".
  15 *
  16 * @index:   Index number of @arg_ptr.
  17 * @arg_ptr: Contents of argv[@index].
  18 * @argc:    Length of @argv.
  19 * @argv:    Pointer to "struct tomoyo_argv".
  20 * @checked: Set to true if @argv[@index] was found.
  21 *
  22 * Returns true on success, false otherwise.
  23 */
  24static 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;
  36                tomoyo_fill_path_info(&arg);
  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
  46/**
  47 * tomoyo_envp - Check envp[] in "struct linux_binbrm".
  48 *
  49 * @env_name:  The name of environment variable.
  50 * @env_value: The value of environment variable.
  51 * @envc:      Length of @envp.
  52 * @envp:      Pointer to "struct tomoyo_envp".
  53 * @checked:   Set to true if @envp[@env_name] was found.
  54 *
  55 * Returns true on success, false otherwise.
  56 */
  57static 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;
  65        tomoyo_fill_path_info(&name);
  66        value.name = env_value;
  67        tomoyo_fill_path_info(&value);
  68        for (i = 0; i < envc; envp++, checked++, i++) {
  69                bool result;
  70                if (!tomoyo_path_matches_pattern(&name, envp->name))
  71                        continue;
  72                *checked = 1;
  73                if (envp->value) {
  74                        result = tomoyo_path_matches_pattern(&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
  89/**
  90 * tomoyo_scan_bprm - Scan "struct linux_binprm".
  91 *
  92 * @ee:   Pointer to "struct tomoyo_execve".
  93 * @argc: Length of @argc.
  94 * @argv: Pointer to "struct tomoyo_argv".
  95 * @envc: Length of @envp.
  96 * @envp: Poiner to "struct tomoyo_envp".
  97 *
  98 * Returns true on success, false otherwise.
  99 */
 100static 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        }
 181out:
 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
 216/**
 217 * tomoyo_scan_exec_realpath - Check "exec.realpath" parameter of "struct tomoyo_condition".
 218 *
 219 * @file:  Pointer to "struct file".
 220 * @ptr:   Pointer to "struct tomoyo_name_union".
 221 * @match: True if "exec.realpath=", false if "exec.realpath!=".
 222 *
 223 * Returns true on success, false otherwise.
 224 */
 225static 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
 242/**
 243 * tomoyo_get_dqword - tomoyo_get_name() for a quoted string.
 244 *
 245 * @start: String to save.
 246 *
 247 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
 248 */
 249static 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
 260/**
 261 * tomoyo_parse_name_union_quoted - Parse a quoted word.
 262 *
 263 * @param: Pointer to "struct tomoyo_acl_param".
 264 * @ptr:   Pointer to "struct tomoyo_name_union".
 265 *
 266 * Returns true on success, false otherwise.
 267 */
 268static 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
 278/**
 279 * tomoyo_parse_argv - Parse an argv[] condition part.
 280 *
 281 * @left:  Lefthand value.
 282 * @right: Righthand value.
 283 * @argv:  Pointer to "struct tomoyo_argv".
 284 *
 285 * Returns true on success, false otherwise.
 286 */
 287static 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
 297/**
 298 * tomoyo_parse_envp - Parse an envp[] condition part.
 299 *
 300 * @left:  Lefthand value.
 301 * @right: Righthand value.
 302 * @envp:  Pointer to "struct tomoyo_envp".
 303 *
 304 * Returns true on success, false otherwise.
 305 */
 306static 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;
 332out:
 333        return false;
 334}
 335
 336/**
 337 * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry.
 338 *
 339 * @a: Pointer to "struct tomoyo_condition".
 340 * @b: Pointer to "struct tomoyo_condition".
 341 *
 342 * Returns true if @a == @b, false otherwise.
 343 */
 344static 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
 355/**
 356 * tomoyo_condition_type - Get condition type.
 357 *
 358 * @word: Keyword string.
 359 *
 360 * Returns one of values in "enum tomoyo_conditions_index" on success,
 361 * TOMOYO_MAX_CONDITION_KEYWORD otherwise.
 362 */
 363static 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
 382/**
 383 * tomoyo_commit_condition - Commit "struct tomoyo_condition".
 384 *
 385 * @entry: Pointer to "struct tomoyo_condition".
 386 *
 387 * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
 388 *
 389 * This function merges duplicated entries. This function returns NULL if
 390 * @entry is not duplicated but memory quota for policy has exceeded.
 391 */
 392static struct tomoyo_condition *tomoyo_commit_condition
 393(struct tomoyo_condition *entry)
 394{
 395        struct tomoyo_condition *ptr;
 396        bool found = false;
 397        if (mutex_lock_interruptible(&tomoyo_policy_lock)) {
 398                dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
 399                ptr = NULL;
 400                found = true;
 401                goto out;
 402        }
 403        list_for_each_entry(ptr, &tomoyo_condition_list, head.list) {
 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        }
 421        mutex_unlock(&tomoyo_policy_lock);
 422out:
 423        if (found) {
 424                tomoyo_del_condition(&entry->head.list);
 425                kfree(entry);
 426                entry = ptr;
 427        }
 428        return entry;
 429}
 430
 431/**
 432 * tomoyo_get_transit_preference - Parse domain transition preference for execve().
 433 *
 434 * @param: Pointer to "struct tomoyo_acl_param".
 435 * @e:     Pointer to "struct tomoyo_condition".
 436 *
 437 * Returns the condition string part.
 438 */
 439static 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;
 460        e->transit = tomoyo_get_name(tomoyo_read_token(param));
 461done:
 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
 471/**
 472 * tomoyo_get_condition - Parse condition part.
 473 *
 474 * @param: Pointer to "struct tomoyo_acl_param".
 475 *
 476 * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
 477 */
 478struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param)
 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;
 491rerun:
 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 ||
 534                                    entry->grant_log != TOMOYO_GRANTLOG_AUTO)
 535                                        goto out;
 536                                else if (!strcmp(right_word, "yes"))
 537                                        entry->grant_log = TOMOYO_GRANTLOG_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 == '@' ||
 586                                    !tomoyo_parse_number_union(param,
 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                }
 622store_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;
 675out:
 676        dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
 677        if (entry) {
 678                tomoyo_del_condition(&entry->head.list);
 679                kfree(entry);
 680        }
 681out2:
 682        tomoyo_put_name(e.transit);
 683        return NULL;
 684}
 685
 686/**
 687 * tomoyo_get_attributes - Revalidate "struct inode".
 688 *
 689 * @obj: Pointer to "struct tomoyo_obj_info".
 690 *
 691 * Returns nothing.
 692 */
 693void tomoyo_get_attributes(struct tomoyo_obj_info *obj)
 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
 734/**
 735 * tomoyo_condition - Check condition part.
 736 *
 737 * @r:    Pointer to "struct tomoyo_request_info".
 738 * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
 739 *
 740 * Returns true on success, false otherwise.
 741 *
 742 * Caller holds tomoyo_read_lock().
 743 */
 744bool tomoyo_condition(struct tomoyo_request_info *r,
 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;
 793                        case TOMOYO_SYMLINK_TARGET:
 794                                symlink = obj ? obj->symlink_target : NULL;
 795                                if (!symlink ||
 796                                    !tomoyo_compare_name_union(symlink, ptr)
 797                                    == match)
 798                                        goto out;
 799                                break;
 800                        case TOMOYO_EXEC_REALPATH:
 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;
 845                        case TOMOYO_TYPE_IS_SOCKET:
 846                                value = S_IFSOCK;
 847                                break;
 848                        case TOMOYO_TYPE_IS_SYMLINK:
 849                                value = S_IFLNK;
 850                                break;
 851                        case TOMOYO_TYPE_IS_FILE:
 852                                value = S_IFREG;
 853                                break;
 854                        case TOMOYO_TYPE_IS_BLOCK_DEV:
 855                                value = S_IFBLK;
 856                                break;
 857                        case TOMOYO_TYPE_IS_DIRECTORY:
 858                                value = S_IFDIR;
 859                                break;
 860                        case TOMOYO_TYPE_IS_CHAR_DEV:
 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;
 875                        case TOMOYO_MODE_OWNER_READ:
 876                                value = S_IRUSR;
 877                                break;
 878                        case TOMOYO_MODE_OWNER_WRITE:
 879                                value = S_IWUSR;
 880                                break;
 881                        case TOMOYO_MODE_OWNER_EXECUTE:
 882                                value = S_IXUSR;
 883                                break;
 884                        case TOMOYO_MODE_GROUP_READ:
 885                                value = S_IRGRP;
 886                                break;
 887                        case TOMOYO_MODE_GROUP_WRITE:
 888                                value = S_IWGRP;
 889                                break;
 890                        case TOMOYO_MODE_GROUP_EXECUTE:
 891                                value = S_IXGRP;
 892                                break;
 893                        case TOMOYO_MODE_OTHERS_READ:
 894                                value = S_IROTH;
 895                                break;
 896                        case TOMOYO_MODE_OTHERS_WRITE:
 897                                value = S_IWOTH;
 898                                break;
 899                        case TOMOYO_MODE_OTHERS_EXECUTE:
 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) {
 919                                        tomoyo_get_attributes(obj);
 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:
 932                                        case TOMOYO_PATH1_DEV_MAJOR:
 933                                        case TOMOYO_PATH1_DEV_MINOR:
 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:
 943                                        case TOMOYO_PATH2_DEV_MAJOR:
 944                                        case TOMOYO_PATH2_DEV_MINOR:
 945                                        case TOMOYO_PATH2_PERM:
 946                                                stat_index = TOMOYO_PATH2;
 947                                                break;
 948                                        case TOMOYO_PATH1_PARENT_UID:
 949                                        case TOMOYO_PATH1_PARENT_GID:
 950                                        case TOMOYO_PATH1_PARENT_INO:
 951                                        case TOMOYO_PATH1_PARENT_PERM:
 952                                                stat_index =
 953                                                        TOMOYO_PATH1_PARENT;
 954                                                break;
 955                                        case TOMOYO_PATH2_PARENT_UID:
 956                                        case TOMOYO_PATH2_PARENT_GID:
 957                                        case TOMOYO_PATH2_PARENT_INO:
 958                                        case TOMOYO_PATH2_PARENT_PERM:
 959                                                stat_index =
 960                                                        TOMOYO_PATH2_PARENT;
 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:
 971                                        case TOMOYO_PATH1_PARENT_UID:
 972                                        case TOMOYO_PATH2_PARENT_UID:
 973                                                value = from_kuid(&init_user_ns, stat->uid);
 974                                                break;
 975                                        case TOMOYO_PATH1_GID:
 976                                        case TOMOYO_PATH2_GID:
 977                                        case TOMOYO_PATH1_PARENT_GID:
 978                                        case TOMOYO_PATH2_PARENT_GID:
 979                                                value = from_kgid(&init_user_ns, stat->gid);
 980                                                break;
 981                                        case TOMOYO_PATH1_INO:
 982                                        case TOMOYO_PATH2_INO:
 983                                        case TOMOYO_PATH1_PARENT_INO:
 984                                        case TOMOYO_PATH2_PARENT_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;
 999                                        case TOMOYO_PATH1_DEV_MAJOR:
1000                                        case TOMOYO_PATH2_DEV_MAJOR:
1001                                                value = MAJOR(stat->rdev);
1002                                                break;
1003                                        case TOMOYO_PATH1_DEV_MINOR:
1004                                        case TOMOYO_PATH2_DEV_MINOR:
1005                                                value = MINOR(stat->rdev);
1006                                                break;
1007                                        case TOMOYO_PATH1_PERM:
1008                                        case TOMOYO_PATH2_PERM:
1009                                        case TOMOYO_PATH1_PARENT_PERM:
1010                                        case TOMOYO_PATH2_PARENT_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:
1023                        case TOMOYO_MODE_OWNER_READ:
1024                        case TOMOYO_MODE_OWNER_WRITE:
1025                        case TOMOYO_MODE_OWNER_EXECUTE:
1026                        case TOMOYO_MODE_GROUP_READ:
1027                        case TOMOYO_MODE_GROUP_WRITE:
1028                        case TOMOYO_MODE_GROUP_EXECUTE:
1029                        case TOMOYO_MODE_OTHERS_READ:
1030                        case TOMOYO_MODE_OTHERS_WRITE:
1031                        case TOMOYO_MODE_OTHERS_EXECUTE:
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:
1066                        case TOMOYO_PATH1_PARENT_PERM:
1067                        case TOMOYO_PATH2_PERM:
1068                        case TOMOYO_PATH2_PARENT_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:
1076                        case TOMOYO_PATH1_PARENT_PERM:
1077                        case TOMOYO_PATH2_PERM:
1078                        case TOMOYO_PATH2_PARENT_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;
1087out:
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}
1095