diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2014-07-14 12:50:58 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2014-07-14 12:50:58 +1000 |
commit | 14cc51024c02b21a156d5ef1e9d3b6deb569e3b8 (patch) | |
tree | fe6756e5be923f4b4cb9811d7bd70938e0739945 /security | |
parent | 912ac8e427353ecb2aa8b4f5f855b83e2bba2556 (diff) | |
parent | a0f9fd9d6d8a2eaa004c2f15ceb234396bbdb45e (diff) |
Merge remote-tracking branch 'integrity/next'
Diffstat (limited to 'security')
-rw-r--r-- | security/integrity/digsig.c | 28 | ||||
-rw-r--r-- | security/integrity/ima/Kconfig | 10 | ||||
-rw-r--r-- | security/integrity/ima/ima.h | 12 | ||||
-rw-r--r-- | security/integrity/ima/ima_appraise.c | 2 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 17 | ||||
-rw-r--r-- | security/integrity/ima/ima_policy.c | 6 | ||||
-rw-r--r-- | security/integrity/integrity.h | 5 | ||||
-rw-r--r-- | security/keys/keyctl.c | 6 |
8 files changed, 73 insertions, 13 deletions
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index b4af4ebc5be2..8d4fbff8b87c 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c @@ -13,7 +13,9 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/err.h> +#include <linux/sched.h> #include <linux/rbtree.h> +#include <linux/cred.h> #include <linux/key-type.h> #include <linux/digsig.h> @@ -24,7 +26,11 @@ static struct key *keyring[INTEGRITY_KEYRING_MAX]; static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { "_evm", "_module", +#ifndef CONFIG_IMA_TRUSTED_KEYRING "_ima", +#else + ".ima", +#endif }; int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, @@ -56,3 +62,25 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, return -EOPNOTSUPP; } + +int integrity_init_keyring(const unsigned int id) +{ + const struct cred *cred = current_cred(); + int err = 0; + + keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), + KGIDT_INIT(0), cred, + ((KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW | KEY_USR_READ | + KEY_USR_WRITE | KEY_USR_SEARCH), + KEY_ALLOC_NOT_IN_QUOTA, NULL); + if (!IS_ERR(keyring[id])) + set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags); + else { + err = PTR_ERR(keyring[id]); + pr_info("Can't allocate %s keyring (%d)\n", + keyring_name[id], err); + keyring[id] = NULL; + } + return err; +} diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 81a27971d884..08758fbd496f 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -123,3 +123,13 @@ config IMA_APPRAISE For more information on integrity appraisal refer to: <http://linux-ima.sourceforge.net> If unsure, say N. + +config IMA_TRUSTED_KEYRING + bool "Require all keys on the .ima keyring be signed" + depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING + depends on INTEGRITY_ASYMMETRIC_KEYS + select KEYS_DEBUG_PROC_KEYS + default y + help + This option requires that all keys added to the .ima + keyring be signed by a key on the system trusted keyring. diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index f79fa8be203c..c42056edfc97 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -249,4 +249,16 @@ static inline int security_filter_rule_match(u32 secid, u32 field, u32 op, return -EINVAL; } #endif /* CONFIG_IMA_LSM_RULES */ + +#ifdef CONFIG_IMA_TRUSTED_KEYRING +static inline int ima_init_keyring(const unsigned int id) +{ + return integrity_init_keyring(id); +} +#else +static inline int ima_init_keyring(const unsigned int id) +{ + return 0; +} +#endif /* CONFIG_IMA_TRUSTED_KEYRING */ #endif diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index d3113d4aaa3c..59ac90275070 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -214,7 +214,7 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, hash_start = 1; case IMA_XATTR_DIGEST: if (iint->flags & IMA_DIGSIG_REQUIRED) { - cause = "IMA signature required"; + cause = "IMA-signature-required"; status = INTEGRITY_FAIL; break; } diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 09baa335ebc7..0d696431209c 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -88,8 +88,6 @@ static void ima_rdwr_violation_check(struct file *file) if (!S_ISREG(inode->i_mode) || !ima_initialized) return; - mutex_lock(&inode->i_mutex); /* file metadata: permissions, xattr */ - if (mode & FMODE_WRITE) { if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { struct integrity_iint_cache *iint; @@ -104,8 +102,6 @@ static void ima_rdwr_violation_check(struct file *file) send_writers = true; } - mutex_unlock(&inode->i_mutex); - if (!send_tomtou && !send_writers) return; @@ -163,7 +159,7 @@ static int process_measurement(struct file *file, const char *filename, { struct inode *inode = file_inode(file); struct integrity_iint_cache *iint; - struct ima_template_desc *template_desc = ima_template_desc_current(); + struct ima_template_desc *template_desc; char *pathbuf = NULL; const char *pathname = NULL; int rc = -ENOMEM, action, must_appraise, _func; @@ -207,6 +203,7 @@ static int process_measurement(struct file *file, const char *filename, goto out_digsig; } + template_desc = ima_template_desc_current(); if (strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0) { if (action & IMA_APPRAISE_SUBMASK) xattr_ptr = &xattr_value; @@ -328,8 +325,14 @@ static int __init init_ima(void) hash_setup(CONFIG_IMA_DEFAULT_HASH); error = ima_init(); - if (!error) - ima_initialized = 1; + if (error) + goto out; + + error = ima_init_keyring(INTEGRITY_KEYRING_IMA); + if (error) + goto out; + ima_initialized = 1; +out: return error; } diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 40a7488f6721..cea84d8bd7be 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -332,7 +332,7 @@ void __init ima_init_policy(void) void ima_update_policy(void) { static const char op[] = "policy_update"; - const char *cause = "already exists"; + const char *cause = "already-exists"; int result = 1; int audit_info = 0; @@ -659,7 +659,7 @@ ssize_t ima_parse_add_rule(char *rule) /* Prevent installed policy from changing */ if (ima_rules != &ima_default_rules) { integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, - NULL, op, "already exists", + NULL, op, "already-exists", -EACCES, audit_info); return -EACCES; } @@ -685,7 +685,7 @@ ssize_t ima_parse_add_rule(char *rule) if (result) { kfree(entry); integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, - NULL, op, "invalid policy", result, + NULL, op, "invalid-policy", result, audit_info); return result; } diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 33c0a70f6b15..09c440d9aaee 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -124,6 +124,7 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode); int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, const char *digest, int digestlen); +int integrity_init_keyring(const unsigned int id); #else static inline int integrity_digsig_verify(const unsigned int id, @@ -133,6 +134,10 @@ static inline int integrity_digsig_verify(const unsigned int id, return -EOPNOTSUPP; } +static inline int integrity_init_keyring(const unsigned int id) +{ + return 0; +} #endif /* CONFIG_INTEGRITY_SIGNATURE */ #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index cd5bd0cef25d..8a8c23357291 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -37,8 +37,6 @@ static int key_get_type_from_user(char *type, return ret; if (ret == 0 || ret >= len) return -EINVAL; - if (type[0] == '.') - return -EPERM; type[len - 1] = '\0'; return 0; } @@ -86,6 +84,10 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, if (!*description) { kfree(description); description = NULL; + } else if ((description[0] == '.') && + (strncmp(type, "keyring", 7) == 0)) { + ret = -EPERM; + goto error2; } } |