diff options
author | James Morris <james.l.morris@oracle.com> | 2014-01-06 22:23:01 +1100 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2014-01-06 22:23:01 +1100 |
commit | 38fd2c202a3d82bc12430bce5789fa2c2a406f71 (patch) | |
tree | a73513dbb015155f5236b391709b9083916b3136 /security/integrity | |
parent | dcf4e392867bf98d50ad108ed7c2bfb941e8c33d (diff) | |
parent | d6e0a2dd12f4067a5bcefb8bbd8ddbeff800afbc (diff) | |
download | linux-38fd2c202a3d82bc12430bce5789fa2c2a406f71.tar.gz linux-38fd2c202a3d82bc12430bce5789fa2c2a406f71.tar.bz2 linux-38fd2c202a3d82bc12430bce5789fa2c2a406f71.zip |
Merge to v3.13-rc7 for prerequisite changes in the Xen code for TPM
Diffstat (limited to 'security/integrity')
-rw-r--r-- | security/integrity/digsig.c | 30 | ||||
-rw-r--r-- | security/integrity/ima/Kconfig | 8 | ||||
-rw-r--r-- | security/integrity/ima/ima.h | 7 | ||||
-rw-r--r-- | security/integrity/ima/ima_api.c | 22 | ||||
-rw-r--r-- | security/integrity/ima/ima_appraise.c | 11 | ||||
-rw-r--r-- | security/integrity/ima/ima_crypto.c | 17 | ||||
-rw-r--r-- | security/integrity/ima/ima_fs.c | 14 | ||||
-rw-r--r-- | security/integrity/ima/ima_init.c | 3 | ||||
-rw-r--r-- | security/integrity/ima/ima_template.c | 21 | ||||
-rw-r--r-- | security/integrity/ima/ima_template_lib.c | 6 | ||||
-rw-r--r-- | security/integrity/integrity.h | 7 |
11 files changed, 68 insertions, 78 deletions
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index 77ca965ab684..b4af4ebc5be2 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c @@ -13,9 +13,7 @@ #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> @@ -23,19 +21,11 @@ static struct key *keyring[INTEGRITY_KEYRING_MAX]; -#ifdef CONFIG_IMA_TRUSTED_KEYRING -static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { - ".evm", - ".module", - ".ima", -}; -#else static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { "_evm", "_module", "_ima", }; -#endif int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, const char *digest, int digestlen) @@ -45,7 +35,7 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, if (!keyring[id]) { keyring[id] = - request_key(&key_type_keyring, keyring_name[id], NULL); + request_key(&key_type_keyring, keyring_name[id], NULL); if (IS_ERR(keyring[id])) { int err = PTR_ERR(keyring[id]); pr_err("no %s keyring: %d\n", keyring_name[id], err); @@ -66,21 +56,3 @@ 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(); - const struct user_struct *user = cred->user; - - 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_ALLOC_NOT_IN_QUOTA, user->uid_keyring); - if (!IS_ERR(keyring[id])) - set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags); - else - pr_info("Can't allocate %s keyring (%ld)\n", - keyring_name[id], PTR_ERR(keyring[id])); - return 0; -} diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index dad8d4ca2437..81a27971d884 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -123,11 +123,3 @@ 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 - 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 bf03c6a16cc8..0356e1d437ca 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -26,7 +26,8 @@ #include "../integrity.h" -enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_ASCII }; +enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN, + IMA_SHOW_ASCII }; enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; /* digest size for IMA, fits SHA1 or MD5 */ @@ -97,7 +98,8 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, const char *op, struct inode *inode, const unsigned char *filename); int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash); -int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields, +int ima_calc_field_array_hash(struct ima_field_data *field_data, + struct ima_template_desc *desc, int num_fields, struct ima_digest_data *hash); int __init ima_calc_boot_aggregate(struct ima_digest_data *hash); void ima_add_violation(struct file *file, const unsigned char *filename, @@ -146,6 +148,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint, int xattr_len, struct ima_template_entry **entry); int ima_store_template(struct ima_template_entry *entry, int violation, struct inode *inode, const unsigned char *filename); +void ima_free_template_entry(struct ima_template_entry *entry); const char *ima_d_path(struct path *path, char **pathbuf); /* rbtree tree calls to lookup, insert, delete diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 0e7540863fc2..c38bbce8c6a6 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -22,6 +22,19 @@ #include "ima.h" /* + * ima_free_template_entry - free an existing template entry + */ +void ima_free_template_entry(struct ima_template_entry *entry) +{ + int i; + + for (i = 0; i < entry->template_desc->num_fields; i++) + kfree(entry->template_data[i].data); + + kfree(entry); +} + +/* * ima_alloc_init_template - create and initialize a new template entry */ int ima_alloc_init_template(struct integrity_iint_cache *iint, @@ -37,6 +50,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint, if (!*entry) return -ENOMEM; + (*entry)->template_desc = template_desc; for (i = 0; i < template_desc->num_fields; i++) { struct ima_template_field *field = template_desc->fields[i]; u32 len; @@ -51,10 +65,9 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint, (*entry)->template_data_len += sizeof(len); (*entry)->template_data_len += len; } - (*entry)->template_desc = template_desc; return 0; out: - kfree(*entry); + ima_free_template_entry(*entry); *entry = NULL; return result; } @@ -94,6 +107,7 @@ int ima_store_template(struct ima_template_entry *entry, /* this function uses default algo */ hash.hdr.algo = HASH_ALGO_SHA1; result = ima_calc_field_array_hash(&entry->template_data[0], + entry->template_desc, num_fields, &hash.hdr); if (result < 0) { integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, @@ -133,7 +147,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename, } result = ima_store_template(entry, violation, inode, filename); if (result < 0) - kfree(entry); + ima_free_template_entry(entry); err_out: integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, op, cause, result, 0); @@ -268,7 +282,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, if (!result || result == -EEXIST) iint->flags |= IMA_MEASURED; if (result < 0) - kfree(entry); + ima_free_template_entry(entry); } void ima_audit_measurement(struct integrity_iint_cache *iint, diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 46353ee517f6..734e9468aca0 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -381,14 +381,3 @@ int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name) } return result; } - -#ifdef CONFIG_IMA_TRUSTED_KEYRING -static int __init init_ima_keyring(void) -{ - int ret; - - ret = integrity_init_keyring(INTEGRITY_KEYRING_IMA); - return 0; -} -late_initcall(init_ima_keyring); -#endif diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 676e0292dfec..fdf60def52e9 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -140,6 +140,7 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) * Calculate the hash of template data */ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, + struct ima_template_desc *td, int num_fields, struct ima_digest_data *hash, struct crypto_shash *tfm) @@ -160,9 +161,13 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, return rc; for (i = 0; i < num_fields; i++) { - rc = crypto_shash_update(&desc.shash, - (const u8 *) &field_data[i].len, - sizeof(field_data[i].len)); + if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) { + rc = crypto_shash_update(&desc.shash, + (const u8 *) &field_data[i].len, + sizeof(field_data[i].len)); + if (rc) + break; + } rc = crypto_shash_update(&desc.shash, field_data[i].data, field_data[i].len); if (rc) @@ -175,7 +180,8 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, return rc; } -int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields, +int ima_calc_field_array_hash(struct ima_field_data *field_data, + struct ima_template_desc *desc, int num_fields, struct ima_digest_data *hash) { struct crypto_shash *tfm; @@ -185,7 +191,8 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields, if (IS_ERR(tfm)) return PTR_ERR(tfm); - rc = ima_calc_field_array_hash_tfm(field_data, num_fields, hash, tfm); + rc = ima_calc_field_array_hash_tfm(field_data, desc, num_fields, + hash, tfm); ima_free_tfm(tfm); diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index d47a7c86a21d..db01125926bd 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -120,6 +120,7 @@ static int ima_measurements_show(struct seq_file *m, void *v) struct ima_template_entry *e; int namelen; u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX; + bool is_ima_template = false; int i; /* get entry */ @@ -145,14 +146,21 @@ static int ima_measurements_show(struct seq_file *m, void *v) ima_putc(m, e->template_desc->name, namelen); /* 5th: template length (except for 'ima' template) */ - if (strcmp(e->template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) + if (strcmp(e->template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0) + is_ima_template = true; + + if (!is_ima_template) ima_putc(m, &e->template_data_len, sizeof(e->template_data_len)); /* 6th: template specific data */ for (i = 0; i < e->template_desc->num_fields; i++) { - e->template_desc->fields[i]->field_show(m, IMA_SHOW_BINARY, - &e->template_data[i]); + enum ima_show_type show = IMA_SHOW_BINARY; + struct ima_template_field *field = e->template_desc->fields[i]; + + if (is_ima_template && strcmp(field->field_id, "d") == 0) + show = IMA_SHOW_BINARY_NO_FIELD_LEN; + field->field_show(m, show, &e->template_data[i]); } return 0; } diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 15f34bd40abe..37122768554a 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -63,7 +63,6 @@ static void __init ima_add_boot_aggregate(void) result = ima_calc_boot_aggregate(&hash.hdr); if (result < 0) { audit_cause = "hashing_error"; - kfree(entry); goto err_out; } } @@ -76,7 +75,7 @@ static void __init ima_add_boot_aggregate(void) result = ima_store_template(entry, violation, NULL, boot_aggregate_name); if (result < 0) - kfree(entry); + ima_free_template_entry(entry); return; err_out: integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op, diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index 4e5da990630b..635695f6a185 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c @@ -90,7 +90,7 @@ static struct ima_template_field *lookup_template_field(const char *field_id) return NULL; } -static int template_fmt_size(char *template_fmt) +static int template_fmt_size(const char *template_fmt) { char c; int template_fmt_len = strlen(template_fmt); @@ -106,22 +106,29 @@ static int template_fmt_size(char *template_fmt) return j + 1; } -static int template_desc_init_fields(char *template_fmt, +static int template_desc_init_fields(const char *template_fmt, struct ima_template_field ***fields, int *num_fields) { - char *c, *template_fmt_ptr = template_fmt; + char *c, *template_fmt_copy, *template_fmt_ptr; int template_num_fields = template_fmt_size(template_fmt); int i, result = 0; if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) return -EINVAL; + /* copying is needed as strsep() modifies the original buffer */ + template_fmt_copy = kstrdup(template_fmt, GFP_KERNEL); + if (template_fmt_copy == NULL) + return -ENOMEM; + *fields = kzalloc(template_num_fields * sizeof(*fields), GFP_KERNEL); if (*fields == NULL) { result = -ENOMEM; goto out; } + + template_fmt_ptr = template_fmt_copy; for (i = 0; (c = strsep(&template_fmt_ptr, "|")) != NULL && i < template_num_fields; i++) { struct ima_template_field *f = lookup_template_field(c); @@ -133,10 +140,12 @@ static int template_desc_init_fields(char *template_fmt, (*fields)[i] = f; } *num_fields = i; - return 0; out: - kfree(*fields); - *fields = NULL; + if (result < 0) { + kfree(*fields); + *fields = NULL; + } + kfree(template_fmt_copy); return result; } diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c index 6d01c694a32c..1683bbf289a4 100644 --- a/security/integrity/ima/ima_template_lib.c +++ b/security/integrity/ima/ima_template_lib.c @@ -109,9 +109,12 @@ static void ima_show_template_data_binary(struct seq_file *m, enum data_formats datafmt, struct ima_field_data *field_data) { - ima_putc(m, &field_data->len, sizeof(u32)); + if (show != IMA_SHOW_BINARY_NO_FIELD_LEN) + ima_putc(m, &field_data->len, sizeof(u32)); + if (!field_data->len) return; + ima_putc(m, field_data->data, field_data->len); } @@ -125,6 +128,7 @@ static void ima_show_template_field_data(struct seq_file *m, ima_show_template_data_ascii(m, show, datafmt, field_data); break; case IMA_SHOW_BINARY: + case IMA_SHOW_BINARY_NO_FIELD_LEN: ima_show_template_data_binary(m, show, datafmt, field_data); break; default: diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index b9e7c133734a..2fb5e53e927f 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -137,19 +137,12 @@ static inline int integrity_digsig_verify(const unsigned int id, #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS int asymmetric_verify(struct key *keyring, const char *sig, int siglen, const char *data, int datalen); - -int integrity_init_keyring(const unsigned int id); #else static inline int asymmetric_verify(struct key *keyring, const char *sig, int siglen, const char *data, int datalen) { return -EOPNOTSUPP; } - -static int integrity_init_keyring(const unsigned int id) -{ - return 0; -} #endif #ifdef CONFIG_INTEGRITY_AUDIT |