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
This commit is contained in:
commit
3af4977ed6
|
@ -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,
|
||||||
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,
|
||||||
/* 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)
|
||||||
* 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,
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
(*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,
|
||||||
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,
|
||||||
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:
|
||||||
|
|
Loading…
Reference in New Issue