guard page for stacks that grow upwards
[linux-2.6.git] / security / tomoyo / util.c
index 592b76a..9bfc1ee 100644 (file)
@@ -26,7 +26,7 @@ bool tomoyo_policy_loaded;
  * The @src is updated to point the first character after the value
  * on success.
  */
-u8 tomoyo_parse_ulong(unsigned long *result, char **str)
+static u8 tomoyo_parse_ulong(unsigned long *result, char **str)
 {
        const char *cp = *str;
        char *ep;
@@ -89,10 +89,10 @@ void tomoyo_print_ulong(char *buffer, const int buffer_len,
 bool tomoyo_parse_name_union(const char *filename,
                             struct tomoyo_name_union *ptr)
 {
-       if (!tomoyo_is_correct_word(filename))
+       if (!tomoyo_correct_word(filename))
                return false;
        if (filename[0] == '@') {
-               ptr->group = tomoyo_get_path_group(filename + 1);
+               ptr->group = tomoyo_get_group(filename + 1, TOMOYO_PATH_GROUP);
                ptr->is_group = true;
                return ptr->group != NULL;
        }
@@ -115,9 +115,9 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num)
        unsigned long v;
        memset(num, 0, sizeof(*num));
        if (data[0] == '@') {
-               if (!tomoyo_is_correct_word(data))
+               if (!tomoyo_correct_word(data))
                        return false;
-               num->group = tomoyo_get_number_group(data + 1);
+               num->group = tomoyo_get_group(data + 1, TOMOYO_NUMBER_GROUP);
                num->is_group = true;
                return num->group != NULL;
        }
@@ -142,7 +142,7 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num)
 }
 
 /**
- * tomoyo_is_byte_range - Check whether the string is a \ooo style octal value.
+ * tomoyo_byte_range - Check whether the string is a \ooo style octal value.
  *
  * @str: Pointer to the string.
  *
@@ -151,7 +151,7 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num)
  * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF.
  * This function verifies that \ooo is in valid range.
  */
-static inline bool tomoyo_is_byte_range(const char *str)
+static inline bool tomoyo_byte_range(const char *str)
 {
        return *str >= '0' && *str++ <= '3' &&
                *str >= '0' && *str++ <= '7' &&
@@ -159,13 +159,13 @@ static inline bool tomoyo_is_byte_range(const char *str)
 }
 
 /**
- * tomoyo_is_alphabet_char - Check whether the character is an alphabet.
+ * tomoyo_alphabet_char - Check whether the character is an alphabet.
  *
  * @c: The character to check.
  *
  * Returns true if @c is an alphabet character, false otherwise.
  */
-static inline bool tomoyo_is_alphabet_char(const char c)
+static inline bool tomoyo_alphabet_char(const char c)
 {
        return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
 }
@@ -223,15 +223,15 @@ void tomoyo_normalize_line(unsigned char *buffer)
        unsigned char *dp = buffer;
        bool first = true;
 
-       while (tomoyo_is_invalid(*sp))
+       while (tomoyo_invalid(*sp))
                sp++;
        while (*sp) {
                if (!first)
                        *dp++ = ' ';
                first = false;
-               while (tomoyo_is_valid(*sp))
+               while (tomoyo_valid(*sp))
                        *dp++ = *sp++;
-               while (tomoyo_is_invalid(*sp))
+               while (tomoyo_invalid(*sp))
                        sp++;
        }
        *dp = '\0';
@@ -265,7 +265,7 @@ bool tomoyo_tokenize(char *buffer, char *w[], size_t size)
 }
 
 /**
- * tomoyo_is_correct_word2 - Validate a string.
+ * tomoyo_correct_word2 - Validate a string.
  *
  * @string: The string to check. May be non-'\0'-terminated.
  * @len:    Length of @string.
@@ -273,7 +273,7 @@ bool tomoyo_tokenize(char *buffer, char *w[], size_t size)
  * Check whether the given string follows the naming rules.
  * Returns true if @string follows the naming rules, false otherwise.
  */
-static bool tomoyo_is_correct_word2(const char *string, size_t len)
+static bool tomoyo_correct_word2(const char *string, size_t len)
 {
        const char *const start = string;
        bool in_repetition = false;
@@ -325,13 +325,13 @@ static bool tomoyo_is_correct_word2(const char *string, size_t len)
                                if (d < '0' || d > '7' || e < '0' || e > '7')
                                        break;
                                c = tomoyo_make_byte(c, d, e);
-                               if (tomoyo_is_invalid(c))
+                               if (tomoyo_invalid(c))
                                        continue; /* pattern is not \000 */
                        }
                        goto out;
                } else if (in_repetition && c == '/') {
                        goto out;
-               } else if (tomoyo_is_invalid(c)) {
+               } else if (tomoyo_invalid(c)) {
                        goto out;
                }
        }
@@ -343,39 +343,39 @@ static bool tomoyo_is_correct_word2(const char *string, size_t len)
 }
 
 /**
- * tomoyo_is_correct_word - Validate a string.
+ * tomoyo_correct_word - Validate a string.
  *
  * @string: The string to check.
  *
  * Check whether the given string follows the naming rules.
  * Returns true if @string follows the naming rules, false otherwise.
  */
-bool tomoyo_is_correct_word(const char *string)
+bool tomoyo_correct_word(const char *string)
 {
-       return tomoyo_is_correct_word2(string, strlen(string));
+       return tomoyo_correct_word2(string, strlen(string));
 }
 
 /**
- * tomoyo_is_correct_path - Validate a pathname.
+ * tomoyo_correct_path - Validate a pathname.
  *
  * @filename: The pathname to check.
  *
  * Check whether the given pathname follows the naming rules.
  * Returns true if @filename follows the naming rules, false otherwise.
  */
-bool tomoyo_is_correct_path(const char *filename)
+bool tomoyo_correct_path(const char *filename)
 {
-       return *filename == '/' && tomoyo_is_correct_word(filename);
+       return *filename == '/' && tomoyo_correct_word(filename);
 }
 
 /**
- * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules.
+ * tomoyo_correct_domain - Check whether the given domainname follows the naming rules.
  *
  * @domainname: The domainname to check.
  *
  * Returns true if @domainname follows the naming rules, false otherwise.
  */
-bool tomoyo_is_correct_domain(const unsigned char *domainname)
+bool tomoyo_correct_domain(const unsigned char *domainname)
 {
        if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME,
                                   TOMOYO_ROOT_NAME_LEN))
@@ -390,23 +390,23 @@ bool tomoyo_is_correct_domain(const unsigned char *domainname)
                if (!cp)
                        break;
                if (*domainname != '/' ||
-                   !tomoyo_is_correct_word2(domainname, cp - domainname - 1))
+                   !tomoyo_correct_word2(domainname, cp - domainname - 1))
                        goto out;
                domainname = cp + 1;
        }
-       return tomoyo_is_correct_path(domainname);
+       return tomoyo_correct_path(domainname);
  out:
        return false;
 }
 
 /**
- * tomoyo_is_domain_def - Check whether the given token can be a domainname.
+ * tomoyo_domain_def - Check whether the given token can be a domainname.
  *
  * @buffer: The token to check.
  *
  * Returns true if @buffer possibly be a domainname, false otherwise.
  */
-bool tomoyo_is_domain_def(const unsigned char *buffer)
+bool tomoyo_domain_def(const unsigned char *buffer)
 {
        return !strncmp(buffer, TOMOYO_ROOT_NAME, TOMOYO_ROOT_NAME_LEN);
 }
@@ -528,7 +528,7 @@ static bool tomoyo_file_matches_pattern2(const char *filename,
                        } else if (c == '\\') {
                                if (filename[1] == '\\')
                                        filename++;
-                               else if (tomoyo_is_byte_range(filename + 1))
+                               else if (tomoyo_byte_range(filename + 1))
                                        filename += 3;
                                else
                                        return false;
@@ -549,14 +549,14 @@ static bool tomoyo_file_matches_pattern2(const char *filename,
                                return false;
                        break;
                case 'a':
-                       if (!tomoyo_is_alphabet_char(c))
+                       if (!tomoyo_alphabet_char(c))
                                return false;
                        break;
                case '0':
                case '1':
                case '2':
                case '3':
-                       if (c == '\\' && tomoyo_is_byte_range(filename + 1)
+                       if (c == '\\' && tomoyo_byte_range(filename + 1)
                            && strncmp(filename + 1, pattern, 3) == 0) {
                                filename += 3;
                                pattern += 2;
@@ -577,7 +577,7 @@ static bool tomoyo_file_matches_pattern2(const char *filename,
                                        continue;
                                if (filename[i + 1] == '\\')
                                        i++;
-                               else if (tomoyo_is_byte_range(filename + i + 1))
+                               else if (tomoyo_byte_range(filename + i + 1))
                                        i += 3;
                                else
                                        break; /* Bad pattern. */
@@ -593,7 +593,7 @@ static bool tomoyo_file_matches_pattern2(const char *filename,
                                while (isxdigit(filename[j]))
                                        j++;
                        } else if (c == 'A') {
-                               while (tomoyo_is_alphabet_char(filename[j]))
+                               while (tomoyo_alphabet_char(filename[j]))
                                        j++;
                        }
                        for (i = 1; i <= j; i++) {
@@ -792,25 +792,67 @@ const char *tomoyo_get_exe(void)
 }
 
 /**
+ * tomoyo_get_mode - Get MAC mode.
+ *
+ * @profile: Profile number.
+ * @index:   Index number of functionality.
+ *
+ * Returns mode.
+ */
+int tomoyo_get_mode(const u8 profile, const u8 index)
+{
+       u8 mode;
+       const u8 category = TOMOYO_MAC_CATEGORY_FILE;
+       if (!tomoyo_policy_loaded)
+               return TOMOYO_CONFIG_DISABLED;
+       mode = tomoyo_profile(profile)->config[index];
+       if (mode == TOMOYO_CONFIG_USE_DEFAULT)
+               mode = tomoyo_profile(profile)->config[category];
+       if (mode == TOMOYO_CONFIG_USE_DEFAULT)
+               mode = tomoyo_profile(profile)->default_config;
+       return mode & 3;
+}
+
+/**
  * tomoyo_init_request_info - Initialize "struct tomoyo_request_info" members.
  *
  * @r:      Pointer to "struct tomoyo_request_info" to initialize.
  * @domain: Pointer to "struct tomoyo_domain_info". NULL for tomoyo_domain().
+ * @index:  Index number of functionality.
  *
  * Returns mode.
  */
 int tomoyo_init_request_info(struct tomoyo_request_info *r,
-                            struct tomoyo_domain_info *domain)
+                            struct tomoyo_domain_info *domain, const u8 index)
 {
+       u8 profile;
        memset(r, 0, sizeof(*r));
        if (!domain)
                domain = tomoyo_domain();
        r->domain = domain;
-       r->mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
+       profile = domain->profile;
+       r->profile = profile;
+       r->type = index;
+       r->mode = tomoyo_get_mode(profile, index);
        return r->mode;
 }
 
 /**
+ * tomoyo_last_word - Get last component of a line.
+ *
+ * @line: A line.
+ *
+ * Returns the last word of a line.
+ */
+const char *tomoyo_last_word(const char *name)
+{
+       const char *cp = strrchr(name, ' ');
+       if (cp)
+               return cp + 1;
+       return name;
+}
+
+/**
  * tomoyo_warn_log - Print warning or error message on console.
  *
  * @r:   Pointer to "struct tomoyo_request_info".
@@ -818,29 +860,34 @@ int tomoyo_init_request_info(struct tomoyo_request_info *r,
  */
 void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...)
 {
-       int len = PAGE_SIZE;
        va_list args;
        char *buffer;
-       if (!tomoyo_verbose_mode(r->domain))
-               return;
-       while (1) {
-               int len2;
-               buffer = kmalloc(len, GFP_NOFS);
-               if (!buffer)
+       const struct tomoyo_domain_info * const domain = r->domain;
+       const struct tomoyo_profile *profile = tomoyo_profile(domain->profile);
+       switch (r->mode) {
+       case TOMOYO_CONFIG_ENFORCING:
+               if (!profile->enforcing->enforcing_verbose)
                        return;
-               va_start(args, fmt);
-               len2 = vsnprintf(buffer, len - 1, fmt, args);
-               va_end(args);
-               if (len2 <= len - 1) {
-                       buffer[len2] = '\0';
-                       break;
-               }
-               len = len2 + 1;
-               kfree(buffer);
+               break;
+       case TOMOYO_CONFIG_PERMISSIVE:
+               if (!profile->permissive->permissive_verbose)
+                       return;
+               break;
+       case TOMOYO_CONFIG_LEARNING:
+               if (!profile->learning->learning_verbose)
+                       return;
+               break;
        }
-       printk(KERN_WARNING "TOMOYO-%s: Access %s denied for %s\n",
-              r->mode == TOMOYO_CONFIG_ENFORCING ? "ERROR" : "WARNING",
-              buffer, tomoyo_get_last_name(r->domain));
+       buffer = kmalloc(4096, GFP_NOFS);
+       if (!buffer)
+               return;
+       va_start(args, fmt);
+       vsnprintf(buffer, 4095, fmt, args);
+       va_end(args);
+       buffer[4095] = '\0';
+       printk(KERN_WARNING "%s: Access %s denied for %s\n",
+              r->mode == TOMOYO_CONFIG_ENFORCING ? "ERROR" : "WARNING", buffer,
+              tomoyo_last_word(domain->domainname->name));
        kfree(buffer);
 }
 
@@ -864,6 +911,8 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
        if (!domain)
                return true;
        list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
+               if (ptr->is_deleted)
+                       continue;
                switch (ptr->type) {
                        u16 perm;
                        u8 i;
@@ -890,20 +939,19 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
                                if (perm & (1 << i))
                                        count++;
                        break;
-               case TOMOYO_TYPE_PATH_NUMBER3_ACL:
-                       perm = container_of(ptr, struct tomoyo_path_number3_acl,
+               case TOMOYO_TYPE_MKDEV_ACL:
+                       perm = container_of(ptr, struct tomoyo_mkdev_acl,
                                            head)->perm;
-                       for (i = 0; i < TOMOYO_MAX_PATH_NUMBER3_OPERATION; i++)
+                       for (i = 0; i < TOMOYO_MAX_MKDEV_OPERATION; i++)
                                if (perm & (1 << i))
                                        count++;
                        break;
-               case TOMOYO_TYPE_MOUNT_ACL:
-                       if (!container_of(ptr, struct tomoyo_mount_acl, head)->
-                           is_deleted)
-                               count++;
+               default:
+                       count++;
                }
        }
-       if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY))
+       if (count < tomoyo_profile(domain->profile)->learning->
+           learning_max_entry)
                return true;
        if (!domain->quota_warned) {
                domain->quota_warned = true;