root/security/tomoyo/condition.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tomoyo_argv
  2. tomoyo_envp
  3. tomoyo_scan_bprm
  4. tomoyo_scan_exec_realpath
  5. tomoyo_get_dqword
  6. tomoyo_parse_name_union_quoted
  7. tomoyo_parse_argv
  8. tomoyo_parse_envp
  9. tomoyo_same_condition
  10. tomoyo_condition_type
  11. tomoyo_get_transit_preference
  12. tomoyo_get_condition
  13. tomoyo_get_attributes
  14. tomoyo_condition

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * security/tomoyo/condition.c
   4  *
   5  * Copyright (C) 2005-2011  NTT DATA CORPORATION
   6  */
   7 
   8 #include "common.h"
   9 #include <linux/slab.h>
  10 
  11 /* List of "struct tomoyo_condition". */
  12 LIST_HEAD(tomoyo_condition_list);
  13 
  14 /**
  15  * tomoyo_argv - Check argv[] in "struct linux_binbrm".
  16  *
  17  * @index:   Index number of @arg_ptr.
  18  * @arg_ptr: Contents of argv[@index].
  19  * @argc:    Length of @argv.
  20  * @argv:    Pointer to "struct tomoyo_argv".
  21  * @checked: Set to true if @argv[@index] was found.
  22  *
  23  * Returns true on success, false otherwise.
  24  */
  25 static bool tomoyo_argv(const unsigned int index, const char *arg_ptr,
  26                         const int argc, const struct tomoyo_argv *argv,
  27                         u8 *checked)
  28 {
  29         int i;
  30         struct tomoyo_path_info arg;
  31 
  32         arg.name = arg_ptr;
  33         for (i = 0; i < argc; argv++, checked++, i++) {
  34                 bool result;
  35 
  36                 if (index != argv->index)
  37                         continue;
  38                 *checked = 1;
  39                 tomoyo_fill_path_info(&arg);
  40                 result = tomoyo_path_matches_pattern(&arg, argv->value);
  41                 if (argv->is_not)
  42                         result = !result;
  43                 if (!result)
  44                         return false;
  45         }
  46         return true;
  47 }
  48 
  49 /**
  50  * tomoyo_envp - Check envp[] in "struct linux_binbrm".
  51  *
  52  * @env_name:  The name of environment variable.
  53  * @env_value: The value of environment variable.
  54  * @envc:      Length of @envp.
  55  * @envp:      Pointer to "struct tomoyo_envp".
  56  * @checked:   Set to true if @envp[@env_name] was found.
  57  *
  58  * Returns true on success, false otherwise.
  59  */
  60 static bool tomoyo_envp(const char *env_name, const char *env_value,
  61                         const int envc, const struct tomoyo_envp *envp,
  62                         u8 *checked)
  63 {
  64         int i;
  65         struct tomoyo_path_info name;
  66         struct tomoyo_path_info value;
  67 
  68         name.name = env_name;
  69         tomoyo_fill_path_info(&name);
  70         value.name = env_value;
  71         tomoyo_fill_path_info(&value);
  72         for (i = 0; i < envc; envp++, checked++, i++) {
  73                 bool result;
  74 
  75                 if (!tomoyo_path_matches_pattern(&name, envp->name))
  76                         continue;
  77                 *checked = 1;
  78                 if (envp->value) {
  79                         result = tomoyo_path_matches_pattern(&value,
  80                                                              envp->value);
  81                         if (envp->is_not)
  82                                 result = !result;
  83                 } else {
  84                         result = true;
  85                         if (!envp->is_not)
  86                                 result = !result;
  87                 }
  88                 if (!result)
  89                         return false;
  90         }
  91         return true;
  92 }
  93 
  94 /**
  95  * tomoyo_scan_bprm - Scan "struct linux_binprm".
  96  *
  97  * @ee:   Pointer to "struct tomoyo_execve".
  98  * @argc: Length of @argc.
  99  * @argv: Pointer to "struct tomoyo_argv".
 100  * @envc: Length of @envp.
 101  * @envp: Poiner to "struct tomoyo_envp".
 102  *
 103  * Returns true on success, false otherwise.
 104  */
 105 static bool tomoyo_scan_bprm(struct tomoyo_execve *ee,
 106                              const u16 argc, const struct tomoyo_argv *argv,
 107                              const u16 envc, const struct tomoyo_envp *envp)
 108 {
 109         struct linux_binprm *bprm = ee->bprm;
 110         struct tomoyo_page_dump *dump = &ee->dump;
 111         char *arg_ptr = ee->tmp;
 112         int arg_len = 0;
 113         unsigned long pos = bprm->p;
 114         int offset = pos % PAGE_SIZE;
 115         int argv_count = bprm->argc;
 116         int envp_count = bprm->envc;
 117         bool result = true;
 118         u8 local_checked[32];
 119         u8 *checked;
 120 
 121         if (argc + envc <= sizeof(local_checked)) {
 122                 checked = local_checked;
 123                 memset(local_checked, 0, sizeof(local_checked));
 124         } else {
 125                 checked = kzalloc(argc + envc, GFP_NOFS);
 126                 if (!checked)
 127                         return false;
 128         }
 129         while (argv_count || envp_count) {
 130                 if (!tomoyo_dump_page(bprm, pos, dump)) {
 131                         result = false;
 132                         goto out;
 133                 }
 134                 pos += PAGE_SIZE - offset;
 135                 while (offset < PAGE_SIZE) {
 136                         /* Read. */
 137                         const char *kaddr = dump->data;
 138                         const unsigned char c = kaddr[offset++];
 139 
 140                         if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) {
 141                                 if (c == '\\') {
 142                                         arg_ptr[arg_len++] = '\\';
 143                                         arg_ptr[arg_len++] = '\\';
 144                                 } else if (c > ' ' && c < 127) {
 145                                         arg_ptr[arg_len++] = c;
 146                                 } else {
 147                                         arg_ptr[arg_len++] = '\\';
 148                                         arg_ptr[arg_len++] = (c >> 6) + '0';
 149                                         arg_ptr[arg_len++] =
 150                                                 ((c >> 3) & 7) + '0';
 151                                         arg_ptr[arg_len++] = (c & 7) + '0';
 152                                 }
 153                         } else {
 154                                 arg_ptr[arg_len] = '\0';
 155                         }
 156                         if (c)
 157                                 continue;
 158                         /* Check. */
 159                         if (argv_count) {
 160                                 if (!tomoyo_argv(bprm->argc - argv_count,
 161                                                  arg_ptr, argc, argv,
 162                                                  checked)) {
 163                                         result = false;
 164                                         break;
 165                                 }
 166                                 argv_count--;
 167                         } else if (envp_count) {
 168                                 char *cp = strchr(arg_ptr, '=');
 169 
 170                                 if (cp) {
 171                                         *cp = '\0';
 172                                         if (!tomoyo_envp(arg_ptr, cp + 1,
 173                                                          envc, envp,
 174                                                          checked + argc)) {
 175                                                 result = false;
 176                                                 break;
 177                                         }
 178                                 }
 179                                 envp_count--;
 180                         } else {
 181                                 break;
 182                         }
 183                         arg_len = 0;
 184                 }
 185                 offset = 0;
 186                 if (!result)
 187                         break;
 188         }
 189 out:
 190         if (result) {
 191                 int i;
 192 
 193                 /* Check not-yet-checked entries. */
 194                 for (i = 0; i < argc; i++) {
 195                         if (checked[i])
 196                                 continue;
 197                         /*
 198                          * Return true only if all unchecked indexes in
 199                          * bprm->argv[] are not matched.
 200                          */
 201                         if (argv[i].is_not)
 202                                 continue;
 203                         result = false;
 204                         break;
 205                 }
 206                 for (i = 0; i < envc; envp++, i++) {
 207                         if (checked[argc + i])
 208                                 continue;
 209                         /*
 210                          * Return true only if all unchecked environ variables
 211                          * in bprm->envp[] are either undefined or not matched.
 212                          */
 213                         if ((!envp->value && !envp->is_not) ||
 214                             (envp->value && envp->is_not))
 215                                 continue;
 216                         result = false;
 217                         break;
 218                 }
 219         }
 220         if (checked != local_checked)
 221                 kfree(checked);
 222         return result;
 223 }
 224 
 225 /**
 226  * tomoyo_scan_exec_realpath - Check "exec.realpath" parameter of "struct tomoyo_condition".
 227  *
 228  * @file:  Pointer to "struct file".
 229  * @ptr:   Pointer to "struct tomoyo_name_union".
 230  * @match: True if "exec.realpath=", false if "exec.realpath!=".
 231  *
 232  * Returns true on success, false otherwise.
 233  */
 234 static bool tomoyo_scan_exec_realpath(struct file *file,
 235                                       const struct tomoyo_name_union *ptr,
 236                                       const bool match)
 237 {
 238         bool result;
 239         struct tomoyo_path_info exe;
 240 
 241         if (!file)
 242                 return false;
 243         exe.name = tomoyo_realpath_from_path(&file->f_path);
 244         if (!exe.name)
 245                 return false;
 246         tomoyo_fill_path_info(&exe);
 247         result = tomoyo_compare_name_union(&exe, ptr);
 248         kfree(exe.name);
 249         return result == match;
 250 }
 251 
 252 /**
 253  * tomoyo_get_dqword - tomoyo_get_name() for a quoted string.
 254  *
 255  * @start: String to save.
 256  *
 257  * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
 258  */
 259 static const struct tomoyo_path_info *tomoyo_get_dqword(char *start)
 260 {
 261         char *cp = start + strlen(start) - 1;
 262 
 263         if (cp == start || *start++ != '"' || *cp != '"')
 264                 return NULL;
 265         *cp = '\0';
 266         if (*start && !tomoyo_correct_word(start))
 267                 return NULL;
 268         return tomoyo_get_name(start);
 269 }
 270 
 271 /**
 272  * tomoyo_parse_name_union_quoted - Parse a quoted word.
 273  *
 274  * @param: Pointer to "struct tomoyo_acl_param".
 275  * @ptr:   Pointer to "struct tomoyo_name_union".
 276  *
 277  * Returns true on success, false otherwise.
 278  */
 279 static bool tomoyo_parse_name_union_quoted(struct tomoyo_acl_param *param,
 280                                            struct tomoyo_name_union *ptr)
 281 {
 282         char *filename = param->data;
 283 
 284         if (*filename == '@')
 285                 return tomoyo_parse_name_union(param, ptr);
 286         ptr->filename = tomoyo_get_dqword(filename);
 287         return ptr->filename != NULL;
 288 }
 289 
 290 /**
 291  * tomoyo_parse_argv - Parse an argv[] condition part.
 292  *
 293  * @left:  Lefthand value.
 294  * @right: Righthand value.
 295  * @argv:  Pointer to "struct tomoyo_argv".
 296  *
 297  * Returns true on success, false otherwise.
 298  */
 299 static bool tomoyo_parse_argv(char *left, char *right,
 300                               struct tomoyo_argv *argv)
 301 {
 302         if (tomoyo_parse_ulong(&argv->index, &left) !=
 303             TOMOYO_VALUE_TYPE_DECIMAL || *left++ != ']' || *left)
 304                 return false;
 305         argv->value = tomoyo_get_dqword(right);
 306         return argv->value != NULL;
 307 }
 308 
 309 /**
 310  * tomoyo_parse_envp - Parse an envp[] condition part.
 311  *
 312  * @left:  Lefthand value.
 313  * @right: Righthand value.
 314  * @envp:  Pointer to "struct tomoyo_envp".
 315  *
 316  * Returns true on success, false otherwise.
 317  */
 318 static bool tomoyo_parse_envp(char *left, char *right,
 319                               struct tomoyo_envp *envp)
 320 {
 321         const struct tomoyo_path_info *name;
 322         const struct tomoyo_path_info *value;
 323         char *cp = left + strlen(left) - 1;
 324 
 325         if (*cp-- != ']' || *cp != '"')
 326                 goto out;
 327         *cp = '\0';
 328         if (!tomoyo_correct_word(left))
 329                 goto out;
 330         name = tomoyo_get_name(left);
 331         if (!name)
 332                 goto out;
 333         if (!strcmp(right, "NULL")) {
 334                 value = NULL;
 335         } else {
 336                 value = tomoyo_get_dqword(right);
 337                 if (!value) {
 338                         tomoyo_put_name(name);
 339                         goto out;
 340                 }
 341         }
 342         envp->name = name;
 343         envp->value = value;
 344         return true;
 345 out:
 346         return false;
 347 }
 348 
 349 /**
 350  * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry.
 351  *
 352  * @a: Pointer to "struct tomoyo_condition".
 353  * @b: Pointer to "struct tomoyo_condition".
 354  *
 355  * Returns true if @a == @b, false otherwise.
 356  */
 357 static inline bool tomoyo_same_condition(const struct tomoyo_condition *a,
 358                                          const struct tomoyo_condition *b)
 359 {
 360         return a->size == b->size && a->condc == b->condc &&
 361                 a->numbers_count == b->numbers_count &&
 362                 a->names_count == b->names_count &&
 363                 a->argc == b->argc && a->envc == b->envc &&
 364                 a->grant_log == b->grant_log && a->transit == b->transit &&
 365                 !memcmp(a + 1, b + 1, a->size - sizeof(*a));
 366 }
 367 
 368 /**
 369  * tomoyo_condition_type - Get condition type.
 370  *
 371  * @word: Keyword string.
 372  *
 373  * Returns one of values in "enum tomoyo_conditions_index" on success,
 374  * TOMOYO_MAX_CONDITION_KEYWORD otherwise.
 375  */
 376 static u8 tomoyo_condition_type(const char *word)
 377 {
 378         u8 i;
 379 
 380         for (i = 0; i < TOMOYO_MAX_CONDITION_KEYWORD; i++) {
 381                 if (!strcmp(word, tomoyo_condition_keyword[i]))
 382                         break;
 383         }
 384         return i;
 385 }
 386 
 387 /* Define this to enable debug mode. */
 388 /* #define DEBUG_CONDITION */
 389 
 390 #ifdef DEBUG_CONDITION
 391 #define dprintk printk
 392 #else
 393 #define dprintk(...) do { } while (0)
 394 #endif
 395 
 396 /**
 397  * tomoyo_commit_condition - Commit "struct tomoyo_condition".
 398  *
 399  * @entry: Pointer to "struct tomoyo_condition".
 400  *
 401  * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
 402  *
 403  * This function merges duplicated entries. This function returns NULL if
 404  * @entry is not duplicated but memory quota for policy has exceeded.
 405  */
 406 static struct tomoyo_condition *tomoyo_commit_condition
 407 (struct tomoyo_condition *entry)
 408 {
 409         struct tomoyo_condition *ptr;
 410         bool found = false;
 411 
 412         if (mutex_lock_interruptible(&tomoyo_policy_lock)) {
 413                 dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
 414                 ptr = NULL;
 415                 found = true;
 416                 goto out;
 417         }
 418         list_for_each_entry(ptr, &tomoyo_condition_list, head.list) {
 419                 if (!tomoyo_same_condition(ptr, entry) ||
 420                     atomic_read(&ptr->head.users) == TOMOYO_GC_IN_PROGRESS)
 421                         continue;
 422                 /* Same entry found. Share this entry. */
 423                 atomic_inc(&ptr->head.users);
 424                 found = true;
 425                 break;
 426         }
 427         if (!found) {
 428                 if (tomoyo_memory_ok(entry)) {
 429                         atomic_set(&entry->head.users, 1);
 430                         list_add(&entry->head.list, &tomoyo_condition_list);
 431                 } else {
 432                         found = true;
 433                         ptr = NULL;
 434                 }
 435         }
 436         mutex_unlock(&tomoyo_policy_lock);
 437 out:
 438         if (found) {
 439                 tomoyo_del_condition(&entry->head.list);
 440                 kfree(entry);
 441                 entry = ptr;
 442         }
 443         return entry;
 444 }
 445 
 446 /**
 447  * tomoyo_get_transit_preference - Parse domain transition preference for execve().
 448  *
 449  * @param: Pointer to "struct tomoyo_acl_param".
 450  * @e:     Pointer to "struct tomoyo_condition".
 451  *
 452  * Returns the condition string part.
 453  */
 454 static char *tomoyo_get_transit_preference(struct tomoyo_acl_param *param,
 455                                            struct tomoyo_condition *e)
 456 {
 457         char * const pos = param->data;
 458         bool flag;
 459 
 460         if (*pos == '<') {
 461                 e->transit = tomoyo_get_domainname(param);
 462                 goto done;
 463         }
 464         {
 465                 char *cp = strchr(pos, ' ');
 466 
 467                 if (cp)
 468                         *cp = '\0';
 469                 flag = tomoyo_correct_path(pos) || !strcmp(pos, "keep") ||
 470                         !strcmp(pos, "initialize") || !strcmp(pos, "reset") ||
 471                         !strcmp(pos, "child") || !strcmp(pos, "parent");
 472                 if (cp)
 473                         *cp = ' ';
 474         }
 475         if (!flag)
 476                 return pos;
 477         e->transit = tomoyo_get_name(tomoyo_read_token(param));
 478 done:
 479         if (e->transit)
 480                 return param->data;
 481         /*
 482          * Return a bad read-only condition string that will let
 483          * tomoyo_get_condition() return NULL.
 484          */
 485         return "/";
 486 }
 487 
 488 /**
 489  * tomoyo_get_condition - Parse condition part.
 490  *
 491  * @param: Pointer to "struct tomoyo_acl_param".
 492  *
 493  * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
 494  */
 495 struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param)
 496 {
 497         struct tomoyo_condition *entry = NULL;
 498         struct tomoyo_condition_element *condp = NULL;
 499         struct tomoyo_number_union *numbers_p = NULL;
 500         struct tomoyo_name_union *names_p = NULL;
 501         struct tomoyo_argv *argv = NULL;
 502         struct tomoyo_envp *envp = NULL;
 503         struct tomoyo_condition e = { };
 504         char * const start_of_string =
 505                 tomoyo_get_transit_preference(param, &e);
 506         char * const end_of_string = start_of_string + strlen(start_of_string);
 507         char *pos;
 508 
 509 rerun:
 510         pos = start_of_string;
 511         while (1) {
 512                 u8 left = -1;
 513                 u8 right = -1;
 514                 char *left_word = pos;
 515                 char *cp;
 516                 char *right_word;
 517                 bool is_not;
 518 
 519                 if (!*left_word)
 520                         break;
 521                 /*
 522                  * Since left-hand condition does not allow use of "path_group"
 523                  * or "number_group" and environment variable's names do not
 524                  * accept '=', it is guaranteed that the original line consists
 525                  * of one or more repetition of $left$operator$right blocks
 526                  * where "$left is free from '=' and ' '" and "$operator is
 527                  * either '=' or '!='" and "$right is free from ' '".
 528                  * Therefore, we can reconstruct the original line at the end
 529                  * of dry run even if we overwrite $operator with '\0'.
 530                  */
 531                 cp = strchr(pos, ' ');
 532                 if (cp) {
 533                         *cp = '\0'; /* Will restore later. */
 534                         pos = cp + 1;
 535                 } else {
 536                         pos = "";
 537                 }
 538                 right_word = strchr(left_word, '=');
 539                 if (!right_word || right_word == left_word)
 540                         goto out;
 541                 is_not = *(right_word - 1) == '!';
 542                 if (is_not)
 543                         *(right_word++ - 1) = '\0'; /* Will restore later. */
 544                 else if (*(right_word + 1) != '=')
 545                         *right_word++ = '\0'; /* Will restore later. */
 546                 else
 547                         goto out;
 548                 dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word,
 549                         is_not ? "!" : "", right_word);
 550                 if (!strcmp(left_word, "grant_log")) {
 551                         if (entry) {
 552                                 if (is_not ||
 553                                     entry->grant_log != TOMOYO_GRANTLOG_AUTO)
 554                                         goto out;
 555                                 else if (!strcmp(right_word, "yes"))
 556                                         entry->grant_log = TOMOYO_GRANTLOG_YES;
 557                                 else if (!strcmp(right_word, "no"))
 558                                         entry->grant_log = TOMOYO_GRANTLOG_NO;
 559                                 else
 560                                         goto out;
 561                         }
 562                         continue;
 563                 }
 564                 if (!strncmp(left_word, "exec.argv[", 10)) {
 565                         if (!argv) {
 566                                 e.argc++;
 567                                 e.condc++;
 568                         } else {
 569                                 e.argc--;
 570                                 e.condc--;
 571                                 left = TOMOYO_ARGV_ENTRY;
 572                                 argv->is_not = is_not;
 573                                 if (!tomoyo_parse_argv(left_word + 10,
 574                                                        right_word, argv++))
 575                                         goto out;
 576                         }
 577                         goto store_value;
 578                 }
 579                 if (!strncmp(left_word, "exec.envp[\"", 11)) {
 580                         if (!envp) {
 581                                 e.envc++;
 582                                 e.condc++;
 583                         } else {
 584                                 e.envc--;
 585                                 e.condc--;
 586                                 left = TOMOYO_ENVP_ENTRY;
 587                                 envp->is_not = is_not;
 588                                 if (!tomoyo_parse_envp(left_word + 11,
 589                                                        right_word, envp++))
 590                                         goto out;
 591                         }
 592                         goto store_value;
 593                 }
 594                 left = tomoyo_condition_type(left_word);
 595                 dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word,
 596                         left);
 597                 if (left == TOMOYO_MAX_CONDITION_KEYWORD) {
 598                         if (!numbers_p) {
 599                                 e.numbers_count++;
 600                         } else {
 601                                 e.numbers_count--;
 602                                 left = TOMOYO_NUMBER_UNION;
 603                                 param->data = left_word;
 604                                 if (*left_word == '@' ||
 605                                     !tomoyo_parse_number_union(param,
 606                                                                numbers_p++))
 607                                         goto out;
 608                         }
 609                 }
 610                 if (!condp)
 611                         e.condc++;
 612                 else
 613                         e.condc--;
 614                 if (left == TOMOYO_EXEC_REALPATH ||
 615                     left == TOMOYO_SYMLINK_TARGET) {
 616                         if (!names_p) {
 617                                 e.names_count++;
 618                         } else {
 619                                 e.names_count--;
 620                                 right = TOMOYO_NAME_UNION;
 621                                 param->data = right_word;
 622                                 if (!tomoyo_parse_name_union_quoted(param,
 623                                                                     names_p++))
 624                                         goto out;
 625                         }
 626                         goto store_value;
 627                 }
 628                 right = tomoyo_condition_type(right_word);
 629                 if (right == TOMOYO_MAX_CONDITION_KEYWORD) {
 630                         if (!numbers_p) {
 631                                 e.numbers_count++;
 632                         } else {
 633                                 e.numbers_count--;
 634                                 right = TOMOYO_NUMBER_UNION;
 635                                 param->data = right_word;
 636                                 if (!tomoyo_parse_number_union(param,
 637                                                                numbers_p++))
 638                                         goto out;
 639                         }
 640                 }
 641 store_value:
 642                 if (!condp) {
 643                         dprintk(KERN_WARNING "%u: dry_run left=%u right=%u match=%u\n",
 644                                 __LINE__, left, right, !is_not);
 645                         continue;
 646                 }
 647                 condp->left = left;
 648                 condp->right = right;
 649                 condp->equals = !is_not;
 650                 dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
 651                         __LINE__, condp->left, condp->right,
 652                         condp->equals);
 653                 condp++;
 654         }
 655         dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n",
 656                 __LINE__, e.condc, e.numbers_count, e.names_count, e.argc,
 657                 e.envc);
 658         if (entry) {
 659                 BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc |
 660                        e.condc);
 661                 return tomoyo_commit_condition(entry);
 662         }
 663         e.size = sizeof(*entry)
 664                 + e.condc * sizeof(struct tomoyo_condition_element)
 665                 + e.numbers_count * sizeof(struct tomoyo_number_union)
 666                 + e.names_count * sizeof(struct tomoyo_name_union)
 667                 + e.argc * sizeof(struct tomoyo_argv)
 668                 + e.envc * sizeof(struct tomoyo_envp);
 669         entry = kzalloc(e.size, GFP_NOFS);
 670         if (!entry)
 671                 goto out2;
 672         *entry = e;
 673         e.transit = NULL;
 674         condp = (struct tomoyo_condition_element *) (entry + 1);
 675         numbers_p = (struct tomoyo_number_union *) (condp + e.condc);
 676         names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count);
 677         argv = (struct tomoyo_argv *) (names_p + e.names_count);
 678         envp = (struct tomoyo_envp *) (argv + e.argc);
 679         {
 680                 bool flag = false;
 681 
 682                 for (pos = start_of_string; pos < end_of_string; pos++) {
 683                         if (*pos)
 684                                 continue;
 685                         if (flag) /* Restore " ". */
 686                                 *pos = ' ';
 687                         else if (*(pos + 1) == '=') /* Restore "!=". */
 688                                 *pos = '!';
 689                         else /* Restore "=". */
 690                                 *pos = '=';
 691                         flag = !flag;
 692                 }
 693         }
 694         goto rerun;
 695 out:
 696         dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
 697         if (entry) {
 698                 tomoyo_del_condition(&entry->head.list);
 699                 kfree(entry);
 700         }
 701 out2:
 702         tomoyo_put_name(e.transit);
 703         return NULL;
 704 }
 705 
 706 /**
 707  * tomoyo_get_attributes - Revalidate "struct inode".
 708  *
 709  * @obj: Pointer to "struct tomoyo_obj_info".
 710  *
 711  * Returns nothing.
 712  */
 713 void tomoyo_get_attributes(struct tomoyo_obj_info *obj)
 714 {
 715         u8 i;
 716         struct dentry *dentry = NULL;
 717 
 718         for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) {
 719                 struct inode *inode;
 720 
 721                 switch (i) {
 722                 case TOMOYO_PATH1:
 723                         dentry = obj->path1.dentry;
 724                         if (!dentry)
 725                                 continue;
 726                         break;
 727                 case TOMOYO_PATH2:
 728                         dentry = obj->path2.dentry;
 729                         if (!dentry)
 730                                 continue;
 731                         break;
 732                 default:
 733                         if (!dentry)
 734                                 continue;
 735                         dentry = dget_parent(dentry);
 736                         break;
 737                 }
 738                 inode = d_backing_inode(dentry);
 739                 if (inode) {
 740                         struct tomoyo_mini_stat *stat = &obj->stat[i];
 741 
 742                         stat->uid  = inode->i_uid;
 743                         stat->gid  = inode->i_gid;
 744                         stat->ino  = inode->i_ino;
 745                         stat->mode = inode->i_mode;
 746                         stat->dev  = inode->i_sb->s_dev;
 747                         stat->rdev = inode->i_rdev;
 748                         obj->stat_valid[i] = true;
 749                 }
 750                 if (i & 1) /* TOMOYO_PATH1_PARENT or TOMOYO_PATH2_PARENT */
 751                         dput(dentry);
 752         }
 753 }
 754 
 755 /**
 756  * tomoyo_condition - Check condition part.
 757  *
 758  * @r:    Pointer to "struct tomoyo_request_info".
 759  * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
 760  *
 761  * Returns true on success, false otherwise.
 762  *
 763  * Caller holds tomoyo_read_lock().
 764  */
 765 bool tomoyo_condition(struct tomoyo_request_info *r,
 766                       const struct tomoyo_condition *cond)
 767 {
 768         u32 i;
 769         unsigned long min_v[2] = { 0, 0 };
 770         unsigned long max_v[2] = { 0, 0 };
 771         const struct tomoyo_condition_element *condp;
 772         const struct tomoyo_number_union *numbers_p;
 773         const struct tomoyo_name_union *names_p;
 774         const struct tomoyo_argv *argv;
 775         const struct tomoyo_envp *envp;
 776         struct tomoyo_obj_info *obj;
 777         u16 condc;
 778         u16 argc;
 779         u16 envc;
 780         struct linux_binprm *bprm = NULL;
 781 
 782         if (!cond)
 783                 return true;
 784         condc = cond->condc;
 785         argc = cond->argc;
 786         envc = cond->envc;
 787         obj = r->obj;
 788         if (r->ee)
 789                 bprm = r->ee->bprm;
 790         if (!bprm && (argc || envc))
 791                 return false;
 792         condp = (struct tomoyo_condition_element *) (cond + 1);
 793         numbers_p = (const struct tomoyo_number_union *) (condp + condc);
 794         names_p = (const struct tomoyo_name_union *)
 795                 (numbers_p + cond->numbers_count);
 796         argv = (const struct tomoyo_argv *) (names_p + cond->names_count);
 797         envp = (const struct tomoyo_envp *) (argv + argc);
 798         for (i = 0; i < condc; i++) {
 799                 const bool match = condp->equals;
 800                 const u8 left = condp->left;
 801                 const u8 right = condp->right;
 802                 bool is_bitop[2] = { false, false };
 803                 u8 j;
 804 
 805                 condp++;
 806                 /* Check argv[] and envp[] later. */
 807                 if (left == TOMOYO_ARGV_ENTRY || left == TOMOYO_ENVP_ENTRY)
 808                         continue;
 809                 /* Check string expressions. */
 810                 if (right == TOMOYO_NAME_UNION) {
 811                         const struct tomoyo_name_union *ptr = names_p++;
 812                         struct tomoyo_path_info *symlink;
 813                         struct tomoyo_execve *ee;
 814                         struct file *file;
 815 
 816                         switch (left) {
 817                         case TOMOYO_SYMLINK_TARGET:
 818                                 symlink = obj ? obj->symlink_target : NULL;
 819                                 if (!symlink ||
 820                                     !tomoyo_compare_name_union(symlink, ptr)
 821                                     == match)
 822                                         goto out;
 823                                 break;
 824                         case TOMOYO_EXEC_REALPATH:
 825                                 ee = r->ee;
 826                                 file = ee ? ee->bprm->file : NULL;
 827                                 if (!tomoyo_scan_exec_realpath(file, ptr,
 828                                                                match))
 829                                         goto out;
 830                                 break;
 831                         }
 832                         continue;
 833                 }
 834                 /* Check numeric or bit-op expressions. */
 835                 for (j = 0; j < 2; j++) {
 836                         const u8 index = j ? right : left;
 837                         unsigned long value = 0;
 838 
 839                         switch (index) {
 840                         case TOMOYO_TASK_UID:
 841                                 value = from_kuid(&init_user_ns, current_uid());
 842                                 break;
 843                         case TOMOYO_TASK_EUID:
 844                                 value = from_kuid(&init_user_ns, current_euid());
 845                                 break;
 846                         case TOMOYO_TASK_SUID:
 847                                 value = from_kuid(&init_user_ns, current_suid());
 848                                 break;
 849                         case TOMOYO_TASK_FSUID:
 850                                 value = from_kuid(&init_user_ns, current_fsuid());
 851                                 break;
 852                         case TOMOYO_TASK_GID:
 853                                 value = from_kgid(&init_user_ns, current_gid());
 854                                 break;
 855                         case TOMOYO_TASK_EGID:
 856                                 value = from_kgid(&init_user_ns, current_egid());
 857                                 break;
 858                         case TOMOYO_TASK_SGID:
 859                                 value = from_kgid(&init_user_ns, current_sgid());
 860                                 break;
 861                         case TOMOYO_TASK_FSGID:
 862                                 value = from_kgid(&init_user_ns, current_fsgid());
 863                                 break;
 864                         case TOMOYO_TASK_PID:
 865                                 value = tomoyo_sys_getpid();
 866                                 break;
 867                         case TOMOYO_TASK_PPID:
 868                                 value = tomoyo_sys_getppid();
 869                                 break;
 870                         case TOMOYO_TYPE_IS_SOCKET:
 871                                 value = S_IFSOCK;
 872                                 break;
 873                         case TOMOYO_TYPE_IS_SYMLINK:
 874                                 value = S_IFLNK;
 875                                 break;
 876                         case TOMOYO_TYPE_IS_FILE:
 877                                 value = S_IFREG;
 878                                 break;
 879                         case TOMOYO_TYPE_IS_BLOCK_DEV:
 880                                 value = S_IFBLK;
 881                                 break;
 882                         case TOMOYO_TYPE_IS_DIRECTORY:
 883                                 value = S_IFDIR;
 884                                 break;
 885                         case TOMOYO_TYPE_IS_CHAR_DEV:
 886                                 value = S_IFCHR;
 887                                 break;
 888                         case TOMOYO_TYPE_IS_FIFO:
 889                                 value = S_IFIFO;
 890                                 break;
 891                         case TOMOYO_MODE_SETUID:
 892                                 value = S_ISUID;
 893                                 break;
 894                         case TOMOYO_MODE_SETGID:
 895                                 value = S_ISGID;
 896                                 break;
 897                         case TOMOYO_MODE_STICKY:
 898                                 value = S_ISVTX;
 899                                 break;
 900                         case TOMOYO_MODE_OWNER_READ:
 901                                 value = 0400;
 902                                 break;
 903                         case TOMOYO_MODE_OWNER_WRITE:
 904                                 value = 0200;
 905                                 break;
 906                         case TOMOYO_MODE_OWNER_EXECUTE:
 907                                 value = 0100;
 908                                 break;
 909                         case TOMOYO_MODE_GROUP_READ:
 910                                 value = 0040;
 911                                 break;
 912                         case TOMOYO_MODE_GROUP_WRITE:
 913                                 value = 0020;
 914                                 break;
 915                         case TOMOYO_MODE_GROUP_EXECUTE:
 916                                 value = 0010;
 917                                 break;
 918                         case TOMOYO_MODE_OTHERS_READ:
 919                                 value = 0004;
 920                                 break;
 921                         case TOMOYO_MODE_OTHERS_WRITE:
 922                                 value = 0002;
 923                                 break;
 924                         case TOMOYO_MODE_OTHERS_EXECUTE:
 925                                 value = 0001;
 926                                 break;
 927                         case TOMOYO_EXEC_ARGC:
 928                                 if (!bprm)
 929                                         goto out;
 930                                 value = bprm->argc;
 931                                 break;
 932                         case TOMOYO_EXEC_ENVC:
 933                                 if (!bprm)
 934                                         goto out;
 935                                 value = bprm->envc;
 936                                 break;
 937                         case TOMOYO_NUMBER_UNION:
 938                                 /* Fetch values later. */
 939                                 break;
 940                         default:
 941                                 if (!obj)
 942                                         goto out;
 943                                 if (!obj->validate_done) {
 944                                         tomoyo_get_attributes(obj);
 945                                         obj->validate_done = true;
 946                                 }
 947                                 {
 948                                         u8 stat_index;
 949                                         struct tomoyo_mini_stat *stat;
 950 
 951                                         switch (index) {
 952                                         case TOMOYO_PATH1_UID:
 953                                         case TOMOYO_PATH1_GID:
 954                                         case TOMOYO_PATH1_INO:
 955                                         case TOMOYO_PATH1_MAJOR:
 956                                         case TOMOYO_PATH1_MINOR:
 957                                         case TOMOYO_PATH1_TYPE:
 958                                         case TOMOYO_PATH1_DEV_MAJOR:
 959                                         case TOMOYO_PATH1_DEV_MINOR:
 960                                         case TOMOYO_PATH1_PERM:
 961                                                 stat_index = TOMOYO_PATH1;
 962                                                 break;
 963                                         case TOMOYO_PATH2_UID:
 964                                         case TOMOYO_PATH2_GID:
 965                                         case TOMOYO_PATH2_INO:
 966                                         case TOMOYO_PATH2_MAJOR:
 967                                         case TOMOYO_PATH2_MINOR:
 968                                         case TOMOYO_PATH2_TYPE:
 969                                         case TOMOYO_PATH2_DEV_MAJOR:
 970                                         case TOMOYO_PATH2_DEV_MINOR:
 971                                         case TOMOYO_PATH2_PERM:
 972                                                 stat_index = TOMOYO_PATH2;
 973                                                 break;
 974                                         case TOMOYO_PATH1_PARENT_UID:
 975                                         case TOMOYO_PATH1_PARENT_GID:
 976                                         case TOMOYO_PATH1_PARENT_INO:
 977                                         case TOMOYO_PATH1_PARENT_PERM:
 978                                                 stat_index =
 979                                                         TOMOYO_PATH1_PARENT;
 980                                                 break;
 981                                         case TOMOYO_PATH2_PARENT_UID:
 982                                         case TOMOYO_PATH2_PARENT_GID:
 983                                         case TOMOYO_PATH2_PARENT_INO:
 984                                         case TOMOYO_PATH2_PARENT_PERM:
 985                                                 stat_index =
 986                                                         TOMOYO_PATH2_PARENT;
 987                                                 break;
 988                                         default:
 989                                                 goto out;
 990                                         }
 991                                         if (!obj->stat_valid[stat_index])
 992                                                 goto out;
 993                                         stat = &obj->stat[stat_index];
 994                                         switch (index) {
 995                                         case TOMOYO_PATH1_UID:
 996                                         case TOMOYO_PATH2_UID:
 997                                         case TOMOYO_PATH1_PARENT_UID:
 998                                         case TOMOYO_PATH2_PARENT_UID:
 999                                                 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 }

/* [<][>][^][v][top][bottom][index][help] */