Commit 3af4977e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security

Pull IMA fixes from James Morris:
 "These three patches fix regressions in the IMA code in your current
  tree.

  The first fixes a couple of bugs in template_desc_init_fields(), and
  the other two ensure that changes in this kernel don't break
  userspace"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  ima: make a copy of template_fmt in template_desc_init_fields()
  ima: do not send field length to userspace for digest of ima template
  ima: do not include field length in template digest calc for ima template
parents b9548514 6df025c1
...@@ -26,7 +26,8 @@ ...@@ -26,7 +26,8 @@
#include "../integrity.h" #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 }; enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
/* digest size for IMA, fits SHA1 or MD5 */ /* digest size for IMA, fits SHA1 or MD5 */
...@@ -97,7 +98,8 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, ...@@ -97,7 +98,8 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
const char *op, struct inode *inode, const char *op, struct inode *inode,
const unsigned char *filename); const unsigned char *filename);
int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash); 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); struct ima_digest_data *hash);
int __init ima_calc_boot_aggregate(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, void ima_add_violation(struct file *file, const unsigned char *filename,
......
...@@ -94,6 +94,7 @@ int ima_store_template(struct ima_template_entry *entry, ...@@ -94,6 +94,7 @@ int ima_store_template(struct ima_template_entry *entry,
/* this function uses default algo */ /* this function uses default algo */
hash.hdr.algo = HASH_ALGO_SHA1; hash.hdr.algo = HASH_ALGO_SHA1;
result = ima_calc_field_array_hash(&entry->template_data[0], result = ima_calc_field_array_hash(&entry->template_data[0],
entry->template_desc,
num_fields, &hash.hdr); num_fields, &hash.hdr);
if (result < 0) { if (result < 0) {
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
......
...@@ -140,6 +140,7 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) ...@@ -140,6 +140,7 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
* Calculate the hash of template data * Calculate the hash of template data
*/ */
static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
struct ima_template_desc *td,
int num_fields, int num_fields,
struct ima_digest_data *hash, struct ima_digest_data *hash,
struct crypto_shash *tfm) struct crypto_shash *tfm)
...@@ -160,9 +161,13 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, ...@@ -160,9 +161,13 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
return rc; return rc;
for (i = 0; i < num_fields; i++) { for (i = 0; i < num_fields; i++) {
rc = crypto_shash_update(&desc.shash, if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) {
(const u8 *) &field_data[i].len, rc = crypto_shash_update(&desc.shash,
sizeof(field_data[i].len)); (const u8 *) &field_data[i].len,
sizeof(field_data[i].len));
if (rc)
break;
}
rc = crypto_shash_update(&desc.shash, field_data[i].data, rc = crypto_shash_update(&desc.shash, field_data[i].data,
field_data[i].len); field_data[i].len);
if (rc) if (rc)
...@@ -175,7 +180,8 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, ...@@ -175,7 +180,8 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
return rc; 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 ima_digest_data *hash)
{ {
struct crypto_shash *tfm; struct crypto_shash *tfm;
...@@ -185,7 +191,8 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields, ...@@ -185,7 +191,8 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields,
if (IS_ERR(tfm)) if (IS_ERR(tfm))
return PTR_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); ima_free_tfm(tfm);
......
...@@ -120,6 +120,7 @@ static int ima_measurements_show(struct seq_file *m, void *v) ...@@ -120,6 +120,7 @@ static int ima_measurements_show(struct seq_file *m, void *v)
struct ima_template_entry *e; struct ima_template_entry *e;
int namelen; int namelen;
u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX; u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX;
bool is_ima_template = false;
int i; int i;
/* get entry */ /* get entry */
...@@ -145,14 +146,21 @@ static int ima_measurements_show(struct seq_file *m, void *v) ...@@ -145,14 +146,21 @@ static int ima_measurements_show(struct seq_file *m, void *v)
ima_putc(m, e->template_desc->name, namelen); ima_putc(m, e->template_desc->name, namelen);
/* 5th: template length (except for 'ima' template) */ /* 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, ima_putc(m, &e->template_data_len,
sizeof(e->template_data_len)); sizeof(e->template_data_len));
/* 6th: template specific data */ /* 6th: template specific data */
for (i = 0; i < e->template_desc->num_fields; i++) { for (i = 0; i < e->template_desc->num_fields; i++) {
e->template_desc->fields[i]->field_show(m, IMA_SHOW_BINARY, enum ima_show_type show = IMA_SHOW_BINARY;
&e->template_data[i]); 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; return 0;
} }
......
...@@ -90,7 +90,7 @@ static struct ima_template_field *lookup_template_field(const char *field_id) ...@@ -90,7 +90,7 @@ static struct ima_template_field *lookup_template_field(const char *field_id)
return NULL; return NULL;
} }
static int template_fmt_size(char *template_fmt) static int template_fmt_size(const char *template_fmt)
{ {
char c; char c;
int template_fmt_len = strlen(template_fmt); int template_fmt_len = strlen(template_fmt);
...@@ -106,23 +106,28 @@ static int template_fmt_size(char *template_fmt) ...@@ -106,23 +106,28 @@ static int template_fmt_size(char *template_fmt)
return j + 1; 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, struct ima_template_field ***fields,
int *num_fields) int *num_fields)
{ {
char *c, *template_fmt_ptr = template_fmt; char *c, *template_fmt_copy;
int template_num_fields = template_fmt_size(template_fmt); int template_num_fields = template_fmt_size(template_fmt);
int i, result = 0; int i, result = 0;
if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX)
return -EINVAL; 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); *fields = kzalloc(template_num_fields * sizeof(*fields), GFP_KERNEL);
if (*fields == NULL) { if (*fields == NULL) {
result = -ENOMEM; result = -ENOMEM;
goto out; goto out;
} }
for (i = 0; (c = strsep(&template_fmt_ptr, "|")) != NULL && for (i = 0; (c = strsep(&template_fmt_copy, "|")) != NULL &&
i < template_num_fields; i++) { i < template_num_fields; i++) {
struct ima_template_field *f = lookup_template_field(c); struct ima_template_field *f = lookup_template_field(c);
...@@ -133,10 +138,12 @@ static int template_desc_init_fields(char *template_fmt, ...@@ -133,10 +138,12 @@ static int template_desc_init_fields(char *template_fmt,
(*fields)[i] = f; (*fields)[i] = f;
} }
*num_fields = i; *num_fields = i;
return 0;
out: out:
kfree(*fields); if (result < 0) {
*fields = NULL; kfree(*fields);
*fields = NULL;
}
kfree(template_fmt_copy);
return result; return result;
} }
......
...@@ -109,9 +109,12 @@ static void ima_show_template_data_binary(struct seq_file *m, ...@@ -109,9 +109,12 @@ static void ima_show_template_data_binary(struct seq_file *m,
enum data_formats datafmt, enum data_formats datafmt,
struct ima_field_data *field_data) 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) if (!field_data->len)
return; return;
ima_putc(m, field_data->data, field_data->len); ima_putc(m, field_data->data, field_data->len);
} }
...@@ -125,6 +128,7 @@ static void ima_show_template_field_data(struct seq_file *m, ...@@ -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); ima_show_template_data_ascii(m, show, datafmt, field_data);
break; break;
case IMA_SHOW_BINARY: case IMA_SHOW_BINARY:
case IMA_SHOW_BINARY_NO_FIELD_LEN:
ima_show_template_data_binary(m, show, datafmt, field_data); ima_show_template_data_binary(m, show, datafmt, field_data);
break; break;
default: default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment