linux/security/tomoyo/common.c
<<
>>
Prefs
   1/*
   2 * security/tomoyo/common.c
   3 *
   4 * Common functions for TOMOYO.
   5 *
   6 * Copyright (C) 2005-2009  NTT DATA CORPORATION
   7 *
   8 * Version: 2.2.0   2009/04/01
   9 *
  10 */
  11
  12#include <linux/uaccess.h>
  13#include <linux/security.h>
  14#include <linux/hardirq.h>
  15#include "realpath.h"
  16#include "common.h"
  17#include "tomoyo.h"
  18
  19/* Has loading policy done? */
  20bool tomoyo_policy_loaded;
  21
  22/* String table for functionality that takes 4 modes. */
  23static const char *tomoyo_mode_4[4] = {
  24        "disabled", "learning", "permissive", "enforcing"
  25};
  26/* String table for functionality that takes 2 modes. */
  27static const char *tomoyo_mode_2[4] = {
  28        "disabled", "enabled", "enabled", "enabled"
  29};
  30
  31/*
  32 * tomoyo_control_array is a static data which contains
  33 *
  34 *  (1) functionality name used by /sys/kernel/security/tomoyo/profile .
  35 *  (2) initial values for "struct tomoyo_profile".
  36 *  (3) max values for "struct tomoyo_profile".
  37 */
  38static struct {
  39        const char *keyword;
  40        unsigned int current_value;
  41        const unsigned int max_value;
  42} tomoyo_control_array[TOMOYO_MAX_CONTROL_INDEX] = {
  43        [TOMOYO_MAC_FOR_FILE]     = { "MAC_FOR_FILE",        0,       3 },
  44        [TOMOYO_MAX_ACCEPT_ENTRY] = { "MAX_ACCEPT_ENTRY", 2048, INT_MAX },
  45        [TOMOYO_VERBOSE]          = { "TOMOYO_VERBOSE",      1,       1 },
  46};
  47
  48/*
  49 * tomoyo_profile is a structure which is used for holding the mode of access
  50 * controls. TOMOYO has 4 modes: disabled, learning, permissive, enforcing.
  51 * An administrator can define up to 256 profiles.
  52 * The ->profile of "struct tomoyo_domain_info" is used for remembering
  53 * the profile's number (0 - 255) assigned to that domain.
  54 */
  55static struct tomoyo_profile {
  56        unsigned int value[TOMOYO_MAX_CONTROL_INDEX];
  57        const struct tomoyo_path_info *comment;
  58} *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES];
  59
  60/* Permit policy management by non-root user? */
  61static bool tomoyo_manage_by_non_root;
  62
  63/* Utility functions. */
  64
  65/* Open operation for /sys/kernel/security/tomoyo/ interface. */
  66static int tomoyo_open_control(const u8 type, struct file *file);
  67/* Close /sys/kernel/security/tomoyo/ interface. */
  68static int tomoyo_close_control(struct file *file);
  69/* Read operation for /sys/kernel/security/tomoyo/ interface. */
  70static int tomoyo_read_control(struct file *file, char __user *buffer,
  71                               const int buffer_len);
  72/* Write operation for /sys/kernel/security/tomoyo/ interface. */
  73static int tomoyo_write_control(struct file *file, const char __user *buffer,
  74                                const int buffer_len);
  75
  76/**
  77 * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value.
  78 *
  79 * @str: Pointer to the string.
  80 *
  81 * Returns true if @str is a \ooo style octal value, false otherwise.
  82 *
  83 * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF.
  84 * This function verifies that \ooo is in valid range.
  85 */
  86static inline bool tomoyo_is_byte_range(const char *str)
  87{
  88        return *str >= '0' && *str++ <= '3' &&
  89                *str >= '0' && *str++ <= '7' &&
  90                *str >= '0' && *str <= '7';
  91}
  92
  93/**
  94 * tomoyo_is_alphabet_char - Check whether the character is an alphabet.
  95 *
  96 * @c: The character to check.
  97 *
  98 * Returns true if @c is an alphabet character, false otherwise.
  99 */
 100static inline bool tomoyo_is_alphabet_char(const char c)
 101{
 102        return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
 103}
 104
 105/**
 106 * tomoyo_make_byte - Make byte value from three octal characters.
 107 *
 108 * @c1: The first character.
 109 * @c2: The second character.
 110 * @c3: The third character.
 111 *
 112 * Returns byte value.
 113 */
 114static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3)
 115{
 116        return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
 117}
 118
 119/**
 120 * tomoyo_str_starts - Check whether the given string starts with the given keyword.
 121 *
 122 * @src:  Pointer to pointer to the string.
 123 * @find: Pointer to the keyword.
 124 *
 125 * Returns true if @src starts with @find, false otherwise.
 126 *
 127 * The @src is updated to point the first character after the @find
 128 * if @src starts with @find.
 129 */
 130static bool tomoyo_str_starts(char **src, const char *find)
 131{
 132        const int len = strlen(find);
 133        char *tmp = *src;
 134
 135        if (strncmp(tmp, find, len))
 136                return false;
 137        tmp += len;
 138        *src = tmp;
 139        return true;
 140}
 141
 142/**
 143 * tomoyo_normalize_line - Format string.
 144 *
 145 * @buffer: The line to normalize.
 146 *
 147 * Leading and trailing whitespaces are removed.
 148 * Multiple whitespaces are packed into single space.
 149 *
 150 * Returns nothing.
 151 */
 152static void tomoyo_normalize_line(unsigned char *buffer)
 153{
 154        unsigned char *sp = buffer;
 155        unsigned char *dp = buffer;
 156        bool first = true;
 157
 158        while (tomoyo_is_invalid(*sp))
 159                sp++;
 160        while (*sp) {
 161                if (!first)
 162                        *dp++ = ' ';
 163                first = false;
 164                while (tomoyo_is_valid(*sp))
 165                        *dp++ = *sp++;
 166                while (tomoyo_is_invalid(*sp))
 167                        sp++;
 168        }
 169        *dp = '\0';
 170}
 171
 172/**
 173 * tomoyo_is_correct_path - Validate a pathname.
 174 * @filename:     The pathname to check.
 175 * @start_type:   Should the pathname start with '/'?
 176 *                1 = must / -1 = must not / 0 = don't care
 177 * @pattern_type: Can the pathname contain a wildcard?
 178 *                1 = must / -1 = must not / 0 = don't care
 179 * @end_type:     Should the pathname end with '/'?
 180 *                1 = must / -1 = must not / 0 = don't care
 181 * @function:     The name of function calling me.
 182 *
 183 * Check whether the given filename follows the naming rules.
 184 * Returns true if @filename follows the naming rules, false otherwise.
 185 */
 186bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
 187                            const s8 pattern_type, const s8 end_type,
 188                            const char *function)
 189{
 190        bool contains_pattern = false;
 191        unsigned char c;
 192        unsigned char d;
 193        unsigned char e;
 194        const char *original_filename = filename;
 195
 196        if (!filename)
 197                goto out;
 198        c = *filename;
 199        if (start_type == 1) { /* Must start with '/' */
 200                if (c != '/')
 201                        goto out;
 202        } else if (start_type == -1) { /* Must not start with '/' */
 203                if (c == '/')
 204                        goto out;
 205        }
 206        if (c)
 207                c = *(filename + strlen(filename) - 1);
 208        if (end_type == 1) { /* Must end with '/' */
 209                if (c != '/')
 210                        goto out;
 211        } else if (end_type == -1) { /* Must not end with '/' */
 212                if (c == '/')
 213                        goto out;
 214        }
 215        while ((c = *filename++) != '\0') {
 216                if (c == '\\') {
 217                        switch ((c = *filename++)) {
 218                        case '\\':  /* "\\" */
 219                                continue;
 220                        case '$':   /* "\$" */
 221                        case '+':   /* "\+" */
 222                        case '?':   /* "\?" */
 223                        case '*':   /* "\*" */
 224                        case '@':   /* "\@" */
 225                        case 'x':   /* "\x" */
 226                        case 'X':   /* "\X" */
 227                        case 'a':   /* "\a" */
 228                        case 'A':   /* "\A" */
 229                        case '-':   /* "\-" */
 230                                if (pattern_type == -1)
 231                                        break; /* Must not contain pattern */
 232                                contains_pattern = true;
 233                                continue;
 234                        case '0':   /* "\ooo" */
 235                        case '1':
 236                        case '2':
 237                        case '3':
 238                                d = *filename++;
 239                                if (d < '0' || d > '7')
 240                                        break;
 241                                e = *filename++;
 242                                if (e < '0' || e > '7')
 243                                        break;
 244                                c = tomoyo_make_byte(c, d, e);
 245                                if (tomoyo_is_invalid(c))
 246                                        continue; /* pattern is not \000 */
 247                        }
 248                        goto out;
 249                } else if (tomoyo_is_invalid(c)) {
 250                        goto out;
 251                }
 252        }
 253        if (pattern_type == 1) { /* Must contain pattern */
 254                if (!contains_pattern)
 255                        goto out;
 256        }
 257        return true;
 258 out:
 259        printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function,
 260               original_filename);
 261        return false;
 262}
 263
 264/**
 265 * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules.
 266 * @domainname:   The domainname to check.
 267 * @function:     The name of function calling me.
 268 *
 269 * Returns true if @domainname follows the naming rules, false otherwise.
 270 */
 271bool tomoyo_is_correct_domain(const unsigned char *domainname,
 272                              const char *function)
 273{
 274        unsigned char c;
 275        unsigned char d;
 276        unsigned char e;
 277        const char *org_domainname = domainname;
 278
 279        if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME,
 280                                   TOMOYO_ROOT_NAME_LEN))
 281                goto out;
 282        domainname += TOMOYO_ROOT_NAME_LEN;
 283        if (!*domainname)
 284                return true;
 285        do {
 286                if (*domainname++ != ' ')
 287                        goto out;
 288                if (*domainname++ != '/')
 289                        goto out;
 290                while ((c = *domainname) != '\0' && c != ' ') {
 291                        domainname++;
 292                        if (c == '\\') {
 293                                c = *domainname++;
 294                                switch ((c)) {
 295                                case '\\':  /* "\\" */
 296                                        continue;
 297                                case '0':   /* "\ooo" */
 298                                case '1':
 299                                case '2':
 300                                case '3':
 301                                        d = *domainname++;
 302                                        if (d < '0' || d > '7')
 303                                                break;
 304                                        e = *domainname++;
 305                                        if (e < '0' || e > '7')
 306                                                break;
 307                                        c = tomoyo_make_byte(c, d, e);
 308                                        if (tomoyo_is_invalid(c))
 309                                                /* pattern is not \000 */
 310                                                continue;
 311                                }
 312                                goto out;
 313                        } else if (tomoyo_is_invalid(c)) {
 314                                goto out;
 315                        }
 316                }
 317        } while (*domainname);
 318        return true;
 319 out:
 320        printk(KERN_DEBUG "%s: Invalid domainname '%s'\n", function,
 321               org_domainname);
 322        return false;
 323}
 324
 325/**
 326 * tomoyo_is_domain_def - Check whether the given token can be a domainname.
 327 *
 328 * @buffer: The token to check.
 329 *
 330 * Returns true if @buffer possibly be a domainname, false otherwise.
 331 */
 332bool tomoyo_is_domain_def(const unsigned char *buffer)
 333{
 334        return !strncmp(buffer, TOMOYO_ROOT_NAME, TOMOYO_ROOT_NAME_LEN);
 335}
 336
 337/**
 338 * tomoyo_find_domain - Find a domain by the given name.
 339 *
 340 * @domainname: The domainname to find.
 341 *
 342 * Caller must call down_read(&tomoyo_domain_list_lock); or
 343 * down_write(&tomoyo_domain_list_lock); .
 344 *
 345 * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
 346 */
 347struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
 348{
 349        struct tomoyo_domain_info *domain;
 350        struct tomoyo_path_info name;
 351
 352        name.name = domainname;
 353        tomoyo_fill_path_info(&name);
 354        list_for_each_entry(domain, &tomoyo_domain_list, list) {
 355                if (!domain->is_deleted &&
 356                    !tomoyo_pathcmp(&name, domain->domainname))
 357                        return domain;
 358        }
 359        return NULL;
 360}
 361
 362/**
 363 * tomoyo_path_depth - Evaluate the number of '/' in a string.
 364 *
 365 * @pathname: The string to evaluate.
 366 *
 367 * Returns path depth of the string.
 368 *
 369 * I score 2 for each of the '/' in the @pathname
 370 * and score 1 if the @pathname ends with '/'.
 371 */
 372static int tomoyo_path_depth(const char *pathname)
 373{
 374        int i = 0;
 375
 376        if (pathname) {
 377                const char *ep = pathname + strlen(pathname);
 378                if (pathname < ep--) {
 379                        if (*ep != '/')
 380                                i++;
 381                        while (pathname <= ep)
 382                                if (*ep-- == '/')
 383                                        i += 2;
 384                }
 385        }
 386        return i;
 387}
 388
 389/**
 390 * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
 391 *
 392 * @filename: The string to evaluate.
 393 *
 394 * Returns the initial length without a pattern in @filename.
 395 */
 396static int tomoyo_const_part_length(const char *filename)
 397{
 398        char c;
 399        int len = 0;
 400
 401        if (!filename)
 402                return 0;
 403        while ((c = *filename++) != '\0') {
 404                if (c != '\\') {
 405                        len++;
 406                        continue;
 407                }
 408                c = *filename++;
 409                switch (c) {
 410                case '\\':  /* "\\" */
 411                        len += 2;
 412                        continue;
 413                case '0':   /* "\ooo" */
 414                case '1':
 415                case '2':
 416                case '3':
 417                        c = *filename++;
 418                        if (c < '0' || c > '7')
 419                                break;
 420                        c = *filename++;
 421                        if (c < '0' || c > '7')
 422                                break;
 423                        len += 4;
 424                        continue;
 425                }
 426                break;
 427        }
 428        return len;
 429}
 430
 431/**
 432 * tomoyo_fill_path_info - Fill in "struct tomoyo_path_info" members.
 433 *
 434 * @ptr: Pointer to "struct tomoyo_path_info" to fill in.
 435 *
 436 * The caller sets "struct tomoyo_path_info"->name.
 437 */
 438void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
 439{
 440        const char *name = ptr->name;
 441        const int len = strlen(name);
 442
 443        ptr->const_len = tomoyo_const_part_length(name);
 444        ptr->is_dir = len && (name[len - 1] == '/');
 445        ptr->is_patterned = (ptr->const_len < len);
 446        ptr->hash = full_name_hash(name, len);
 447        ptr->depth = tomoyo_path_depth(name);
 448}
 449
 450/**
 451 * tomoyo_file_matches_to_pattern2 - Pattern matching without '/' character
 452 * and "\-" pattern.
 453 *
 454 * @filename:     The start of string to check.
 455 * @filename_end: The end of string to check.
 456 * @pattern:      The start of pattern to compare.
 457 * @pattern_end:  The end of pattern to compare.
 458 *
 459 * Returns true if @filename matches @pattern, false otherwise.
 460 */
 461static bool tomoyo_file_matches_to_pattern2(const char *filename,
 462                                            const char *filename_end,
 463                                            const char *pattern,
 464                                            const char *pattern_end)
 465{
 466        while (filename < filename_end && pattern < pattern_end) {
 467                char c;
 468                if (*pattern != '\\') {
 469                        if (*filename++ != *pattern++)
 470                                return false;
 471                        continue;
 472                }
 473                c = *filename;
 474                pattern++;
 475                switch (*pattern) {
 476                        int i;
 477                        int j;
 478                case '?':
 479                        if (c == '/') {
 480                                return false;
 481                        } else if (c == '\\') {
 482                                if (filename[1] == '\\')
 483                                        filename++;
 484                                else if (tomoyo_is_byte_range(filename + 1))
 485                                        filename += 3;
 486                                else
 487                                        return false;
 488                        }
 489                        break;
 490                case '\\':
 491                        if (c != '\\')
 492                                return false;
 493                        if (*++filename != '\\')
 494                                return false;
 495                        break;
 496                case '+':
 497                        if (!isdigit(c))
 498                                return false;
 499                        break;
 500                case 'x':
 501                        if (!isxdigit(c))
 502                                return false;
 503                        break;
 504                case 'a':
 505                        if (!tomoyo_is_alphabet_char(c))
 506                                return false;
 507                        break;
 508                case '0':
 509                case '1':
 510                case '2':
 511                case '3':
 512                        if (c == '\\' && tomoyo_is_byte_range(filename + 1)
 513                            && strncmp(filename + 1, pattern, 3) == 0) {
 514                                filename += 3;
 515                                pattern += 2;
 516                                break;
 517                        }
 518                        return false; /* Not matched. */
 519                case '*':
 520                case '@':
 521                        for (i = 0; i <= filename_end - filename; i++) {
 522                                if (tomoyo_file_matches_to_pattern2(
 523                                                    filename + i, filename_end,
 524                                                    pattern + 1, pattern_end))
 525                                        return true;
 526                                c = filename[i];
 527                                if (c == '.' && *pattern == '@')
 528                                        break;
 529                                if (c != '\\')
 530                                        continue;
 531                                if (filename[i + 1] == '\\')
 532                                        i++;
 533                                else if (tomoyo_is_byte_range(filename + i + 1))
 534                                        i += 3;
 535                                else
 536                                        break; /* Bad pattern. */
 537                        }
 538                        return false; /* Not matched. */
 539                default:
 540                        j = 0;
 541                        c = *pattern;
 542                        if (c == '$') {
 543                                while (isdigit(filename[j]))
 544                                        j++;
 545                        } else if (c == 'X') {
 546                                while (isxdigit(filename[j]))
 547                                        j++;
 548                        } else if (c == 'A') {
 549                                while (tomoyo_is_alphabet_char(filename[j]))
 550                                        j++;
 551                        }
 552                        for (i = 1; i <= j; i++) {
 553                                if (tomoyo_file_matches_to_pattern2(
 554                                                    filename + i, filename_end,
 555                                                    pattern + 1, pattern_end))
 556                                        return true;
 557                        }
 558                        return false; /* Not matched or bad pattern. */
 559                }
 560                filename++;
 561                pattern++;
 562        }
 563        while (*pattern == '\\' &&
 564               (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
 565                pattern += 2;
 566        return filename == filename_end && pattern == pattern_end;
 567}
 568
 569/**
 570 * tomoyo_file_matches_to_pattern - Pattern matching without without '/' character.
 571 *
 572 * @filename:     The start of string to check.
 573 * @filename_end: The end of string to check.
 574 * @pattern:      The start of pattern to compare.
 575 * @pattern_end:  The end of pattern to compare.
 576 *
 577 * Returns true if @filename matches @pattern, false otherwise.
 578 */
 579static bool tomoyo_file_matches_to_pattern(const char *filename,
 580                                           const char *filename_end,
 581                                           const char *pattern,
 582                                           const char *pattern_end)
 583{
 584        const char *pattern_start = pattern;
 585        bool first = true;
 586        bool result;
 587
 588        while (pattern < pattern_end - 1) {
 589                /* Split at "\-" pattern. */
 590                if (*pattern++ != '\\' || *pattern++ != '-')
 591                        continue;
 592                result = tomoyo_file_matches_to_pattern2(filename,
 593                                                         filename_end,
 594                                                         pattern_start,
 595                                                         pattern - 2);
 596                if (first)
 597                        result = !result;
 598                if (result)
 599                        return false;
 600                first = false;
 601                pattern_start = pattern;
 602        }
 603        result = tomoyo_file_matches_to_pattern2(filename, filename_end,
 604                                                 pattern_start, pattern_end);
 605        return first ? result : !result;
 606}
 607
 608/**
 609 * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
 610 * @filename: The filename to check.
 611 * @pattern:  The pattern to compare.
 612 *
 613 * Returns true if matches, false otherwise.
 614 *
 615 * The following patterns are available.
 616 *   \\     \ itself.
 617 *   \ooo   Octal representation of a byte.
 618 *   \*     More than or equals to 0 character other than '/'.
 619 *   \@     More than or equals to 0 character other than '/' or '.'.
 620 *   \?     1 byte character other than '/'.
 621 *   \$     More than or equals to 1 decimal digit.
 622 *   \+     1 decimal digit.
 623 *   \X     More than or equals to 1 hexadecimal digit.
 624 *   \x     1 hexadecimal digit.
 625 *   \A     More than or equals to 1 alphabet character.
 626 *   \a     1 alphabet character.
 627 *   \-     Subtraction operator.
 628 */
 629bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
 630                                 const struct tomoyo_path_info *pattern)
 631{
 632        /*
 633          if (!filename || !pattern)
 634          return false;
 635        */
 636        const char *f = filename->name;
 637        const char *p = pattern->name;
 638        const int len = pattern->const_len;
 639
 640        /* If @pattern doesn't contain pattern, I can use strcmp(). */
 641        if (!pattern->is_patterned)
 642                return !tomoyo_pathcmp(filename, pattern);
 643        /* Dont compare if the number of '/' differs. */
 644        if (filename->depth != pattern->depth)
 645                return false;
 646        /* Compare the initial length without patterns. */
 647        if (strncmp(f, p, len))
 648                return false;
 649        f += len;
 650        p += len;
 651        /* Main loop. Compare each directory component. */
 652        while (*f && *p) {
 653                const char *f_delimiter = strchr(f, '/');
 654                const char *p_delimiter = strchr(p, '/');
 655                if (!f_delimiter)
 656                        f_delimiter = f + strlen(f);
 657                if (!p_delimiter)
 658                        p_delimiter = p + strlen(p);
 659                if (!tomoyo_file_matches_to_pattern(f, f_delimiter,
 660                                                    p, p_delimiter))
 661                        return false;
 662                f = f_delimiter;
 663                if (*f)
 664                        f++;
 665                p = p_delimiter;
 666                if (*p)
 667                        p++;
 668        }
 669        /* Ignore trailing "\*" and "\@" in @pattern. */
 670        while (*p == '\\' &&
 671               (*(p + 1) == '*' || *(p + 1) == '@'))
 672                p += 2;
 673        return !*f && !*p;
 674}
 675
 676/**
 677 * tomoyo_io_printf - Transactional printf() to "struct tomoyo_io_buffer" structure.
 678 *
 679 * @head: Pointer to "struct tomoyo_io_buffer".
 680 * @fmt:  The printf()'s format string, followed by parameters.
 681 *
 682 * Returns true if output was written, false otherwise.
 683 *
 684 * The snprintf() will truncate, but tomoyo_io_printf() won't.
 685 */
 686bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
 687{
 688        va_list args;
 689        int len;
 690        int pos = head->read_avail;
 691        int size = head->readbuf_size - pos;
 692
 693        if (size <= 0)
 694                return false;
 695        va_start(args, fmt);
 696        len = vsnprintf(head->read_buf + pos, size, fmt, args);
 697        va_end(args);
 698        if (pos + len >= head->readbuf_size)
 699                return false;
 700        head->read_avail += len;
 701        return true;
 702}
 703
 704/**
 705 * tomoyo_get_exe - Get tomoyo_realpath() of current process.
 706 *
 707 * Returns the tomoyo_realpath() of current process on success, NULL otherwise.
 708 *
 709 * This function uses tomoyo_alloc(), so the caller must call tomoyo_free()
 710 * if this function didn't return NULL.
 711 */
 712static const char *tomoyo_get_exe(void)
 713{
 714        struct mm_struct *mm = current->mm;
 715        struct vm_area_struct *vma;
 716        const char *cp = NULL;
 717
 718        if (!mm)
 719                return NULL;
 720        down_read(&mm->mmap_sem);
 721        for (vma = mm->mmap; vma; vma = vma->vm_next) {
 722                if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
 723                        cp = tomoyo_realpath_from_path(&vma->vm_file->f_path);
 724                        break;
 725                }
 726        }
 727        up_read(&mm->mmap_sem);
 728        return cp;
 729}
 730
 731/**
 732 * tomoyo_get_msg - Get warning message.
 733 *
 734 * @is_enforce: Is it enforcing mode?
 735 *
 736 * Returns "ERROR" or "WARNING".
 737 */
 738const char *tomoyo_get_msg(const bool is_enforce)
 739{
 740        if (is_enforce)
 741                return "ERROR";
 742        else
 743                return "WARNING";
 744}
 745
 746/**
 747 * tomoyo_check_flags - Check mode for specified functionality.
 748 *
 749 * @domain: Pointer to "struct tomoyo_domain_info".
 750 * @index:  The functionality to check mode.
 751 *
 752 * TOMOYO checks only process context.
 753 * This code disables TOMOYO's enforcement in case the function is called from
 754 * interrupt context.
 755 */
 756unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
 757                                const u8 index)
 758{
 759        const u8 profile = domain->profile;
 760
 761        if (WARN_ON(in_interrupt()))
 762                return 0;
 763        return tomoyo_policy_loaded && index < TOMOYO_MAX_CONTROL_INDEX
 764#if TOMOYO_MAX_PROFILES != 256
 765                && profile < TOMOYO_MAX_PROFILES
 766#endif
 767                && tomoyo_profile_ptr[profile] ?
 768                tomoyo_profile_ptr[profile]->value[index] : 0;
 769}
 770
 771/**
 772 * tomoyo_verbose_mode - Check whether TOMOYO is verbose mode.
 773 *
 774 * @domain: Pointer to "struct tomoyo_domain_info".
 775 *
 776 * Returns true if domain policy violation warning should be printed to
 777 * console.
 778 */
 779bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain)
 780{
 781        return tomoyo_check_flags(domain, TOMOYO_VERBOSE) != 0;
 782}
 783
 784/**
 785 * tomoyo_domain_quota_is_ok - Check for domain's quota.
 786 *
 787 * @domain: Pointer to "struct tomoyo_domain_info".
 788 *
 789 * Returns true if the domain is not exceeded quota, false otherwise.
 790 */
 791bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)
 792{
 793        unsigned int count = 0;
 794        struct tomoyo_acl_info *ptr;
 795
 796        if (!domain)
 797                return true;
 798        down_read(&tomoyo_domain_acl_info_list_lock);
 799        list_for_each_entry(ptr, &domain->acl_info_list, list) {
 800                if (ptr->type & TOMOYO_ACL_DELETED)
 801                        continue;
 802                switch (tomoyo_acl_type2(ptr)) {
 803                        struct tomoyo_single_path_acl_record *acl1;
 804                        struct tomoyo_double_path_acl_record *acl2;
 805                        u16 perm;
 806                case TOMOYO_TYPE_SINGLE_PATH_ACL:
 807                        acl1 = container_of(ptr,
 808                                    struct tomoyo_single_path_acl_record,
 809                                            head);
 810                        perm = acl1->perm;
 811                        if (perm & (1 << TOMOYO_TYPE_EXECUTE_ACL))
 812                                count++;
 813                        if (perm &
 814                            ((1 << TOMOYO_TYPE_READ_ACL) |
 815                             (1 << TOMOYO_TYPE_WRITE_ACL)))
 816                                count++;
 817                        if (perm & (1 << TOMOYO_TYPE_CREATE_ACL))
 818                                count++;
 819                        if (perm & (1 << TOMOYO_TYPE_UNLINK_ACL))
 820                                count++;
 821                        if (perm & (1 << TOMOYO_TYPE_MKDIR_ACL))
 822                                count++;
 823                        if (perm & (1 << TOMOYO_TYPE_RMDIR_ACL))
 824                                count++;
 825                        if (perm & (1 << TOMOYO_TYPE_MKFIFO_ACL))
 826                                count++;
 827                        if (perm & (1 << TOMOYO_TYPE_MKSOCK_ACL))
 828                                count++;
 829                        if (perm & (1 << TOMOYO_TYPE_MKBLOCK_ACL))
 830                                count++;
 831                        if (perm & (1 << TOMOYO_TYPE_MKCHAR_ACL))
 832                                count++;
 833                        if (perm & (1 << TOMOYO_TYPE_TRUNCATE_ACL))
 834                                count++;
 835                        if (perm & (1 << TOMOYO_TYPE_SYMLINK_ACL))
 836                                count++;
 837                        if (perm & (1 << TOMOYO_TYPE_REWRITE_ACL))
 838                                count++;
 839                        break;
 840                case TOMOYO_TYPE_DOUBLE_PATH_ACL:
 841                        acl2 = container_of(ptr,
 842                                    struct tomoyo_double_path_acl_record,
 843                                            head);
 844                        perm = acl2->perm;
 845                        if (perm & (1 << TOMOYO_TYPE_LINK_ACL))
 846                                count++;
 847                        if (perm & (1 << TOMOYO_TYPE_RENAME_ACL))
 848                                count++;
 849                        break;
 850                }
 851        }
 852        up_read(&tomoyo_domain_acl_info_list_lock);
 853        if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY))
 854                return true;
 855        if (!domain->quota_warned) {
 856                domain->quota_warned = true;
 857                printk(KERN_WARNING "TOMOYO-WARNING: "
 858                       "Domain '%s' has so many ACLs to hold. "
 859                       "Stopped learning mode.\n", domain->domainname->name);
 860        }
 861        return false;
 862}
 863
 864/**
 865 * tomoyo_find_or_assign_new_profile - Create a new profile.
 866 *
 867 * @profile: Profile number to create.
 868 *
 869 * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise.
 870 */
 871static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned
 872                                                                int profile)
 873{
 874        static DEFINE_MUTEX(lock);
 875        struct tomoyo_profile *ptr = NULL;
 876        int i;
 877
 878        if (profile >= TOMOYO_MAX_PROFILES)
 879                return NULL;
 880        mutex_lock(&lock);
 881        ptr = tomoyo_profile_ptr[profile];
 882        if (ptr)
 883                goto ok;
 884        ptr = tomoyo_alloc_element(sizeof(*ptr));
 885        if (!ptr)
 886                goto ok;
 887        for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++)
 888                ptr->value[i] = tomoyo_control_array[i].current_value;
 889        mb(); /* Avoid out-of-order execution. */
 890        tomoyo_profile_ptr[profile] = ptr;
 891 ok:
 892        mutex_unlock(&lock);
 893        return ptr;
 894}
 895
 896/**
 897 * tomoyo_write_profile - Write to profile table.
 898 *
 899 * @head: Pointer to "struct tomoyo_io_buffer".
 900 *
 901 * Returns 0 on success, negative value otherwise.
 902 */
 903static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
 904{
 905        char *data = head->write_buf;
 906        unsigned int i;
 907        unsigned int value;
 908        char *cp;
 909        struct tomoyo_profile *profile;
 910        unsigned long num;
 911
 912        cp = strchr(data, '-');
 913        if (cp)
 914                *cp = '\0';
 915        if (strict_strtoul(data, 10, &num))
 916                return -EINVAL;
 917        if (cp)
 918                data = cp + 1;
 919        profile = tomoyo_find_or_assign_new_profile(num);
 920        if (!profile)
 921                return -EINVAL;
 922        cp = strchr(data, '=');
 923        if (!cp)
 924                return -EINVAL;
 925        *cp = '\0';
 926        if (!strcmp(data, "COMMENT")) {
 927                profile->comment = tomoyo_save_name(cp + 1);
 928                return 0;
 929        }
 930        for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) {
 931                if (strcmp(data, tomoyo_control_array[i].keyword))
 932                        continue;
 933                if (sscanf(cp + 1, "%u", &value) != 1) {
 934                        int j;
 935                        const char **modes;
 936                        switch (i) {
 937                        case TOMOYO_VERBOSE:
 938                                modes = tomoyo_mode_2;
 939                                break;
 940                        default:
 941                                modes = tomoyo_mode_4;
 942                                break;
 943                        }
 944                        for (j = 0; j < 4; j++) {
 945                                if (strcmp(cp + 1, modes[j]))
 946                                        continue;
 947                                value = j;
 948                                break;
 949                        }
 950                        if (j == 4)
 951                                return -EINVAL;
 952                } else if (value > tomoyo_control_array[i].max_value) {
 953                        value = tomoyo_control_array[i].max_value;
 954                }
 955                profile->value[i] = value;
 956                return 0;
 957        }
 958        return -EINVAL;
 959}
 960
 961/**
 962 * tomoyo_read_profile - Read from profile table.
 963 *
 964 * @head: Pointer to "struct tomoyo_io_buffer".
 965 *
 966 * Returns 0.
 967 */
 968static int tomoyo_read_profile(struct tomoyo_io_buffer *head)
 969{
 970        static const int total = TOMOYO_MAX_CONTROL_INDEX + 1;
 971        int step;
 972
 973        if (head->read_eof)
 974                return 0;
 975        for (step = head->read_step; step < TOMOYO_MAX_PROFILES * total;
 976             step++) {
 977                const u8 index = step / total;
 978                u8 type = step % total;
 979                const struct tomoyo_profile *profile
 980                        = tomoyo_profile_ptr[index];
 981                head->read_step = step;
 982                if (!profile)
 983                        continue;
 984                if (!type) { /* Print profile' comment tag. */
 985                        if (!tomoyo_io_printf(head, "%u-COMMENT=%s\n",
 986                                              index, profile->comment ?
 987                                              profile->comment->name : ""))
 988                                break;
 989                        continue;
 990                }
 991                type--;
 992                if (type < TOMOYO_MAX_CONTROL_INDEX) {
 993                        const unsigned int value = profile->value[type];
 994                        const char **modes = NULL;
 995                        const char *keyword
 996                                = tomoyo_control_array[type].keyword;
 997                        switch (tomoyo_control_array[type].max_value) {
 998                        case 3:
 999                                modes = tomoyo_mode_4;
1000                                break;
1001                        case 1:
1002                                modes = tomoyo_mode_2;
1003                                break;
1004                        }
1005                        if (modes) {
1006                                if (!tomoyo_io_printf(head, "%u-%s=%s\n", index,
1007                                                      keyword, modes[value]))
1008                                        break;
1009                        } else {
1010                                if (!tomoyo_io_printf(head, "%u-%s=%u\n", index,
1011                                                      keyword, value))
1012                                        break;
1013                        }
1014                }
1015        }
1016        if (step == TOMOYO_MAX_PROFILES * total)
1017                head->read_eof = true;
1018        return 0;
1019}
1020
1021/*
1022 * tomoyo_policy_manager_entry is a structure which is used for holding list of
1023 * domainnames or programs which are permitted to modify configuration via
1024 * /sys/kernel/security/tomoyo/ interface.
1025 * It has following fields.
1026 *
1027 *  (1) "list" which is linked to tomoyo_policy_manager_list .
1028 *  (2) "manager" is a domainname or a program's pathname.
1029 *  (3) "is_domain" is a bool which is true if "manager" is a domainname, false
1030 *      otherwise.
1031 *  (4) "is_deleted" is a bool which is true if marked as deleted, false
1032 *      otherwise.
1033 */
1034struct tomoyo_policy_manager_entry {
1035        struct list_head list;
1036        /* A path to program or a domainname. */
1037        const struct tomoyo_path_info *manager;
1038        bool is_domain;  /* True if manager is a domainname. */
1039        bool is_deleted; /* True if this entry is deleted. */
1040};
1041
1042/*
1043 * tomoyo_policy_manager_list is used for holding list of domainnames or
1044 * programs which are permitted to modify configuration via
1045 * /sys/kernel/security/tomoyo/ interface.
1046 *
1047 * An entry is added by
1048 *
1049 * # echo '<kernel> /sbin/mingetty /bin/login /bin/bash' > \
1050 *                                        /sys/kernel/security/tomoyo/manager
1051 *  (if you want to specify by a domainname)
1052 *
1053 *  or
1054 *
1055 * # echo '/usr/lib/ccs/editpolicy' > /sys/kernel/security/tomoyo/manager
1056 *  (if you want to specify by a program's location)
1057 *
1058 * and is deleted by
1059 *
1060 * # echo 'delete <kernel> /sbin/mingetty /bin/login /bin/bash' > \
1061 *                                        /sys/kernel/security/tomoyo/manager
1062 *
1063 *  or
1064 *
1065 * # echo 'delete /usr/lib/ccs/editpolicy' > \
1066 *                                        /sys/kernel/security/tomoyo/manager
1067 *
1068 * and all entries are retrieved by
1069 *
1070 * # cat /sys/kernel/security/tomoyo/manager
1071 */
1072static LIST_HEAD(tomoyo_policy_manager_list);
1073static DECLARE_RWSEM(tomoyo_policy_manager_list_lock);
1074
1075/**
1076 * tomoyo_update_manager_entry - Add a manager entry.
1077 *
1078 * @manager:   The path to manager or the domainnamme.
1079 * @is_delete: True if it is a delete request.
1080 *
1081 * Returns 0 on success, negative value otherwise.
1082 */
1083static int tomoyo_update_manager_entry(const char *manager,
1084                                       const bool is_delete)
1085{
1086        struct tomoyo_policy_manager_entry *new_entry;
1087        struct tomoyo_policy_manager_entry *ptr;
1088        const struct tomoyo_path_info *saved_manager;
1089        int error = -ENOMEM;
1090        bool is_domain = false;
1091
1092        if (tomoyo_is_domain_def(manager)) {
1093                if (!tomoyo_is_correct_domain(manager, __func__))
1094                        return -EINVAL;
1095                is_domain = true;
1096        } else {
1097                if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__))
1098                        return -EINVAL;
1099        }
1100        saved_manager = tomoyo_save_name(manager);
1101        if (!saved_manager)
1102                return -ENOMEM;
1103        down_write(&tomoyo_policy_manager_list_lock);
1104        list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
1105                if (ptr->manager != saved_manager)
1106                        continue;
1107                ptr->is_deleted = is_delete;
1108                error = 0;
1109                goto out;
1110        }
1111        if (is_delete) {
1112                error = -ENOENT;
1113                goto out;
1114        }
1115        new_entry = tomoyo_alloc_element(sizeof(*new_entry));
1116        if (!new_entry)
1117                goto out;
1118        new_entry->manager = saved_manager;
1119        new_entry->is_domain = is_domain;
1120        list_add_tail(&new_entry->list, &tomoyo_policy_manager_list);
1121        error = 0;
1122 out:
1123        up_write(&tomoyo_policy_manager_list_lock);
1124        return error;
1125}
1126
1127/**
1128 * tomoyo_write_manager_policy - Write manager policy.
1129 *
1130 * @head: Pointer to "struct tomoyo_io_buffer".
1131 *
1132 * Returns 0 on success, negative value otherwise.
1133 */
1134static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head)
1135{
1136        char *data = head->write_buf;
1137        bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE);
1138
1139        if (!strcmp(data, "manage_by_non_root")) {
1140                tomoyo_manage_by_non_root = !is_delete;
1141                return 0;
1142        }
1143        return tomoyo_update_manager_entry(data, is_delete);
1144}
1145
1146/**
1147 * tomoyo_read_manager_policy - Read manager policy.
1148 *
1149 * @head: Pointer to "struct tomoyo_io_buffer".
1150 *
1151 * Returns 0.
1152 */
1153static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
1154{
1155        struct list_head *pos;
1156        bool done = true;
1157
1158        if (head->read_eof)
1159                return 0;
1160        down_read(&tomoyo_policy_manager_list_lock);
1161        list_for_each_cookie(pos, head->read_var2,
1162                             &tomoyo_policy_manager_list) {
1163                struct tomoyo_policy_manager_entry *ptr;
1164                ptr = list_entry(pos, struct tomoyo_policy_manager_entry,
1165                                 list);
1166                if (ptr->is_deleted)
1167                        continue;
1168                done = tomoyo_io_printf(head, "%s\n", ptr->manager->name);
1169                if (!done)
1170                        break;
1171        }
1172        up_read(&tomoyo_policy_manager_list_lock);
1173        head->read_eof = done;
1174        return 0;
1175}
1176
1177/**
1178 * tomoyo_is_policy_manager - Check whether the current process is a policy manager.
1179 *
1180 * Returns true if the current process is permitted to modify policy
1181 * via /sys/kernel/security/tomoyo/ interface.
1182 */
1183static bool tomoyo_is_policy_manager(void)
1184{
1185        struct tomoyo_policy_manager_entry *ptr;
1186        const char *exe;
1187        const struct task_struct *task = current;
1188        const struct tomoyo_path_info *domainname = tomoyo_domain()->domainname;
1189        bool found = false;
1190
1191        if (!tomoyo_policy_loaded)
1192                return true;
1193        if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid))
1194                return false;
1195        down_read(&tomoyo_policy_manager_list_lock);
1196        list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
1197                if (!ptr->is_deleted && ptr->is_domain
1198                    && !tomoyo_pathcmp(domainname, ptr->manager)) {
1199                        found = true;
1200                        break;
1201                }
1202        }
1203        up_read(&tomoyo_policy_manager_list_lock);
1204        if (found)
1205                return true;
1206        exe = tomoyo_get_exe();
1207        if (!exe)
1208                return false;
1209        down_read(&tomoyo_policy_manager_list_lock);
1210        list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
1211                if (!ptr->is_deleted && !ptr->is_domain
1212                    && !strcmp(exe, ptr->manager->name)) {
1213                        found = true;
1214                        break;
1215                }
1216        }
1217        up_read(&tomoyo_policy_manager_list_lock);
1218        if (!found) { /* Reduce error messages. */
1219                static pid_t last_pid;
1220                const pid_t pid = current->pid;
1221                if (last_pid != pid) {
1222                        printk(KERN_WARNING "%s ( %s ) is not permitted to "
1223                               "update policies.\n", domainname->name, exe);
1224                        last_pid = pid;
1225                }
1226        }
1227        tomoyo_free(exe);
1228        return found;
1229}
1230
1231/**
1232 * tomoyo_is_select_one - Parse select command.
1233 *
1234 * @head: Pointer to "struct tomoyo_io_buffer".
1235 * @data: String to parse.
1236 *
1237 * Returns true on success, false otherwise.
1238 */
1239static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
1240                                 const char *data)
1241{
1242        unsigned int pid;
1243        struct tomoyo_domain_info *domain = NULL;
1244
1245        if (sscanf(data, "pid=%u", &pid) == 1) {
1246                struct task_struct *p;
1247                read_lock(&tasklist_lock);
1248                p = find_task_by_vpid(pid);
1249                if (p)
1250                        domain = tomoyo_real_domain(p);
1251                read_unlock(&tasklist_lock);
1252        } else if (!strncmp(data, "domain=", 7)) {
1253                if (tomoyo_is_domain_def(data + 7)) {
1254                        down_read(&tomoyo_domain_list_lock);
1255                        domain = tomoyo_find_domain(data + 7);
1256                        up_read(&tomoyo_domain_list_lock);
1257                }
1258        } else
1259                return false;
1260        head->write_var1 = domain;
1261        /* Accessing read_buf is safe because head->io_sem is held. */
1262        if (!head->read_buf)
1263                return true; /* Do nothing if open(O_WRONLY). */
1264        head->read_avail = 0;
1265        tomoyo_io_printf(head, "# select %s\n", data);
1266        head->read_single_domain = true;
1267        head->read_eof = !domain;
1268        if (domain) {
1269                struct tomoyo_domain_info *d;
1270                head->read_var1 = NULL;
1271                down_read(&tomoyo_domain_list_lock);
1272                list_for_each_entry(d, &tomoyo_domain_list, list) {
1273                        if (d == domain)
1274                                break;
1275                        head->read_var1 = &d->list;
1276                }
1277                up_read(&tomoyo_domain_list_lock);
1278                head->read_var2 = NULL;
1279                head->read_bit = 0;
1280                head->read_step = 0;
1281                if (domain->is_deleted)
1282                        tomoyo_io_printf(head, "# This is a deleted domain.\n");
1283        }
1284        return true;
1285}
1286
1287/**
1288 * tomoyo_delete_domain - Delete a domain.
1289 *
1290 * @domainname: The name of domain.
1291 *
1292 * Returns 0.
1293 */
1294static int tomoyo_delete_domain(char *domainname)
1295{
1296        struct tomoyo_domain_info *domain;
1297        struct tomoyo_path_info name;
1298
1299        name.name = domainname;
1300        tomoyo_fill_path_info(&name);
1301        down_write(&tomoyo_domain_list_lock);
1302        /* Is there an active domain? */
1303        list_for_each_entry(domain, &tomoyo_domain_list, list) {
1304                /* Never delete tomoyo_kernel_domain */
1305                if (domain == &tomoyo_kernel_domain)
1306                        continue;
1307                if (domain->is_deleted ||
1308                    tomoyo_pathcmp(domain->domainname, &name))
1309                        continue;
1310                domain->is_deleted = true;
1311                break;
1312        }
1313        up_write(&tomoyo_domain_list_lock);
1314        return 0;
1315}
1316
1317/**
1318 * tomoyo_write_domain_policy - Write domain policy.
1319 *
1320 * @head: Pointer to "struct tomoyo_io_buffer".
1321 *
1322 * Returns 0 on success, negative value otherwise.
1323 */
1324static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
1325{
1326        char *data = head->write_buf;
1327        struct tomoyo_domain_info *domain = head->write_var1;
1328        bool is_delete = false;
1329        bool is_select = false;
1330        unsigned int profile;
1331
1332        if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE))
1333                is_delete = true;
1334        else if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_SELECT))
1335                is_select = true;
1336        if (is_select && tomoyo_is_select_one(head, data))
1337                return 0;
1338        /* Don't allow updating policies by non manager programs. */
1339        if (!tomoyo_is_policy_manager())
1340                return -EPERM;
1341        if (tomoyo_is_domain_def(data)) {
1342                domain = NULL;
1343                if (is_delete)
1344                        tomoyo_delete_domain(data);
1345                else if (is_select) {
1346                        down_read(&tomoyo_domain_list_lock);
1347                        domain = tomoyo_find_domain(data);
1348                        up_read(&tomoyo_domain_list_lock);
1349                } else
1350                        domain = tomoyo_find_or_assign_new_domain(data, 0);
1351                head->write_var1 = domain;
1352                return 0;
1353        }
1354        if (!domain)
1355                return -EINVAL;
1356
1357        if (sscanf(data, TOMOYO_KEYWORD_USE_PROFILE "%u", &profile) == 1
1358            && profile < TOMOYO_MAX_PROFILES) {
1359                if (tomoyo_profile_ptr[profile] || !tomoyo_policy_loaded)
1360                        domain->profile = (u8) profile;
1361                return 0;
1362        }
1363        if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
1364                tomoyo_set_domain_flag(domain, is_delete,
1365                               TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ);
1366                return 0;
1367        }
1368        return tomoyo_write_file_policy(data, domain, is_delete);
1369}
1370
1371/**
1372 * tomoyo_print_single_path_acl - Print a single path ACL entry.
1373 *
1374 * @head: Pointer to "struct tomoyo_io_buffer".
1375 * @ptr:  Pointer to "struct tomoyo_single_path_acl_record".
1376 *
1377 * Returns true on success, false otherwise.
1378 */
1379static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head,
1380                                         struct tomoyo_single_path_acl_record *
1381                                         ptr)
1382{
1383        int pos;
1384        u8 bit;
1385        const char *atmark = "";
1386        const char *filename;
1387        const u16 perm = ptr->perm;
1388
1389        filename = ptr->filename->name;
1390        for (bit = head->read_bit; bit < TOMOYO_MAX_SINGLE_PATH_OPERATION;
1391             bit++) {
1392                const char *msg;
1393                if (!(perm & (1 << bit)))
1394                        continue;
1395                /* Print "read/write" instead of "read" and "write". */
1396                if ((bit == TOMOYO_TYPE_READ_ACL ||
1397                     bit == TOMOYO_TYPE_WRITE_ACL)
1398                    && (perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
1399                        continue;
1400                msg = tomoyo_sp2keyword(bit);
1401                pos = head->read_avail;
1402                if (!tomoyo_io_printf(head, "allow_%s %s%s\n", msg,
1403                                      atmark, filename))
1404                        goto out;
1405        }
1406        head->read_bit = 0;
1407        return true;
1408 out:
1409        head->read_bit = bit;
1410        head->read_avail = pos;
1411        return false;
1412}
1413
1414/**
1415 * tomoyo_print_double_path_acl - Print a double path ACL entry.
1416 *
1417 * @head: Pointer to "struct tomoyo_io_buffer".
1418 * @ptr:  Pointer to "struct tomoyo_double_path_acl_record".
1419 *
1420 * Returns true on success, false otherwise.
1421 */
1422static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head,
1423                                         struct tomoyo_double_path_acl_record *
1424                                         ptr)
1425{
1426        int pos;
1427        const char *atmark1 = "";
1428        const char *atmark2 = "";
1429        const char *filename1;
1430        const char *filename2;
1431        const u8 perm = ptr->perm;
1432        u8 bit;
1433
1434        filename1 = ptr->filename1->name;
1435        filename2 = ptr->filename2->name;
1436        for (bit = head->read_bit; bit < TOMOYO_MAX_DOUBLE_PATH_OPERATION;
1437             bit++) {
1438                const char *msg;
1439                if (!(perm & (1 << bit)))
1440                        continue;
1441                msg = tomoyo_dp2keyword(bit);
1442                pos = head->read_avail;
1443                if (!tomoyo_io_printf(head, "allow_%s %s%s %s%s\n", msg,
1444                                      atmark1, filename1, atmark2, filename2))
1445                        goto out;
1446        }
1447        head->read_bit = 0;
1448        return true;
1449 out:
1450        head->read_bit = bit;
1451        head->read_avail = pos;
1452        return false;
1453}
1454
1455/**
1456 * tomoyo_print_entry - Print an ACL entry.
1457 *
1458 * @head: Pointer to "struct tomoyo_io_buffer".
1459 * @ptr:  Pointer to an ACL entry.
1460 *
1461 * Returns true on success, false otherwise.
1462 */
1463static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
1464                               struct tomoyo_acl_info *ptr)
1465{
1466        const u8 acl_type = tomoyo_acl_type2(ptr);
1467
1468        if (acl_type & TOMOYO_ACL_DELETED)
1469                return true;
1470        if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) {
1471                struct tomoyo_single_path_acl_record *acl
1472                        = container_of(ptr,
1473                                       struct tomoyo_single_path_acl_record,
1474                                       head);
1475                return tomoyo_print_single_path_acl(head, acl);
1476        }
1477        if (acl_type == TOMOYO_TYPE_DOUBLE_PATH_ACL) {
1478                struct tomoyo_double_path_acl_record *acl
1479                        = container_of(ptr,
1480                                       struct tomoyo_double_path_acl_record,
1481                                       head);
1482                return tomoyo_print_double_path_acl(head, acl);
1483        }
1484        BUG(); /* This must not happen. */
1485        return false;
1486}
1487
1488/**
1489 * tomoyo_read_domain_policy - Read domain policy.
1490 *
1491 * @head: Pointer to "struct tomoyo_io_buffer".
1492 *
1493 * Returns 0.
1494 */
1495static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
1496{
1497        struct list_head *dpos;
1498        struct list_head *apos;
1499        bool done = true;
1500
1501        if (head->read_eof)
1502                return 0;
1503        if (head->read_step == 0)
1504                head->read_step = 1;
1505        down_read(&tomoyo_domain_list_lock);
1506        list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) {
1507                struct tomoyo_domain_info *domain;
1508                const char *quota_exceeded = "";
1509                const char *transition_failed = "";
1510                const char *ignore_global_allow_read = "";
1511                domain = list_entry(dpos, struct tomoyo_domain_info, list);
1512                if (head->read_step != 1)
1513                        goto acl_loop;
1514                if (domain->is_deleted && !head->read_single_domain)
1515                        continue;
1516                /* Print domainname and flags. */
1517                if (domain->quota_warned)
1518                        quota_exceeded = "quota_exceeded\n";
1519                if (domain->flags & TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED)
1520                        transition_failed = "transition_failed\n";
1521                if (domain->flags &
1522                    TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ)
1523                        ignore_global_allow_read
1524                                = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
1525                done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE
1526                                        "%u\n%s%s%s\n",
1527                                        domain->domainname->name,
1528                                        domain->profile, quota_exceeded,
1529                                        transition_failed,
1530                                        ignore_global_allow_read);
1531                if (!done)
1532                        break;
1533                head->read_step = 2;
1534acl_loop:
1535                if (head->read_step == 3)
1536                        goto tail_mark;
1537                /* Print ACL entries in the domain. */
1538                down_read(&tomoyo_domain_acl_info_list_lock);
1539                list_for_each_cookie(apos, head->read_var2,
1540                                     &domain->acl_info_list) {
1541                        struct tomoyo_acl_info *ptr
1542                                = list_entry(apos, struct tomoyo_acl_info,
1543                                             list);
1544                        done = tomoyo_print_entry(head, ptr);
1545                        if (!done)
1546                                break;
1547                }
1548                up_read(&tomoyo_domain_acl_info_list_lock);
1549                if (!done)
1550                        break;
1551                head->read_step = 3;
1552tail_mark:
1553                done = tomoyo_io_printf(head, "\n");
1554                if (!done)
1555                        break;
1556                head->read_step = 1;
1557                if (head->read_single_domain)
1558                        break;
1559        }
1560        up_read(&tomoyo_domain_list_lock);
1561        head->read_eof = done;
1562        return 0;
1563}
1564
1565/**
1566 * tomoyo_write_domain_profile - Assign profile for specified domain.
1567 *
1568 * @head: Pointer to "struct tomoyo_io_buffer".
1569 *
1570 * Returns 0 on success, -EINVAL otherwise.
1571 *
1572 * This is equivalent to doing
1573 *
1574 *     ( echo "select " $domainname; echo "use_profile " $profile ) |
1575 *     /usr/lib/ccs/loadpolicy -d
1576 */
1577static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
1578{
1579        char *data = head->write_buf;
1580        char *cp = strchr(data, ' ');
1581        struct tomoyo_domain_info *domain;
1582        unsigned long profile;
1583
1584        if (!cp)
1585                return -EINVAL;
1586        *cp = '\0';
1587        down_read(&tomoyo_domain_list_lock);
1588        domain = tomoyo_find_domain(cp + 1);
1589        up_read(&tomoyo_domain_list_lock);
1590        if (strict_strtoul(data, 10, &profile))
1591                return -EINVAL;
1592        if (domain && profile < TOMOYO_MAX_PROFILES
1593            && (tomoyo_profile_ptr[profile] || !tomoyo_policy_loaded))
1594                domain->profile = (u8) profile;
1595        return 0;
1596}
1597
1598/**
1599 * tomoyo_read_domain_profile - Read only domainname and profile.
1600 *
1601 * @head: Pointer to "struct tomoyo_io_buffer".
1602 *
1603 * Returns list of profile number and domainname pairs.
1604 *
1605 * This is equivalent to doing
1606 *
1607 *     grep -A 1 '^<kernel>' /sys/kernel/security/tomoyo/domain_policy |
1608 *     awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
1609 *     domainname = $0; } else if ( $1 == "use_profile" ) {
1610 *     print $2 " " domainname; domainname = ""; } } ; '
1611 */
1612static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
1613{
1614        struct list_head *pos;
1615        bool done = true;
1616
1617        if (head->read_eof)
1618                return 0;
1619        down_read(&tomoyo_domain_list_lock);
1620        list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) {
1621                struct tomoyo_domain_info *domain;
1622                domain = list_entry(pos, struct tomoyo_domain_info, list);
1623                if (domain->is_deleted)
1624                        continue;
1625                done = tomoyo_io_printf(head, "%u %s\n", domain->profile,
1626                                        domain->domainname->name);
1627                if (!done)
1628                        break;
1629        }
1630        up_read(&tomoyo_domain_list_lock);
1631        head->read_eof = done;
1632        return 0;
1633}
1634
1635/**
1636 * tomoyo_write_pid: Specify PID to obtain domainname.
1637 *
1638 * @head: Pointer to "struct tomoyo_io_buffer".
1639 *
1640 * Returns 0.
1641 */
1642static int tomoyo_write_pid(struct tomoyo_io_buffer *head)
1643{
1644        unsigned long pid;
1645        /* No error check. */
1646        strict_strtoul(head->write_buf, 10, &pid);
1647        head->read_step = (int) pid;
1648        head->read_eof = false;
1649        return 0;
1650}
1651
1652/**
1653 * tomoyo_read_pid - Get domainname of the specified PID.
1654 *
1655 * @head: Pointer to "struct tomoyo_io_buffer".
1656 *
1657 * Returns the domainname which the specified PID is in on success,
1658 * empty string otherwise.
1659 * The PID is specified by tomoyo_write_pid() so that the user can obtain
1660 * using read()/write() interface rather than sysctl() interface.
1661 */
1662static int tomoyo_read_pid(struct tomoyo_io_buffer *head)
1663{
1664        if (head->read_avail == 0 && !head->read_eof) {
1665                const int pid = head->read_step;
1666                struct task_struct *p;
1667                struct tomoyo_domain_info *domain = NULL;
1668                read_lock(&tasklist_lock);
1669                p = find_task_by_vpid(pid);
1670                if (p)
1671                        domain = tomoyo_real_domain(p);
1672                read_unlock(&tasklist_lock);
1673                if (domain)
1674                        tomoyo_io_printf(head, "%d %u %s", pid, domain->profile,
1675                                         domain->domainname->name);
1676                head->read_eof = true;
1677        }
1678        return 0;
1679}
1680
1681/**
1682 * tomoyo_write_exception_policy - Write exception policy.
1683 *
1684 * @head: Pointer to "struct tomoyo_io_buffer".
1685 *
1686 * Returns 0 on success, negative value otherwise.
1687 */
1688static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head)
1689{
1690        char *data = head->write_buf;
1691        bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE);
1692
1693        if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_KEEP_DOMAIN))
1694                return tomoyo_write_domain_keeper_policy(data, false,
1695                                                         is_delete);
1696        if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NO_KEEP_DOMAIN))
1697                return tomoyo_write_domain_keeper_policy(data, true, is_delete);
1698        if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_INITIALIZE_DOMAIN))
1699                return tomoyo_write_domain_initializer_policy(data, false,
1700                                                              is_delete);
1701        if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN))
1702                return tomoyo_write_domain_initializer_policy(data, true,
1703                                                              is_delete);
1704        if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALIAS))
1705                return tomoyo_write_alias_policy(data, is_delete);
1706        if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_READ))
1707                return tomoyo_write_globally_readable_policy(data, is_delete);
1708        if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_FILE_PATTERN))
1709                return tomoyo_write_pattern_policy(data, is_delete);
1710        if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE))
1711                return tomoyo_write_no_rewrite_policy(data, is_delete);
1712        return -EINVAL;
1713}
1714
1715/**
1716 * tomoyo_read_exception_policy - Read exception policy.
1717 *
1718 * @head: Pointer to "struct tomoyo_io_buffer".
1719 *
1720 * Returns 0 on success, -EINVAL otherwise.
1721 */
1722static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head)
1723{
1724        if (!head->read_eof) {
1725                switch (head->read_step) {
1726                case 0:
1727                        head->read_var2 = NULL;
1728                        head->read_step = 1;
1729                case 1:
1730                        if (!tomoyo_read_domain_keeper_policy(head))
1731                                break;
1732                        head->read_var2 = NULL;
1733                        head->read_step = 2;
1734                case 2:
1735                        if (!tomoyo_read_globally_readable_policy(head))
1736                                break;
1737                        head->read_var2 = NULL;
1738                        head->read_step = 3;
1739                case 3:
1740                        head->read_var2 = NULL;
1741                        head->read_step = 4;
1742                case 4:
1743                        if (!tomoyo_read_domain_initializer_policy(head))
1744                                break;
1745                        head->read_var2 = NULL;
1746                        head->read_step = 5;
1747                case 5:
1748                        if (!tomoyo_read_alias_policy(head))
1749                                break;
1750                        head->read_var2 = NULL;
1751                        head->read_step = 6;
1752                case 6:
1753                        head->read_var2 = NULL;
1754                        head->read_step = 7;
1755                case 7:
1756                        if (!tomoyo_read_file_pattern(head))
1757                                break;
1758                        head->read_var2 = NULL;
1759                        head->read_step = 8;
1760                case 8:
1761                        if (!tomoyo_read_no_rewrite_policy(head))
1762                                break;
1763                        head->read_var2 = NULL;
1764                        head->read_step = 9;
1765                case 9:
1766                        head->read_eof = true;
1767                        break;
1768                default:
1769                        return -EINVAL;
1770                }
1771        }
1772        return 0;
1773}
1774
1775/* path to policy loader */
1776static const char *tomoyo_loader = "/sbin/tomoyo-init";
1777
1778/**
1779 * tomoyo_policy_loader_exists - Check whether /sbin/tomoyo-init exists.
1780 *
1781 * Returns true if /sbin/tomoyo-init exists, false otherwise.
1782 */
1783static bool tomoyo_policy_loader_exists(void)
1784{
1785        /*
1786         * Don't activate MAC if the policy loader doesn't exist.
1787         * If the initrd includes /sbin/init but real-root-dev has not
1788         * mounted on / yet, activating MAC will block the system since
1789         * policies are not loaded yet.
1790         * Thus, let do_execve() call this function everytime.
1791         */
1792        struct path path;
1793
1794        if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) {
1795                printk(KERN_INFO "Not activating Mandatory Access Control now "
1796                       "since %s doesn't exist.\n", tomoyo_loader);
1797                return false;
1798        }
1799        path_put(&path);
1800        return true;
1801}
1802
1803/**
1804 * tomoyo_load_policy - Run external policy loader to load policy.
1805 *
1806 * @filename: The program about to start.
1807 *
1808 * This function checks whether @filename is /sbin/init , and if so
1809 * invoke /sbin/tomoyo-init and wait for the termination of /sbin/tomoyo-init
1810 * and then continues invocation of /sbin/init.
1811 * /sbin/tomoyo-init reads policy files in /etc/tomoyo/ directory and
1812 * writes to /sys/kernel/security/tomoyo/ interfaces.
1813 *
1814 * Returns nothing.
1815 */
1816void tomoyo_load_policy(const char *filename)
1817{
1818        char *argv[2];
1819        char *envp[3];
1820
1821        if (tomoyo_policy_loaded)
1822                return;
1823        /*
1824         * Check filename is /sbin/init or /sbin/tomoyo-start.
1825         * /sbin/tomoyo-start is a dummy filename in case where /sbin/init can't
1826         * be passed.
1827         * You can create /sbin/tomoyo-start by
1828         * "ln -s /bin/true /sbin/tomoyo-start".
1829         */
1830        if (strcmp(filename, "/sbin/init") &&
1831            strcmp(filename, "/sbin/tomoyo-start"))
1832                return;
1833        if (!tomoyo_policy_loader_exists())
1834                return;
1835
1836        printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
1837               tomoyo_loader);
1838        argv[0] = (char *) tomoyo_loader;
1839        argv[1] = NULL;
1840        envp[0] = "HOME=/";
1841        envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
1842        envp[2] = NULL;
1843        call_usermodehelper(argv[0], argv, envp, 1);
1844
1845        printk(KERN_INFO "TOMOYO: 2.2.0   2009/04/01\n");
1846        printk(KERN_INFO "Mandatory Access Control activated.\n");
1847        tomoyo_policy_loaded = true;
1848        { /* Check all profiles currently assigned to domains are defined. */
1849                struct tomoyo_domain_info *domain;
1850                down_read(&tomoyo_domain_list_lock);
1851                list_for_each_entry(domain, &tomoyo_domain_list, list) {
1852                        const u8 profile = domain->profile;
1853                        if (tomoyo_profile_ptr[profile])
1854                                continue;
1855                        panic("Profile %u (used by '%s') not defined.\n",
1856                              profile, domain->domainname->name);
1857                }
1858                up_read(&tomoyo_domain_list_lock);
1859        }
1860}
1861
1862/**
1863 * tomoyo_read_version: Get version.
1864 *
1865 * @head: Pointer to "struct tomoyo_io_buffer".
1866 *
1867 * Returns version information.
1868 */
1869static int tomoyo_read_version(struct tomoyo_io_buffer *head)
1870{
1871        if (!head->read_eof) {
1872                tomoyo_io_printf(head, "2.2.0");
1873                head->read_eof = true;
1874        }
1875        return 0;
1876}
1877
1878/**
1879 * tomoyo_read_self_domain - Get the current process's domainname.
1880 *
1881 * @head: Pointer to "struct tomoyo_io_buffer".
1882 *
1883 * Returns the current process's domainname.
1884 */
1885static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head)
1886{
1887        if (!head->read_eof) {
1888                /*
1889                 * tomoyo_domain()->domainname != NULL
1890                 * because every process belongs to a domain and
1891                 * the domain's name cannot be NULL.
1892                 */
1893                tomoyo_io_printf(head, "%s", tomoyo_domain()->domainname->name);
1894                head->read_eof = true;
1895        }
1896        return 0;
1897}
1898
1899/**
1900 * tomoyo_open_control - open() for /sys/kernel/security/tomoyo/ interface.
1901 *
1902 * @type: Type of interface.
1903 * @file: Pointer to "struct file".
1904 *
1905 * Associates policy handler and returns 0 on success, -ENOMEM otherwise.
1906 */
1907static int tomoyo_open_control(const u8 type, struct file *file)
1908{
1909        struct tomoyo_io_buffer *head = tomoyo_alloc(sizeof(*head));
1910
1911        if (!head)
1912                return -ENOMEM;
1913        mutex_init(&head->io_sem);
1914        switch (type) {
1915        case TOMOYO_DOMAINPOLICY:
1916                /* /sys/kernel/security/tomoyo/domain_policy */
1917                head->write = tomoyo_write_domain_policy;
1918                head->read = tomoyo_read_domain_policy;
1919                break;
1920        case TOMOYO_EXCEPTIONPOLICY:
1921                /* /sys/kernel/security/tomoyo/exception_policy */
1922                head->write = tomoyo_write_exception_policy;
1923                head->read = tomoyo_read_exception_policy;
1924                break;
1925        case TOMOYO_SELFDOMAIN:
1926                /* /sys/kernel/security/tomoyo/self_domain */
1927                head->read = tomoyo_read_self_domain;
1928                break;
1929        case TOMOYO_DOMAIN_STATUS:
1930                /* /sys/kernel/security/tomoyo/.domain_status */
1931                head->write = tomoyo_write_domain_profile;
1932                head->read = tomoyo_read_domain_profile;
1933                break;
1934        case TOMOYO_PROCESS_STATUS:
1935                /* /sys/kernel/security/tomoyo/.process_status */
1936                head->write = tomoyo_write_pid;
1937                head->read = tomoyo_read_pid;
1938                break;
1939        case TOMOYO_VERSION:
1940                /* /sys/kernel/security/tomoyo/version */
1941                head->read = tomoyo_read_version;
1942                head->readbuf_size = 128;
1943                break;
1944        case TOMOYO_MEMINFO:
1945                /* /sys/kernel/security/tomoyo/meminfo */
1946                head->write = tomoyo_write_memory_quota;
1947                head->read = tomoyo_read_memory_counter;
1948                head->readbuf_size = 512;
1949                break;
1950        case TOMOYO_PROFILE:
1951                /* /sys/kernel/security/tomoyo/profile */
1952                head->write = tomoyo_write_profile;
1953                head->read = tomoyo_read_profile;
1954                break;
1955        case TOMOYO_MANAGER:
1956                /* /sys/kernel/security/tomoyo/manager */
1957                head->write = tomoyo_write_manager_policy;
1958                head->read = tomoyo_read_manager_policy;
1959                break;
1960        }
1961        if (!(file->f_mode & FMODE_READ)) {
1962                /*
1963                 * No need to allocate read_buf since it is not opened
1964                 * for reading.
1965                 */
1966                head->read = NULL;
1967        } else {
1968                if (!head->readbuf_size)
1969                        head->readbuf_size = 4096 * 2;
1970                head->read_buf = tomoyo_alloc(head->readbuf_size);
1971                if (!head->read_buf) {
1972                        tomoyo_free(head);
1973                        return -ENOMEM;
1974                }
1975        }
1976        if (!(file->f_mode & FMODE_WRITE)) {
1977                /*
1978                 * No need to allocate write_buf since it is not opened
1979                 * for writing.
1980                 */
1981                head->write = NULL;
1982        } else if (head->write) {
1983                head->writebuf_size = 4096 * 2;
1984                head->write_buf = tomoyo_alloc(head->writebuf_size);
1985                if (!head->write_buf) {
1986                        tomoyo_free(head->read_buf);
1987                        tomoyo_free(head);
1988                        return -ENOMEM;
1989                }
1990        }
1991        file->private_data = head;
1992        /*
1993         * Call the handler now if the file is
1994         * /sys/kernel/security/tomoyo/self_domain
1995         * so that the user can use
1996         * cat < /sys/kernel/security/tomoyo/self_domain"
1997         * to know the current process's domainname.
1998         */
1999        if (type == TOMOYO_SELFDOMAIN)
2000                tomoyo_read_control(file, NULL, 0);
2001        return 0;
2002}
2003
2004/**
2005 * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface.
2006 *
2007 * @file:       Pointer to "struct file".
2008 * @buffer:     Poiner to buffer to write to.
2009 * @buffer_len: Size of @buffer.
2010 *
2011 * Returns bytes read on success, negative value otherwise.
2012 */
2013static int tomoyo_read_control(struct file *file, char __user *buffer,
2014                               const int buffer_len)
2015{
2016        int len = 0;
2017        struct tomoyo_io_buffer *head = file->private_data;
2018        char *cp;
2019
2020        if (!head->read)
2021                return -ENOSYS;
2022        if (mutex_lock_interruptible(&head->io_sem))
2023                return -EINTR;
2024        /* Call the policy handler. */
2025        len = head->read(head);
2026        if (len < 0)
2027                goto out;
2028        /* Write to buffer. */
2029        len = head->read_avail;
2030        if (len > buffer_len)
2031                len = buffer_len;
2032        if (!len)
2033                goto out;
2034        /* head->read_buf changes by some functions. */
2035        cp = head->read_buf;
2036        if (copy_to_user(buffer, cp, len)) {
2037                len = -EFAULT;
2038                goto out;
2039        }
2040        head->read_avail -= len;
2041        memmove(cp, cp + len, head->read_avail);
2042 out:
2043        mutex_unlock(&head->io_sem);
2044        return len;
2045}
2046
2047/**
2048 * tomoyo_write_control - write() for /sys/kernel/security/tomoyo/ interface.
2049 *
2050 * @file:       Pointer to "struct file".
2051 * @buffer:     Pointer to buffer to read from.
2052 * @buffer_len: Size of @buffer.
2053 *
2054 * Returns @buffer_len on success, negative value otherwise.
2055 */
2056static int tomoyo_write_control(struct file *file, const char __user *buffer,
2057                                const int buffer_len)
2058{
2059        struct tomoyo_io_buffer *head = file->private_data;
2060        int error = buffer_len;
2061        int avail_len = buffer_len;
2062        char *cp0 = head->write_buf;
2063
2064        if (!head->write)
2065                return -ENOSYS;
2066        if (!access_ok(VERIFY_READ, buffer, buffer_len))
2067                return -EFAULT;
2068        /* Don't allow updating policies by non manager programs. */
2069        if (head->write != tomoyo_write_pid &&
2070            head->write != tomoyo_write_domain_policy &&
2071            !tomoyo_is_policy_manager())
2072                return -EPERM;
2073        if (mutex_lock_interruptible(&head->io_sem))
2074                return -EINTR;
2075        /* Read a line and dispatch it to the policy handler. */
2076        while (avail_len > 0) {
2077                char c;
2078                if (head->write_avail >= head->writebuf_size - 1) {
2079                        error = -ENOMEM;
2080                        break;
2081                } else if (get_user(c, buffer)) {
2082                        error = -EFAULT;
2083                        break;
2084                }
2085                buffer++;
2086                avail_len--;
2087                cp0[head->write_avail++] = c;
2088                if (c != '\n')
2089                        continue;
2090                cp0[head->write_avail - 1] = '\0';
2091                head->write_avail = 0;
2092                tomoyo_normalize_line(cp0);
2093                head->write(head);
2094        }
2095        mutex_unlock(&head->io_sem);
2096        return error;
2097}
2098
2099/**
2100 * tomoyo_close_control - close() for /sys/kernel/security/tomoyo/ interface.
2101 *
2102 * @file: Pointer to "struct file".
2103 *
2104 * Releases memory and returns 0.
2105 */
2106static int tomoyo_close_control(struct file *file)
2107{
2108        struct tomoyo_io_buffer *head = file->private_data;
2109
2110        /* Release memory used for policy I/O. */
2111        tomoyo_free(head->read_buf);
2112        head->read_buf = NULL;
2113        tomoyo_free(head->write_buf);
2114        head->write_buf = NULL;
2115        tomoyo_free(head);
2116        head = NULL;
2117        file->private_data = NULL;
2118        return 0;
2119}
2120
2121/**
2122 * tomoyo_alloc_acl_element - Allocate permanent memory for ACL entry.
2123 *
2124 * @acl_type:  Type of ACL entry.
2125 *
2126 * Returns pointer to the ACL entry on success, NULL otherwise.
2127 */
2128void *tomoyo_alloc_acl_element(const u8 acl_type)
2129{
2130        int len;
2131        struct tomoyo_acl_info *ptr;
2132
2133        switch (acl_type) {
2134        case TOMOYO_TYPE_SINGLE_PATH_ACL:
2135                len = sizeof(struct tomoyo_single_path_acl_record);
2136                break;
2137        case TOMOYO_TYPE_DOUBLE_PATH_ACL:
2138                len = sizeof(struct tomoyo_double_path_acl_record);
2139                break;
2140        default:
2141                return NULL;
2142        }
2143        ptr = tomoyo_alloc_element(len);
2144        if (!ptr)
2145                return NULL;
2146        ptr->type = acl_type;
2147        return ptr;
2148}
2149
2150/**
2151 * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface.
2152 *
2153 * @inode: Pointer to "struct inode".
2154 * @file:  Pointer to "struct file".
2155 *
2156 * Returns 0 on success, negative value otherwise.
2157 */
2158static int tomoyo_open(struct inode *inode, struct file *file)
2159{
2160        const int key = ((u8 *) file->f_path.dentry->d_inode->i_private)
2161                - ((u8 *) NULL);
2162        return tomoyo_open_control(key, file);
2163}
2164
2165/**
2166 * tomoyo_release - close() for /sys/kernel/security/tomoyo/ interface.
2167 *
2168 * @inode: Pointer to "struct inode".
2169 * @file:  Pointer to "struct file".
2170 *
2171 * Returns 0 on success, negative value otherwise.
2172 */
2173static int tomoyo_release(struct inode *inode, struct file *file)
2174{
2175        return tomoyo_close_control(file);
2176}
2177
2178/**
2179 * tomoyo_read - read() for /sys/kernel/security/tomoyo/ interface.
2180 *
2181 * @file:  Pointer to "struct file".
2182 * @buf:   Pointer to buffer.
2183 * @count: Size of @buf.
2184 * @ppos:  Unused.
2185 *
2186 * Returns bytes read on success, negative value otherwise.
2187 */
2188static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count,
2189                           loff_t *ppos)
2190{
2191        return tomoyo_read_control(file, buf, count);
2192}
2193
2194/**
2195 * tomoyo_write - write() for /sys/kernel/security/tomoyo/ interface.
2196 *
2197 * @file:  Pointer to "struct file".
2198 * @buf:   Pointer to buffer.
2199 * @count: Size of @buf.
2200 * @ppos:  Unused.
2201 *
2202 * Returns @count on success, negative value otherwise.
2203 */
2204static ssize_t tomoyo_write(struct file *file, const char __user *buf,
2205                            size_t count, loff_t *ppos)
2206{
2207        return tomoyo_write_control(file, buf, count);
2208}
2209
2210/*
2211 * tomoyo_operations is a "struct file_operations" which is used for handling
2212 * /sys/kernel/security/tomoyo/ interface.
2213 *
2214 * Some files under /sys/kernel/security/tomoyo/ directory accept open(O_RDWR).
2215 * See tomoyo_io_buffer for internals.
2216 */
2217static const struct file_operations tomoyo_operations = {
2218        .open    = tomoyo_open,
2219        .release = tomoyo_release,
2220        .read    = tomoyo_read,
2221        .write   = tomoyo_write,
2222};
2223
2224/**
2225 * tomoyo_create_entry - Create interface files under /sys/kernel/security/tomoyo/ directory.
2226 *
2227 * @name:   The name of the interface file.
2228 * @mode:   The permission of the interface file.
2229 * @parent: The parent directory.
2230 * @key:    Type of interface.
2231 *
2232 * Returns nothing.
2233 */
2234static void __init tomoyo_create_entry(const char *name, const mode_t mode,
2235                                       struct dentry *parent, const u8 key)
2236{
2237        securityfs_create_file(name, mode, parent, ((u8 *) NULL) + key,
2238                               &tomoyo_operations);
2239}
2240
2241/**
2242 * tomoyo_initerface_init - Initialize /sys/kernel/security/tomoyo/ interface.
2243 *
2244 * Returns 0.
2245 */
2246static int __init tomoyo_initerface_init(void)
2247{
2248        struct dentry *tomoyo_dir;
2249
2250        /* Don't create securityfs entries unless registered. */
2251        if (current_cred()->security != &tomoyo_kernel_domain)
2252                return 0;
2253
2254        tomoyo_dir = securityfs_create_dir("tomoyo", NULL);
2255        tomoyo_create_entry("domain_policy",    0600, tomoyo_dir,
2256                            TOMOYO_DOMAINPOLICY);
2257        tomoyo_create_entry("exception_policy", 0600, tomoyo_dir,
2258                            TOMOYO_EXCEPTIONPOLICY);
2259        tomoyo_create_entry("self_domain",      0400, tomoyo_dir,
2260                            TOMOYO_SELFDOMAIN);
2261        tomoyo_create_entry(".domain_status",   0600, tomoyo_dir,
2262                            TOMOYO_DOMAIN_STATUS);
2263        tomoyo_create_entry(".process_status",  0600, tomoyo_dir,
2264                            TOMOYO_PROCESS_STATUS);
2265        tomoyo_create_entry("meminfo",          0600, tomoyo_dir,
2266                            TOMOYO_MEMINFO);
2267        tomoyo_create_entry("profile",          0600, tomoyo_dir,
2268                            TOMOYO_PROFILE);
2269        tomoyo_create_entry("manager",          0600, tomoyo_dir,
2270                            TOMOYO_MANAGER);
2271        tomoyo_create_entry("version",          0400, tomoyo_dir,
2272                            TOMOYO_VERSION);
2273        return 0;
2274}
2275
2276fs_initcall(tomoyo_initerface_init);
2277