Commit bcbc9b0c authored by Mimi Zohar's avatar Mimi Zohar

ima: extend the measurement list to include the file signature

This patch defines a new template called 'ima-sig', which includes
the file signature in the template data, in addition to the file's
digest and pathname.

A template is composed of a set of fields.  Associated with each
field is an initialization and display function.  This patch defines
a new template field called 'sig', the initialization function
ima_eventsig_init(), and the display function ima_show_template_sig().

This patch modifies the .field_init() function definition to include
the 'security.ima' extended attribute and length.

Changelog:
- remove unused code (Dmitry Kasatkin)
- avoid calling ima_write_template_field_data() unnecesarily (Roberto Sassu)
- rename DATA_FMT_SIG to DATA_FMT_HEX
- cleanup ima_eventsig_init() based on Roberto's comments
Signed-off-by: default avatarMimi Zohar <zohar@linux.vnet.ibm.com>
Signed-off-by: default avatarDmitry Kasatkin <d.kasatkin@samsung.com>
Signed-off-by: default avatarRoberto Sassu <roberto.sassu@polito.it>
parent 42a20ba5
...@@ -63,6 +63,8 @@ choice ...@@ -63,6 +63,8 @@ choice
bool "ima" bool "ima"
config IMA_NG_TEMPLATE config IMA_NG_TEMPLATE
bool "ima-ng (default)" bool "ima-ng (default)"
config IMA_SIG_TEMPLATE
bool "ima-sig"
endchoice endchoice
config IMA_DEFAULT_TEMPLATE config IMA_DEFAULT_TEMPLATE
...@@ -70,6 +72,7 @@ config IMA_DEFAULT_TEMPLATE ...@@ -70,6 +72,7 @@ config IMA_DEFAULT_TEMPLATE
depends on IMA depends on IMA
default "ima" if IMA_TEMPLATE default "ima" if IMA_TEMPLATE
default "ima-ng" if IMA_NG_TEMPLATE default "ima-ng" if IMA_NG_TEMPLATE
default "ima-sig" if IMA_SIG_TEMPLATE
choice choice
prompt "Default integrity hash algorithm" prompt "Default integrity hash algorithm"
......
...@@ -59,7 +59,8 @@ struct ima_template_field { ...@@ -59,7 +59,8 @@ struct ima_template_field {
const char field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN]; const char field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN];
int (*field_init) (struct integrity_iint_cache *iint, struct file *file, int (*field_init) (struct integrity_iint_cache *iint, struct file *file,
const unsigned char *filename, const unsigned char *filename,
struct ima_field_data *field_data); struct evm_ima_xattr_data *xattr_value,
int xattr_len, struct ima_field_data *field_data);
void (*field_show) (struct seq_file *m, enum ima_show_type show, void (*field_show) (struct seq_file *m, enum ima_show_type show,
struct ima_field_data *field_data); struct ima_field_data *field_data);
}; };
...@@ -134,12 +135,15 @@ int ima_collect_measurement(struct integrity_iint_cache *iint, ...@@ -134,12 +135,15 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
struct evm_ima_xattr_data **xattr_value, struct evm_ima_xattr_data **xattr_value,
int *xattr_len); int *xattr_len);
void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
const unsigned char *filename); const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value,
int xattr_len);
void ima_audit_measurement(struct integrity_iint_cache *iint, void ima_audit_measurement(struct integrity_iint_cache *iint,
const unsigned char *filename); const unsigned char *filename);
int ima_alloc_init_template(struct integrity_iint_cache *iint, int ima_alloc_init_template(struct integrity_iint_cache *iint,
struct file *file, const unsigned char *filename, struct file *file, const unsigned char *filename,
struct ima_template_entry **entry); struct evm_ima_xattr_data *xattr_value,
int xattr_len, struct ima_template_entry **entry);
int ima_store_template(struct ima_template_entry *entry, int violation, int ima_store_template(struct ima_template_entry *entry, int violation,
struct inode *inode, const unsigned char *filename); struct inode *inode, const unsigned char *filename);
const char *ima_d_path(struct path *path, char **pathbuf); const char *ima_d_path(struct path *path, char **pathbuf);
......
...@@ -26,7 +26,8 @@ ...@@ -26,7 +26,8 @@
*/ */
int ima_alloc_init_template(struct integrity_iint_cache *iint, int ima_alloc_init_template(struct integrity_iint_cache *iint,
struct file *file, const unsigned char *filename, struct file *file, const unsigned char *filename,
struct ima_template_entry **entry) struct evm_ima_xattr_data *xattr_value,
int xattr_len, struct ima_template_entry **entry)
{ {
struct ima_template_desc *template_desc = ima_template_desc_current(); struct ima_template_desc *template_desc = ima_template_desc_current();
int i, result = 0; int i, result = 0;
...@@ -41,6 +42,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint, ...@@ -41,6 +42,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
u32 len; u32 len;
result = field->field_init(iint, file, filename, result = field->field_init(iint, file, filename,
xattr_value, xattr_len,
&((*entry)->template_data[i])); &((*entry)->template_data[i]));
if (result != 0) if (result != 0)
goto out; goto out;
...@@ -123,7 +125,8 @@ void ima_add_violation(struct file *file, const unsigned char *filename, ...@@ -123,7 +125,8 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
/* can overflow, only indicator */ /* can overflow, only indicator */
atomic_long_inc(&ima_htable.violations); atomic_long_inc(&ima_htable.violations);
result = ima_alloc_init_template(NULL, file, filename, &entry); result = ima_alloc_init_template(NULL, file, filename,
NULL, 0, &entry);
if (result < 0) { if (result < 0) {
result = -ENOMEM; result = -ENOMEM;
goto err_out; goto err_out;
...@@ -239,7 +242,9 @@ int ima_collect_measurement(struct integrity_iint_cache *iint, ...@@ -239,7 +242,9 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
* Must be called with iint->mutex held. * Must be called with iint->mutex held.
*/ */
void ima_store_measurement(struct integrity_iint_cache *iint, void ima_store_measurement(struct integrity_iint_cache *iint,
struct file *file, const unsigned char *filename) struct file *file, const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value,
int xattr_len)
{ {
const char *op = "add_template_measure"; const char *op = "add_template_measure";
const char *audit_cause = "ENOMEM"; const char *audit_cause = "ENOMEM";
...@@ -251,7 +256,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint, ...@@ -251,7 +256,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
if (iint->flags & IMA_MEASURED) if (iint->flags & IMA_MEASURED)
return; return;
result = ima_alloc_init_template(iint, file, filename, &entry); result = ima_alloc_init_template(iint, file, filename,
xattr_value, xattr_len, &entry);
if (result < 0) { if (result < 0) {
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
op, audit_cause, result, 0); op, audit_cause, result, 0);
......
...@@ -69,7 +69,7 @@ static void __init ima_add_boot_aggregate(void) ...@@ -69,7 +69,7 @@ static void __init ima_add_boot_aggregate(void)
} }
result = ima_alloc_init_template(iint, NULL, boot_aggregate_name, result = ima_alloc_init_template(iint, NULL, boot_aggregate_name,
&entry); NULL, 0, &entry);
if (result < 0) if (result < 0)
return; return;
......
...@@ -225,7 +225,8 @@ static int process_measurement(struct file *file, const char *filename, ...@@ -225,7 +225,8 @@ static int process_measurement(struct file *file, const char *filename,
pathname = (const char *)file->f_dentry->d_name.name; pathname = (const char *)file->f_dentry->d_name.name;
if (action & IMA_MEASURE) if (action & IMA_MEASURE)
ima_store_measurement(iint, file, pathname); ima_store_measurement(iint, file, pathname,
xattr_value, xattr_len);
if (action & IMA_APPRAISE_SUBMASK) if (action & IMA_APPRAISE_SUBMASK)
rc = ima_appraise_measurement(_func, iint, file, pathname, rc = ima_appraise_measurement(_func, iint, file, pathname,
xattr_value, xattr_len); xattr_value, xattr_len);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
static struct ima_template_desc defined_templates[] = { static struct ima_template_desc defined_templates[] = {
{.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT}, {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
{.name = "ima-ng",.fmt = "d-ng|n-ng"}, {.name = "ima-ng",.fmt = "d-ng|n-ng"},
{.name = "ima-sig",.fmt = "d-ng|n-ng|sig"},
}; };
static struct ima_template_field supported_fields[] = { static struct ima_template_field supported_fields[] = {
...@@ -31,6 +32,8 @@ static struct ima_template_field supported_fields[] = { ...@@ -31,6 +32,8 @@ static struct ima_template_field supported_fields[] = {
.field_show = ima_show_template_digest_ng}, .field_show = ima_show_template_digest_ng},
{.field_id = "n-ng",.field_init = ima_eventname_ng_init, {.field_id = "n-ng",.field_init = ima_eventname_ng_init,
.field_show = ima_show_template_string}, .field_show = ima_show_template_string},
{.field_id = "sig",.field_init = ima_eventsig_init,
.field_show = ima_show_template_sig},
}; };
static struct ima_template_desc *ima_template; static struct ima_template_desc *ima_template;
......
...@@ -28,7 +28,8 @@ enum data_formats { ...@@ -28,7 +28,8 @@ enum data_formats {
DATA_FMT_DIGEST = 0, DATA_FMT_DIGEST = 0,
DATA_FMT_DIGEST_WITH_ALGO, DATA_FMT_DIGEST_WITH_ALGO,
DATA_FMT_EVENT_NAME, DATA_FMT_EVENT_NAME,
DATA_FMT_STRING DATA_FMT_STRING,
DATA_FMT_HEX
}; };
static int ima_write_template_field_data(const void *data, const u32 datalen, static int ima_write_template_field_data(const void *data, const u32 datalen,
...@@ -90,6 +91,9 @@ static void ima_show_template_data_ascii(struct seq_file *m, ...@@ -90,6 +91,9 @@ static void ima_show_template_data_ascii(struct seq_file *m,
buf_ptr += 2; buf_ptr += 2;
buflen -= buf_ptr - field_data->data; buflen -= buf_ptr - field_data->data;
case DATA_FMT_DIGEST: case DATA_FMT_DIGEST:
case DATA_FMT_HEX:
if (!buflen)
break;
ima_print_digest(m, buf_ptr, buflen); ima_print_digest(m, buf_ptr, buflen);
break; break;
case DATA_FMT_STRING: case DATA_FMT_STRING:
...@@ -147,6 +151,12 @@ void ima_show_template_string(struct seq_file *m, enum ima_show_type show, ...@@ -147,6 +151,12 @@ void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data); ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data);
} }
void ima_show_template_sig(struct seq_file *m, enum ima_show_type show,
struct ima_field_data *field_data)
{
ima_show_template_field_data(m, show, DATA_FMT_HEX, field_data);
}
static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo, static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo,
struct ima_field_data *field_data, struct ima_field_data *field_data,
bool size_limit) bool size_limit)
...@@ -190,6 +200,7 @@ static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo, ...@@ -190,6 +200,7 @@ static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo,
*/ */
int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
const unsigned char *filename, const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value, int xattr_len,
struct ima_field_data *field_data) struct ima_field_data *field_data)
{ {
struct { struct {
...@@ -237,7 +248,8 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, ...@@ -237,7 +248,8 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
*/ */
int ima_eventdigest_ng_init(struct integrity_iint_cache *iint, int ima_eventdigest_ng_init(struct integrity_iint_cache *iint,
struct file *file, const unsigned char *filename, struct file *file, const unsigned char *filename,
struct ima_field_data *field_data) struct evm_ima_xattr_data *xattr_value,
int xattr_len, struct ima_field_data *field_data)
{ {
u8 *cur_digest = NULL, hash_algo = HASH_ALGO__LAST; u8 *cur_digest = NULL, hash_algo = HASH_ALGO__LAST;
u32 cur_digestsize = 0; u32 cur_digestsize = 0;
...@@ -295,6 +307,7 @@ static int ima_eventname_init_common(struct integrity_iint_cache *iint, ...@@ -295,6 +307,7 @@ static int ima_eventname_init_common(struct integrity_iint_cache *iint,
*/ */
int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file, int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file,
const unsigned char *filename, const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value, int xattr_len,
struct ima_field_data *field_data) struct ima_field_data *field_data)
{ {
return ima_eventname_init_common(iint, file, filename, return ima_eventname_init_common(iint, file, filename,
...@@ -306,8 +319,29 @@ int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file, ...@@ -306,8 +319,29 @@ int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file,
*/ */
int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file, int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file,
const unsigned char *filename, const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value, int xattr_len,
struct ima_field_data *field_data) struct ima_field_data *field_data)
{ {
return ima_eventname_init_common(iint, file, filename, return ima_eventname_init_common(iint, file, filename,
field_data, false); field_data, false);
} }
/*
* ima_eventsig_init - include the file signature as part of the template data
*/
int ima_eventsig_init(struct integrity_iint_cache *iint, struct file *file,
const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value, int xattr_len,
struct ima_field_data *field_data)
{
enum data_formats fmt = DATA_FMT_HEX;
int rc = 0;
if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG))
goto out;
rc = ima_write_template_field_data(xattr_value, xattr_len, fmt,
field_data);
out:
return rc;
}
...@@ -24,16 +24,26 @@ void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show, ...@@ -24,16 +24,26 @@ void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show,
struct ima_field_data *field_data); struct ima_field_data *field_data);
void ima_show_template_string(struct seq_file *m, enum ima_show_type show, void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
struct ima_field_data *field_data); struct ima_field_data *field_data);
void ima_show_template_sig(struct seq_file *m, enum ima_show_type show,
struct ima_field_data *field_data);
int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file, int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
const unsigned char *filename, const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value, int xattr_len,
struct ima_field_data *field_data); struct ima_field_data *field_data);
int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file, int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file,
const unsigned char *filename, const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value, int xattr_len,
struct ima_field_data *field_data); struct ima_field_data *field_data);
int ima_eventdigest_ng_init(struct integrity_iint_cache *iint, int ima_eventdigest_ng_init(struct integrity_iint_cache *iint,
struct file *file, const unsigned char *filename, struct file *file, const unsigned char *filename,
struct ima_field_data *field_data); struct evm_ima_xattr_data *xattr_value,
int xattr_len, struct ima_field_data *field_data);
int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file, int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file,
const unsigned char *filename, const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value, int xattr_len,
struct ima_field_data *field_data); struct ima_field_data *field_data);
int ima_eventsig_init(struct integrity_iint_cache *iint, struct file *file,
const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value, int xattr_len,
struct ima_field_data *field_data);
#endif /* __LINUX_IMA_TEMPLATE_LIB_H */ #endif /* __LINUX_IMA_TEMPLATE_LIB_H */
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