diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 465df022c211..2b280350708f 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -11,16 +11,6 @@ #include #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 (!strcmp(data, "PREFERENCE")) { + for (i = 0; i < TOMOYO_MAX_PREF; i++) + tomoyo_set_uint(&profile->pref[i], cp, + tomoyo_pref_keywords[i]); + return 0; } - 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; - } - 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; } } diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 139ad7544460..2b39e63234c8 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -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. **********/ diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 72cd2b97cae8..adcbdebd7352 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c @@ -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;