forked from luck/tmp_suning_uos_patched
ima: Define ima-modsig template
Define new "d-modsig" template field which holds the digest that is expected to match the one contained in the modsig, and also new "modsig" template field which holds the appended file signature. Add a new "ima-modsig" defined template descriptor with the new fields as well as the ones from the "ima-sig" descriptor. Change ima_store_measurement() to accept a struct modsig * argument so that it can be passed along to the templates via struct ima_event_data. Suggested-by: Mimi Zohar <zohar@linux.ibm.com> Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com> Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
This commit is contained in:
parent
15588227e0
commit
3878d505aa
|
@ -68,8 +68,10 @@ descriptors by adding their identifier to the format string
|
||||||
- 'd-ng': the digest of the event, calculated with an arbitrary hash
|
- 'd-ng': the digest of the event, calculated with an arbitrary hash
|
||||||
algorithm (field format: [<hash algo>:]digest, where the digest
|
algorithm (field format: [<hash algo>:]digest, where the digest
|
||||||
prefix is shown only if the hash algorithm is not SHA1 or MD5);
|
prefix is shown only if the hash algorithm is not SHA1 or MD5);
|
||||||
|
- 'd-modsig': the digest of the event without the appended modsig;
|
||||||
- 'n-ng': the name of the event, without size limitations;
|
- 'n-ng': the name of the event, without size limitations;
|
||||||
- 'sig': the file signature;
|
- 'sig': the file signature;
|
||||||
|
- 'modsig' the appended file signature;
|
||||||
- 'buf': the buffer data that was used to generate the hash without size limitations;
|
- 'buf': the buffer data that was used to generate the hash without size limitations;
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,6 +81,7 @@ Below, there is the list of defined template descriptors:
|
||||||
- "ima-ng" (default): its format is ``d-ng|n-ng``;
|
- "ima-ng" (default): its format is ``d-ng|n-ng``;
|
||||||
- "ima-sig": its format is ``d-ng|n-ng|sig``;
|
- "ima-sig": its format is ``d-ng|n-ng|sig``;
|
||||||
- "ima-buf": its format is ``d-ng|n-ng|buf``;
|
- "ima-buf": its format is ``d-ng|n-ng|buf``;
|
||||||
|
- "ima-modsig": its format is ``d-ng|n-ng|sig|d-modsig|modsig``;
|
||||||
|
|
||||||
|
|
||||||
Use
|
Use
|
||||||
|
|
|
@ -60,6 +60,7 @@ struct ima_event_data {
|
||||||
const unsigned char *filename;
|
const unsigned char *filename;
|
||||||
struct evm_ima_xattr_data *xattr_value;
|
struct evm_ima_xattr_data *xattr_value;
|
||||||
int xattr_len;
|
int xattr_len;
|
||||||
|
const struct modsig *modsig;
|
||||||
const char *violation;
|
const char *violation;
|
||||||
const void *buf;
|
const void *buf;
|
||||||
int buf_len;
|
int buf_len;
|
||||||
|
@ -211,7 +212,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
|
||||||
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,
|
struct evm_ima_xattr_data *xattr_value,
|
||||||
int xattr_len, int pcr,
|
int xattr_len, const struct modsig *modsig, int pcr,
|
||||||
struct ima_template_desc *template_desc);
|
struct ima_template_desc *template_desc);
|
||||||
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);
|
||||||
|
@ -312,6 +313,10 @@ bool ima_hook_supports_modsig(enum ima_hooks func);
|
||||||
int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len,
|
int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len,
|
||||||
struct modsig **modsig);
|
struct modsig **modsig);
|
||||||
void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size);
|
void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size);
|
||||||
|
int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo,
|
||||||
|
const u8 **digest, u32 *digest_size);
|
||||||
|
int ima_get_raw_modsig(const struct modsig *modsig, const void **data,
|
||||||
|
u32 *data_len);
|
||||||
void ima_free_modsig(struct modsig *modsig);
|
void ima_free_modsig(struct modsig *modsig);
|
||||||
#else
|
#else
|
||||||
static inline bool ima_hook_supports_modsig(enum ima_hooks func)
|
static inline bool ima_hook_supports_modsig(enum ima_hooks func)
|
||||||
|
@ -330,6 +335,19 @@ static inline void ima_collect_modsig(struct modsig *modsig, const void *buf,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int ima_get_modsig_digest(const struct modsig *modsig,
|
||||||
|
enum hash_algo *algo, const u8 **digest,
|
||||||
|
u32 *digest_size)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ima_get_raw_modsig(const struct modsig *modsig,
|
||||||
|
const void **data, u32 *data_len)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void ima_free_modsig(struct modsig *modsig)
|
static inline void ima_free_modsig(struct modsig *modsig)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,7 +288,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
|
||||||
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,
|
struct evm_ima_xattr_data *xattr_value,
|
||||||
int xattr_len, int pcr,
|
int xattr_len, const struct modsig *modsig, int pcr,
|
||||||
struct ima_template_desc *template_desc)
|
struct ima_template_desc *template_desc)
|
||||||
{
|
{
|
||||||
static const char op[] = "add_template_measure";
|
static const char op[] = "add_template_measure";
|
||||||
|
@ -300,7 +300,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
|
||||||
.file = file,
|
.file = file,
|
||||||
.filename = filename,
|
.filename = filename,
|
||||||
.xattr_value = xattr_value,
|
.xattr_value = xattr_value,
|
||||||
.xattr_len = xattr_len };
|
.xattr_len = xattr_len,
|
||||||
|
.modsig = modsig };
|
||||||
int violation = 0;
|
int violation = 0;
|
||||||
|
|
||||||
if (iint->measured_pcrs & (0x1 << pcr))
|
if (iint->measured_pcrs & (0x1 << pcr))
|
||||||
|
|
|
@ -323,7 +323,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
|
||||||
|
|
||||||
if (action & IMA_MEASURE)
|
if (action & IMA_MEASURE)
|
||||||
ima_store_measurement(iint, file, pathname,
|
ima_store_measurement(iint, file, pathname,
|
||||||
xattr_value, xattr_len, pcr,
|
xattr_value, xattr_len, modsig, pcr,
|
||||||
template_desc);
|
template_desc);
|
||||||
if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) {
|
if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) {
|
||||||
inode_lock(inode);
|
inode_lock(inode);
|
||||||
|
|
|
@ -138,6 +138,25 @@ int ima_modsig_verify(struct key *keyring, const struct modsig *modsig)
|
||||||
VERIFYING_MODULE_SIGNATURE, NULL, NULL);
|
VERIFYING_MODULE_SIGNATURE, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo,
|
||||||
|
const u8 **digest, u32 *digest_size)
|
||||||
|
{
|
||||||
|
*algo = modsig->hash_algo;
|
||||||
|
*digest = modsig->digest;
|
||||||
|
*digest_size = modsig->digest_size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ima_get_raw_modsig(const struct modsig *modsig, const void **data,
|
||||||
|
u32 *data_len)
|
||||||
|
{
|
||||||
|
*data = &modsig->raw_pkcs7;
|
||||||
|
*data_len = modsig->raw_pkcs7_len;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void ima_free_modsig(struct modsig *modsig)
|
void ima_free_modsig(struct modsig *modsig)
|
||||||
{
|
{
|
||||||
if (!modsig)
|
if (!modsig)
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
* ima_policy.c
|
* ima_policy.c
|
||||||
* - initialize default measure policy rules
|
* - initialize default measure policy rules
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
@ -845,6 +848,38 @@ static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
|
||||||
ima_log_string_op(ab, key, value, NULL);
|
ima_log_string_op(ab, key, value, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validating the appended signature included in the measurement list requires
|
||||||
|
* the file hash calculated without the appended signature (i.e., the 'd-modsig'
|
||||||
|
* field). Therefore, notify the user if they have the 'modsig' field but not
|
||||||
|
* the 'd-modsig' field in the template.
|
||||||
|
*/
|
||||||
|
static void check_template_modsig(const struct ima_template_desc *template)
|
||||||
|
{
|
||||||
|
#define MSG "template with 'modsig' field also needs 'd-modsig' field\n"
|
||||||
|
bool has_modsig, has_dmodsig;
|
||||||
|
static bool checked;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* We only need to notify the user once. */
|
||||||
|
if (checked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
has_modsig = has_dmodsig = false;
|
||||||
|
for (i = 0; i < template->num_fields; i++) {
|
||||||
|
if (!strcmp(template->fields[i]->field_id, "modsig"))
|
||||||
|
has_modsig = true;
|
||||||
|
else if (!strcmp(template->fields[i]->field_id, "d-modsig"))
|
||||||
|
has_dmodsig = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_modsig && !has_dmodsig)
|
||||||
|
pr_notice(MSG);
|
||||||
|
|
||||||
|
checked = true;
|
||||||
|
#undef MSG
|
||||||
|
}
|
||||||
|
|
||||||
static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||||
{
|
{
|
||||||
struct audit_buffer *ab;
|
struct audit_buffer *ab;
|
||||||
|
@ -1187,6 +1222,12 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||||
else if (entry->action == APPRAISE)
|
else if (entry->action == APPRAISE)
|
||||||
temp_ima_appraise |= ima_appraise_flag(entry->func);
|
temp_ima_appraise |= ima_appraise_flag(entry->func);
|
||||||
|
|
||||||
|
if (!result && entry->flags & IMA_MODSIG_ALLOWED) {
|
||||||
|
template_desc = entry->template ? entry->template :
|
||||||
|
ima_template_desc_current();
|
||||||
|
check_template_modsig(template_desc);
|
||||||
|
}
|
||||||
|
|
||||||
audit_log_format(ab, "res=%d", !result);
|
audit_log_format(ab, "res=%d", !result);
|
||||||
audit_log_end(ab);
|
audit_log_end(ab);
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -23,6 +23,7 @@ static struct ima_template_desc builtin_templates[] = {
|
||||||
{.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"},
|
{.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
|
||||||
{.name = "ima-buf", .fmt = "d-ng|n-ng|buf"},
|
{.name = "ima-buf", .fmt = "d-ng|n-ng|buf"},
|
||||||
|
{.name = "ima-modsig", .fmt = "d-ng|n-ng|sig|d-modsig|modsig"},
|
||||||
{.name = "", .fmt = ""}, /* placeholder for a custom format */
|
{.name = "", .fmt = ""}, /* placeholder for a custom format */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,6 +43,10 @@ static const struct ima_template_field supported_fields[] = {
|
||||||
.field_show = ima_show_template_sig},
|
.field_show = ima_show_template_sig},
|
||||||
{.field_id = "buf", .field_init = ima_eventbuf_init,
|
{.field_id = "buf", .field_init = ima_eventbuf_init,
|
||||||
.field_show = ima_show_template_buf},
|
.field_show = ima_show_template_buf},
|
||||||
|
{.field_id = "d-modsig", .field_init = ima_eventdigest_modsig_init,
|
||||||
|
.field_show = ima_show_template_digest_ng},
|
||||||
|
{.field_id = "modsig", .field_init = ima_eventmodsig_init,
|
||||||
|
.field_show = ima_show_template_sig},
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -49,7 +54,7 @@ static const struct ima_template_field supported_fields[] = {
|
||||||
* need to be accounted for since they shouldn't be defined in the same template
|
* need to be accounted for since they shouldn't be defined in the same template
|
||||||
* description as 'd-ng' and 'n-ng' respectively.
|
* description as 'd-ng' and 'n-ng' respectively.
|
||||||
*/
|
*/
|
||||||
#define MAX_TEMPLATE_NAME_LEN sizeof("d-ng|n-ng|sig|buf")
|
#define MAX_TEMPLATE_NAME_LEN sizeof("d-ng|n-ng|sig|buf|d-modisg|modsig")
|
||||||
|
|
||||||
static struct ima_template_desc *ima_template;
|
static struct ima_template_desc *ima_template;
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,8 @@ int ima_parse_buf(void *bufstartp, void *bufendp, void **bufcurp,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo,
|
static int ima_eventdigest_init_common(const u8 *digest, u32 digestsize,
|
||||||
|
u8 hash_algo,
|
||||||
struct ima_field_data *field_data)
|
struct ima_field_data *field_data)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -328,6 +329,41 @@ int ima_eventdigest_ng_init(struct ima_event_data *event_data,
|
||||||
hash_algo, field_data);
|
hash_algo, field_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function writes the digest of the file which is expected to match the
|
||||||
|
* digest contained in the file's appended signature.
|
||||||
|
*/
|
||||||
|
int ima_eventdigest_modsig_init(struct ima_event_data *event_data,
|
||||||
|
struct ima_field_data *field_data)
|
||||||
|
{
|
||||||
|
enum hash_algo hash_algo;
|
||||||
|
const u8 *cur_digest;
|
||||||
|
u32 cur_digestsize;
|
||||||
|
|
||||||
|
if (!event_data->modsig)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (event_data->violation) {
|
||||||
|
/* Recording a violation. */
|
||||||
|
hash_algo = HASH_ALGO_SHA1;
|
||||||
|
cur_digest = NULL;
|
||||||
|
cur_digestsize = 0;
|
||||||
|
} else {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = ima_get_modsig_digest(event_data->modsig, &hash_algo,
|
||||||
|
&cur_digest, &cur_digestsize);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
else if (hash_algo == HASH_ALGO__LAST || cur_digestsize == 0)
|
||||||
|
/* There was some error collecting the digest. */
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ima_eventdigest_init_common(cur_digest, cur_digestsize,
|
||||||
|
hash_algo, field_data);
|
||||||
|
}
|
||||||
|
|
||||||
static int ima_eventname_init_common(struct ima_event_data *event_data,
|
static int ima_eventname_init_common(struct ima_event_data *event_data,
|
||||||
struct ima_field_data *field_data,
|
struct ima_field_data *field_data,
|
||||||
bool size_limit)
|
bool size_limit)
|
||||||
|
@ -406,3 +442,29 @@ int ima_eventbuf_init(struct ima_event_data *event_data,
|
||||||
event_data->buf_len, DATA_FMT_HEX,
|
event_data->buf_len, DATA_FMT_HEX,
|
||||||
field_data);
|
field_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ima_eventmodsig_init - include the appended file signature as part of the
|
||||||
|
* template data
|
||||||
|
*/
|
||||||
|
int ima_eventmodsig_init(struct ima_event_data *event_data,
|
||||||
|
struct ima_field_data *field_data)
|
||||||
|
{
|
||||||
|
const void *data;
|
||||||
|
u32 data_len;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!event_data->modsig)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* modsig is a runtime structure containing pointers. Get its raw data
|
||||||
|
* instead.
|
||||||
|
*/
|
||||||
|
rc = ima_get_raw_modsig(event_data->modsig, &data, &data_len);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
return ima_write_template_field_data(data, data_len, DATA_FMT_HEX,
|
||||||
|
field_data);
|
||||||
|
}
|
||||||
|
|
|
@ -36,10 +36,14 @@ int ima_eventname_init(struct ima_event_data *event_data,
|
||||||
struct ima_field_data *field_data);
|
struct ima_field_data *field_data);
|
||||||
int ima_eventdigest_ng_init(struct ima_event_data *event_data,
|
int ima_eventdigest_ng_init(struct ima_event_data *event_data,
|
||||||
struct ima_field_data *field_data);
|
struct ima_field_data *field_data);
|
||||||
|
int ima_eventdigest_modsig_init(struct ima_event_data *event_data,
|
||||||
|
struct ima_field_data *field_data);
|
||||||
int ima_eventname_ng_init(struct ima_event_data *event_data,
|
int ima_eventname_ng_init(struct ima_event_data *event_data,
|
||||||
struct ima_field_data *field_data);
|
struct ima_field_data *field_data);
|
||||||
int ima_eventsig_init(struct ima_event_data *event_data,
|
int ima_eventsig_init(struct ima_event_data *event_data,
|
||||||
struct ima_field_data *field_data);
|
struct ima_field_data *field_data);
|
||||||
int ima_eventbuf_init(struct ima_event_data *event_data,
|
int ima_eventbuf_init(struct ima_event_data *event_data,
|
||||||
struct ima_field_data *field_data);
|
struct ima_field_data *field_data);
|
||||||
|
int ima_eventmodsig_init(struct ima_event_data *event_data,
|
||||||
|
struct ima_field_data *field_data);
|
||||||
#endif /* __LINUX_IMA_TEMPLATE_LIB_H */
|
#endif /* __LINUX_IMA_TEMPLATE_LIB_H */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user