TOMOYO: Simplify profile structure.
Tetsuo Handa [Sun, 26 Jun 2011 14:18:21 +0000 (23:18 +0900)]
Remove global preference from profile structure in order to make code simpler.

Due to this structure change, printk() warnings upon policy violation are
temporarily disabled. They will be replaced by
/sys/kernel/security/tomoyo/audit by next patch.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>

security/tomoyo/common.c
security/tomoyo/common.h
security/tomoyo/util.c

index 465df02..2b28035 100644 (file)
 #include <linux/security.h>
 #include "common.h"
 
-static struct tomoyo_profile tomoyo_default_profile = {
-       .learning = &tomoyo_default_profile.preference,
-       .permissive = &tomoyo_default_profile.preference,
-       .enforcing = &tomoyo_default_profile.preference,
-       .preference.enforcing_verbose = true,
-       .preference.learning_max_entry = 2048,
-       .preference.learning_verbose = false,
-       .preference.permissive_verbose = true
-};
-
 /* Profile version. Currently only 20090903 is defined. */
 static unsigned int tomoyo_profile_version;
 
@@ -61,6 +51,11 @@ static const char *tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX
        [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file",
 };
 
+/* String table for PREFERENCE keyword. */
+static const char * const tomoyo_pref_keywords[TOMOYO_MAX_PREF] = {
+       [TOMOYO_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry",
+};
+
 /* Permit policy management by non-root user? */
 static bool tomoyo_manage_by_non_root;
 
@@ -71,11 +66,22 @@ static bool tomoyo_manage_by_non_root;
  *
  * @value: Bool value.
  */
+/*
 static const char *tomoyo_yesno(const unsigned int value)
 {
        return value ? "yes" : "no";
 }
+*/
 
+/**
+ * tomoyo_addprintf - strncat()-like-snprintf().
+ *
+ * @buffer: Buffer to write to. Must be '\0'-terminated.
+ * @len:    Size of @buffer.
+ * @fmt:    The printf()'s format string, followed by parameters.
+ *
+ * Returns nothing.
+ */
 static void tomoyo_addprintf(char *buffer, int len, const char *fmt, ...)
 {
        va_list args;
@@ -294,12 +300,10 @@ static struct tomoyo_profile *tomoyo_assign_profile(const unsigned int profile)
        ptr = tomoyo_profile_ptr[profile];
        if (!ptr && tomoyo_memory_ok(entry)) {
                ptr = entry;
-               ptr->learning = &tomoyo_default_profile.preference;
-               ptr->permissive = &tomoyo_default_profile.preference;
-               ptr->enforcing = &tomoyo_default_profile.preference;
                ptr->default_config = TOMOYO_CONFIG_DISABLED;
                memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT,
                       sizeof(ptr->config));
+               ptr->pref[TOMOYO_PREF_MAX_LEARNING_ENTRY] = 2048;
                mb(); /* Avoid out-of-order execution. */
                tomoyo_profile_ptr[profile] = ptr;
                entry = NULL;
@@ -319,13 +323,22 @@ static struct tomoyo_profile *tomoyo_assign_profile(const unsigned int profile)
  */
 struct tomoyo_profile *tomoyo_profile(const u8 profile)
 {
+       static struct tomoyo_profile tomoyo_null_profile;
        struct tomoyo_profile *ptr = tomoyo_profile_ptr[profile];
-       if (!tomoyo_policy_loaded)
-               return &tomoyo_default_profile;
-       BUG_ON(!ptr);
+       if (!ptr)
+               ptr = &tomoyo_null_profile;
        return ptr;
 }
 
+/**
+ * tomoyo_find_yesno - Find values for specified keyword.
+ *
+ * @string: String to check.
+ * @find:   Name of keyword.
+ *
+ * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise.
+ */
+/*
 static s8 tomoyo_find_yesno(const char *string, const char *find)
 {
        const char *cp = strstr(string, find);
@@ -338,19 +351,17 @@ static s8 tomoyo_find_yesno(const char *string, const char *find)
        }
        return -1;
 }
+*/
 
-static void tomoyo_set_bool(bool *b, const char *string, const char *find)
-{
-       switch (tomoyo_find_yesno(string, find)) {
-       case 1:
-               *b = true;
-               break;
-       case 0:
-               *b = false;
-               break;
-       }
-}
-
+/**
+ * tomoyo_set_uint - Set value for specified preference.
+ *
+ * @i:      Pointer to "unsigned int".
+ * @string: String to check.
+ * @find:   Name of keyword.
+ *
+ * Returns nothing.
+ */
 static void tomoyo_set_uint(unsigned int *i, const char *string,
                            const char *find)
 {
@@ -359,51 +370,16 @@ static void tomoyo_set_uint(unsigned int *i, const char *string,
                sscanf(cp + strlen(find), "=%u", i);
 }
 
-static void tomoyo_set_pref(const char *name, const char *value,
-                           const bool use_default,
-                           struct tomoyo_profile *profile)
-{
-       struct tomoyo_preference **pref;
-       bool *verbose;
-       if (!strcmp(name, "enforcing")) {
-               if (use_default) {
-                       pref = &profile->enforcing;
-                       goto set_default;
-               }
-               profile->enforcing = &profile->preference;
-               verbose = &profile->preference.enforcing_verbose;
-               goto set_verbose;
-       }
-       if (!strcmp(name, "permissive")) {
-               if (use_default) {
-                       pref = &profile->permissive;
-                       goto set_default;
-               }
-               profile->permissive = &profile->preference;
-               verbose = &profile->preference.permissive_verbose;
-               goto set_verbose;
-       }
-       if (!strcmp(name, "learning")) {
-               if (use_default) {
-                       pref = &profile->learning;
-                       goto set_default;
-               }
-               profile->learning = &profile->preference;
-               tomoyo_set_uint(&profile->preference.learning_max_entry, value,
-                            "max_entry");
-               verbose = &profile->preference.learning_verbose;
-               goto set_verbose;
-       }
-       return;
- set_default:
-       *pref = &tomoyo_default_profile.preference;
-       return;
- set_verbose:
-       tomoyo_set_bool(verbose, value, "verbose");
-}
-
+/**
+ * tomoyo_set_mode - Set mode for specified profile.
+ *
+ * @name:    Name of functionality.
+ * @value:   Mode for @name.
+ * @profile: Pointer to "struct tomoyo_profile".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_set_mode(char *name, const char *value,
-                          const bool use_default,
                           struct tomoyo_profile *profile)
 {
        u8 i;
@@ -425,7 +401,7 @@ static int tomoyo_set_mode(char *name, const char *value,
        } else {
                return -EINVAL;
        }
-       if (use_default) {
+       if (strstr(value, "use_default")) {
                config = TOMOYO_CONFIG_USE_DEFAULT;
        } else {
                u8 mode;
@@ -455,34 +431,21 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
 {
        char *data = head->write_buf;
        unsigned int i;
-       bool use_default = false;
        char *cp;
        struct tomoyo_profile *profile;
        if (sscanf(data, "PROFILE_VERSION=%u", &tomoyo_profile_version) == 1)
                return 0;
        i = simple_strtoul(data, &cp, 10);
-       if (data == cp) {
-               profile = &tomoyo_default_profile;
-       } else {
-               if (*cp != '-')
-                       return -EINVAL;
-               data = cp + 1;
-               profile = tomoyo_assign_profile(i);
-               if (!profile)
-                       return -EINVAL;
-       }
+       if (*cp != '-')
+               return -EINVAL;
+       data = cp + 1;
+       profile = tomoyo_assign_profile(i);
+       if (!profile)
+               return -EINVAL;
        cp = strchr(data, '=');
        if (!cp)
                return -EINVAL;
        *cp++ = '\0';
-       if (profile != &tomoyo_default_profile)
-               use_default = strstr(cp, "use_default") != NULL;
-       if (tomoyo_str_starts(&data, "PREFERENCE::")) {
-               tomoyo_set_pref(data, cp, use_default, profile);
-               return 0;
-       }
-       if (profile == &tomoyo_default_profile)
-               return -EINVAL;
        if (!strcmp(data, "COMMENT")) {
                static DEFINE_SPINLOCK(lock);
                const struct tomoyo_path_info *new_comment
@@ -497,48 +460,13 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
                tomoyo_put_name(old_comment);
                return 0;
        }
-       return tomoyo_set_mode(data, cp, use_default, profile);
-}
-
-static void tomoyo_print_preference(struct tomoyo_io_buffer *head,
-                                   const int idx)
-{
-       struct tomoyo_preference *pref = &tomoyo_default_profile.preference;
-       const struct tomoyo_profile *profile = idx >= 0 ?
-               tomoyo_profile_ptr[idx] : NULL;
-       char buffer[16] = "";
-       if (profile) {
-               buffer[sizeof(buffer) - 1] = '\0';
-               snprintf(buffer, sizeof(buffer) - 1, "%u-", idx);
-       }
-       if (profile) {
-               pref = profile->learning;
-               if (pref == &tomoyo_default_profile.preference)
-                       goto skip1;
-       }
-       tomoyo_io_printf(head, "%sPREFERENCE::%s={ "
-                        "verbose=%s max_entry=%u }\n",
-                        buffer, "learning",
-                        tomoyo_yesno(pref->learning_verbose),
-                        pref->learning_max_entry);
- skip1:
-       if (profile) {
-               pref = profile->permissive;
-               if (pref == &tomoyo_default_profile.preference)
-                       goto skip2;
-       }
-       tomoyo_io_printf(head, "%sPREFERENCE::%s={ verbose=%s }\n",
-                        buffer, "permissive",
-                        tomoyo_yesno(pref->permissive_verbose));
- skip2:
-       if (profile) {
-               pref = profile->enforcing;
-               if (pref == &tomoyo_default_profile.preference)
-                       return;
+       if (!strcmp(data, "PREFERENCE")) {
+               for (i = 0; i < TOMOYO_MAX_PREF; i++)
+                       tomoyo_set_uint(&profile->pref[i], cp,
+                                       tomoyo_pref_keywords[i]);
+               return 0;
        }
-       tomoyo_io_printf(head, "%sPREFERENCE::%s={ verbose=%s }\n",
-                        buffer, "enforcing",
-                        tomoyo_yesno(pref->enforcing_verbose));
+       return tomoyo_set_mode(data, cp, profile);
 }
 
 static void tomoyo_print_config(struct tomoyo_io_buffer *head, const u8 config)
@@ -561,7 +489,6 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
        switch (head->r.step) {
        case 0:
                tomoyo_io_printf(head, "PROFILE_VERSION=%s\n", "20090903");
-               tomoyo_print_preference(head, -1);
                head->r.step++;
                break;
        case 1:
@@ -575,11 +502,18 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
                break;
        case 2:
                {
+                       u8 i;
                        const struct tomoyo_path_info *comment =
                                profile->comment;
                        tomoyo_io_printf(head, "%u-COMMENT=", index);
                        tomoyo_set_string(head, comment ? comment->name : "");
                        tomoyo_set_lf(head);
+                       tomoyo_io_printf(head, "%u-PREFERENCE={ ", index);
+                       for (i = 0; i < TOMOYO_MAX_PREF; i++)
+                               tomoyo_io_printf(head, "%s=%u ",
+                                                tomoyo_pref_keywords[i],
+                                                profile->pref[i]);
+                       tomoyo_set_string(head, "}\n");
                        head->r.step++;
                }
                break;
@@ -606,7 +540,6 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
                }
                if (head->r.bit == TOMOYO_MAX_MAC_INDEX
                    + TOMOYO_MAX_MAC_CATEGORY_INDEX) {
-                       tomoyo_print_preference(head, index);
                        head->r.index++;
                        head->r.step = 1;
                }
@@ -1777,7 +1710,7 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head)
 static void tomoyo_read_version(struct tomoyo_io_buffer *head)
 {
        if (!head->r.eof) {
-               tomoyo_io_printf(head, "2.3.0");
+               tomoyo_io_printf(head, "2.4.0");
                head->r.eof = true;
        }
 }
index 139ad75..2b39e63 100644 (file)
@@ -211,6 +211,12 @@ enum tomoyo_mac_category_index {
  */
 #define TOMOYO_RETRY_REQUEST 1
 
+/* Index numbers for profile's PREFERENCE values. */
+enum tomoyo_pref_index {
+       TOMOYO_PREF_MAX_LEARNING_ENTRY,
+       TOMOYO_MAX_PREF
+};
+
 /********** Structure definitions. **********/
 
 /* Common header for holding ACL entries. */
@@ -497,6 +503,7 @@ struct tomoyo_profile {
        struct tomoyo_preference preference;
        u8 default_config;
        u8 config[TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX];
+       unsigned int pref[TOMOYO_MAX_PREF];
 };
 
 /********** Function prototypes. **********/
index 72cd2b9..adcbdeb 100644 (file)
@@ -899,35 +899,10 @@ const char *tomoyo_last_word(const char *name)
  */
 void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...)
 {
-       va_list args;
-       char *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;
-               break;
-       case TOMOYO_CONFIG_PERMISSIVE:
-               if (!profile->permissive->permissive_verbose)
-                       return;
-               break;
-       case TOMOYO_CONFIG_LEARNING:
-               if (!profile->learning->learning_verbose)
-                       return;
-               break;
-       }
-       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);
+       /*
+        * Temporarily disabled.
+        * Will be replaced with /sys/kernel/security/tomoyo/audit interface.
+        */
 }
 
 /**
@@ -978,13 +953,13 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
                        if (perm & (1 << i))
                                count++;
        }
-       if (count < tomoyo_profile(domain->profile)->learning->
-           learning_max_entry)
+       if (count < tomoyo_profile(domain->profile)->
+           pref[TOMOYO_PREF_MAX_LEARNING_ENTRY])
                return true;
        if (!domain->quota_warned) {
                domain->quota_warned = true;
                printk(KERN_WARNING "TOMOYO-WARNING: "
-                      "Domain '%s' has so many ACLs to hold. "
+                      "Domain '%s' has too many ACLs to hold. "
                       "Stopped learning mode.\n", domain->domainname->name);
        }
        return false;