static struct crypto_shash *shash;
- static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg,
- unsigned long msglen,
- unsigned long modulus_bitlen,
- unsigned char *out,
- unsigned long *outlen)
+ static const char *pkcs_1_v1_5_decode_emsa(const unsigned char *msg,
+ unsigned long msglen,
+ unsigned long modulus_bitlen,
+ unsigned long *outlen)
{
unsigned long modulus_len, ps_len, i;
/* test message size */
if ((msglen > modulus_len) || (modulus_len < 11))
- return -EINVAL;
+ return NULL;
/* separate encoded message */
- if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1))
- return -EINVAL;
+ if (msg[0] != 0x00 || msg[1] != 0x01)
+ return NULL;
for (i = 2; i < modulus_len - 1; i++)
if (msg[i] != 0xFF)
if (msg[i] != 0)
/* There was no octet with hexadecimal value 0x00
to separate ps from m. */
- return -EINVAL;
+ return NULL;
ps_len = i - 2;
- if (*outlen < (msglen - (2 + ps_len + 1))) {
- *outlen = msglen - (2 + ps_len + 1);
- return -EOVERFLOW;
- }
-
*outlen = (msglen - (2 + ps_len + 1));
- memcpy(out, &msg[2 + ps_len + 1], *outlen);
- return 0;
+ return msg + 2 + ps_len + 1;
}
/*
unsigned long mlen, mblen;
unsigned nret, l;
int head, i;
- unsigned char *out1 = NULL, *out2 = NULL;
+ unsigned char *out1 = NULL;
+ const char *m;
MPI in = NULL, res = NULL, pkey[2];
uint8_t *p, *datap, *endp;
struct user_key_payload *ukp;
}
mblen = mpi_get_nbits(pkey[0]);
- mlen = (mblen + 7)/8;
+ mlen = DIV_ROUND_UP(mblen, 8);
if (mlen == 0)
goto err;
if (!out1)
goto err;
- out2 = kzalloc(mlen, GFP_KERNEL);
- if (!out2)
- goto err;
-
nret = siglen;
in = mpi_read_from_buffer(sig, &nret);
if (!in)
memset(out1, 0, head);
memcpy(out1 + head, p, l);
- err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len);
- if (err)
- goto err;
+ kfree(p);
+
+ m = pkcs_1_v1_5_decode_emsa(out1, len, mblen, &len);
- if (len != hlen || memcmp(out2, h, hlen))
+ if (!m || len != hlen || memcmp(m, h, hlen))
err = -EINVAL;
err:
mpi_free(in);
mpi_free(res);
kfree(out1);
- kfree(out2);
while (--i >= 0)
mpi_free(pkey[i]);
err1:
hmac_misc.gid = from_kgid(&init_user_ns, inode->i_gid);
hmac_misc.mode = inode->i_mode;
crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof hmac_misc);
+ if (evm_hmac_version > 1)
+ crypto_shash_update(desc, inode->i_sb->s_uuid,
+ sizeof(inode->i_sb->s_uuid));
crypto_shash_final(desc, digest);
}
rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
&xattr_data,
sizeof(xattr_data), 0);
- }
- else if (rc == -ENODATA)
+ } else if (rc == -ENODATA && inode->i_op->removexattr) {
rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM);
+ }
return rc;
}
int ima_inode_alloc(struct inode *inode);
int ima_add_template_entry(struct ima_template_entry *entry, int violation,
const char *op, struct inode *inode);
- int ima_calc_hash(struct file *file, char *digest);
- int ima_calc_template_hash(int template_len, void *template, char *digest);
+ int ima_calc_file_hash(struct file *file, char *digest);
+ int ima_calc_buffer_hash(const void *data, int len, char *digest);
int ima_calc_boot_aggregate(char *digest);
void ima_add_violation(struct inode *inode, const unsigned char *filename,
const char *op, const char *cause);
+ int ima_init_crypto(void);
/*
* used to protect h_table and sha_table
int ima_store_template(struct ima_template_entry *entry, int violation,
struct inode *inode);
void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show);
+ const char *ima_d_path(struct path *path, char **pathbuf);
/* rbtree tree calls to lookup, insert, delete
* integrity data associated with an inode.
struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
/* IMA policy related functions */
- enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK, MODULE_CHECK, POST_SETATTR };
+ enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, POST_SETATTR };
int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
int flags);
/* Appraise integrity measurements */
#define IMA_APPRAISE_ENFORCE 0x01
#define IMA_APPRAISE_FIX 0x02
+#define IMA_APPRAISE_MODULES 0x04
#ifdef CONFIG_IMA_APPRAISE
- int ima_appraise_measurement(struct integrity_iint_cache *iint,
+ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
struct file *file, const unsigned char *filename);
int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func);
void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
+ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
+ int func);
#else
- static inline int ima_appraise_measurement(struct integrity_iint_cache *iint,
+ static inline int ima_appraise_measurement(int func,
+ struct integrity_iint_cache *iint,
struct file *file,
const unsigned char *filename)
{
struct file *file)
{
}
+
+ static inline enum integrity_status ima_get_cache_status(struct integrity_iint_cache
+ *iint, int func)
+ {
+ return INTEGRITY_UNKNOWN;
+ }
#endif
/* LSM based policy rules require audit */
fmode_t mode = file->f_mode;
int must_measure;
bool send_tomtou = false, send_writers = false;
- unsigned char *pathname = NULL, *pathbuf = NULL;
+ char *pathbuf = NULL;
+ const char *pathname;
if (!S_ISREG(inode->i_mode) || !ima_initialized)
return;
if (!send_tomtou && !send_writers)
return;
- /* We will allow 11 spaces for ' (deleted)' to be appended */
- pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL);
- if (pathbuf) {
- pathname = d_path(&file->f_path, pathbuf, PATH_MAX + 11);
- if (IS_ERR(pathname))
- pathname = NULL;
- else if (strlen(pathname) > IMA_EVENT_NAME_LEN_MAX)
- pathname = NULL;
- }
+ pathname = ima_d_path(&file->f_path, &pathbuf);
+ if (!pathname || strlen(pathname) > IMA_EVENT_NAME_LEN_MAX)
+ pathname = dentry->d_name.name;
+
if (send_tomtou)
- ima_add_violation(inode,
- !pathname ? dentry->d_name.name : pathname,
+ ima_add_violation(inode, pathname,
"invalid_pcr", "ToMToU");
if (send_writers)
- ima_add_violation(inode,
- !pathname ? dentry->d_name.name : pathname,
+ ima_add_violation(inode, pathname,
"invalid_pcr", "open_writers");
kfree(pathbuf);
}
ima_check_last_writer(iint, inode, file);
}
- static int process_measurement(struct file *file, const unsigned char *filename,
+ static int process_measurement(struct file *file, const char *filename,
int mask, int function)
{
struct inode *inode = file->f_dentry->d_inode;
struct integrity_iint_cache *iint;
- unsigned char *pathname = NULL, *pathbuf = NULL;
- int rc = -ENOMEM, action, must_appraise;
+ char *pathbuf = NULL;
+ const char *pathname = NULL;
+ int rc = -ENOMEM, action, must_appraise, _func;
if (!ima_initialized || !S_ISREG(inode->i_mode))
return 0;
- /* Determine if in appraise/audit/measurement policy,
- * returns IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT bitmask. */
+ /* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action
+ * bitmask based on the appraise/audit/measurement policy.
+ * Included is the appraise submask.
+ */
action = ima_get_action(inode, mask, function);
if (!action)
return 0;
must_appraise = action & IMA_APPRAISE;
+ /* Is the appraise rule hook specific? */
+ _func = (action & IMA_FILE_APPRAISE) ? FILE_CHECK : function;
+
mutex_lock(&inode->i_mutex);
iint = integrity_inode_get(inode);
goto out;
/* Determine if already appraised/measured based on bitmask
- * (IMA_MEASURE, IMA_MEASURED, IMA_APPRAISE, IMA_APPRAISED,
- * IMA_AUDIT, IMA_AUDITED) */
+ * (IMA_MEASURE, IMA_MEASURED, IMA_XXXX_APPRAISE, IMA_XXXX_APPRAISED,
+ * IMA_AUDIT, IMA_AUDITED)
+ */
iint->flags |= action;
+ action &= IMA_DO_MASK;
action &= ~((iint->flags & IMA_DONE_MASK) >> 1);
/* Nothing to do, just return existing appraised status */
if (!action) {
- if (iint->flags & IMA_APPRAISED)
- rc = iint->ima_status;
- goto out;
+ if (must_appraise)
+ rc = ima_get_cache_status(iint, _func);
+ goto out_digsig;
}
rc = ima_collect_measurement(iint, file);
if (rc != 0)
- goto out;
+ goto out_digsig;
+
+ if (function != BPRM_CHECK)
+ pathname = ima_d_path(&file->f_path, &pathbuf);
+
+ if (!pathname)
+ pathname = filename;
- if (function != BPRM_CHECK) {
- /* We will allow 11 spaces for ' (deleted)' to be appended */
- pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL);
- if (pathbuf) {
- pathname =
- d_path(&file->f_path, pathbuf, PATH_MAX + 11);
- if (IS_ERR(pathname))
- pathname = NULL;
- }
- }
if (action & IMA_MEASURE)
- ima_store_measurement(iint, file,
- !pathname ? filename : pathname);
- if (action & IMA_APPRAISE)
- rc = ima_appraise_measurement(iint, file,
- !pathname ? filename : pathname);
+ ima_store_measurement(iint, file, pathname);
+ if (action & IMA_APPRAISE_SUBMASK)
+ rc = ima_appraise_measurement(_func, iint, file, pathname);
if (action & IMA_AUDIT)
- ima_audit_measurement(iint, !pathname ? filename : pathname);
+ ima_audit_measurement(iint, pathname);
kfree(pathbuf);
+ out_digsig:
+ if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG))
+ rc = -EACCES;
out:
mutex_unlock(&inode->i_mutex);
- return (rc && must_appraise) ? -EACCES : 0;
+ if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE))
+ return -EACCES;
+ return 0;
}
/**
* Measure files being mmapped executable based on the ima_must_measure()
* policy decision.
*
- * Return 0 on success, an error code on failure.
- * (Based on the results of appraise_measurement().)
+ * On success return 0. On integrity appraisal error, assuming the file
+ * is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
*/
int ima_file_mmap(struct file *file, unsigned long prot)
{
- int rc = 0;
-
- if (!file)
- return 0;
- if (prot & PROT_EXEC)
- rc = process_measurement(file, file->f_dentry->d_name.name,
- MAY_EXEC, FILE_MMAP);
- return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0;
+ if (file && (prot & PROT_EXEC))
+ return process_measurement(file, file->f_dentry->d_name.name,
+ MAY_EXEC, MMAP_CHECK);
+ return 0;
}
/**
* So we can be certain that what we verify and measure here is actually
* what is being executed.
*
- * Return 0 on success, an error code on failure.
- * (Based on the results of appraise_measurement().)
+ * On success return 0. On integrity appraisal error, assuming the file
+ * is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
*/
int ima_bprm_check(struct linux_binprm *bprm)
{
- int rc;
-
- rc = process_measurement(bprm->file,
+ return process_measurement(bprm->file,
(strcmp(bprm->filename, bprm->interp) == 0) ?
bprm->filename : bprm->interp,
MAY_EXEC, BPRM_CHECK);
- return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0;
}
/**
*
* Measure files based on the ima_must_measure() policy decision.
*
- * Always return 0 and audit dentry_open failures.
- * (Return code will be based upon measurement appraisal.)
+ * On success return 0. On integrity appraisal error, assuming the file
+ * is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
*/
int ima_file_check(struct file *file, int mask)
{
- int rc;
-
ima_rdwr_violation_check(file);
- rc = process_measurement(file, file->f_dentry->d_name.name,
+ return process_measurement(file, file->f_dentry->d_name.name,
mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
FILE_CHECK);
- return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0;
}
EXPORT_SYMBOL_GPL(ima_file_check);
*
* Measure/appraise kernel modules based on policy.
*
- * Always return 0 and audit dentry_open failures.
- * Return code is based upon measurement appraisal.
+ * On success return 0. On integrity appraisal error, assuming the file
+ * is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
*/
int ima_module_check(struct file *file)
{
- int rc = 0;
-
- if (!file)
- return -EACCES; /* INTEGRITY_UNKNOWN */
+ if (!file) {
- if (ima_appraise & IMA_APPRAISE_MODULES) {
+#ifndef CONFIG_MODULE_SIG_FORCE
- rc = -EACCES; /* INTEGRITY_UNKNOWN */
++ if (ima_appraise & IMA_APPRAISE_MODULES)
++ return -EACCES; /* INTEGRITY_UNKNOWN */
+#endif
- }
- } else
- rc = process_measurement(file, file->f_dentry->d_name.name,
- MAY_EXEC, MODULE_CHECK);
- return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0;
++ return 0; /* We rely on module signature checking */
++ }
+ return process_measurement(file, file->f_dentry->d_name.name,
+ MAY_EXEC, MODULE_CHECK);
}
static int __init init_ima(void)
#include <linux/magic.h>
#include <linux/parser.h>
#include <linux/slab.h>
+ #include <linux/genhd.h>
#include "ima.h"
#define IMA_FSMAGIC 0x0004
#define IMA_UID 0x0008
#define IMA_FOWNER 0x0010
+ #define IMA_FSUUID 0x0020
#define UNKNOWN 0
#define MEASURE 0x0001 /* same as IMA_MEASURE */
enum ima_hooks func;
int mask;
unsigned long fsmagic;
+ u8 fsuuid[16];
kuid_t uid;
kuid_t fowner;
struct {
void *rule; /* LSM file metadata specific */
+ void *args_p; /* audit value */
int type; /* audit type */
} lsm[MAX_LSM_RULES];
};
{.action = DONT_MEASURE,.fsmagic = BINFMTFS_MAGIC,.flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC},
- {.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC,
+ {.action = MEASURE,.func = MMAP_CHECK,.mask = MAY_EXEC,
.flags = IMA_FUNC | IMA_MASK},
{.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
.flags = IMA_FUNC | IMA_MASK},
}
__setup("ima_appraise_tcb", default_appraise_policy_setup);
+ /*
+ * Although the IMA policy does not change, the LSM policy can be
+ * reloaded, leaving the IMA LSM based rules referring to the old,
+ * stale LSM policy.
+ *
+ * Update the IMA LSM based rules to reflect the reloaded LSM policy.
+ * We assume the rules still exist; and BUG_ON() if they don't.
+ */
+ static void ima_lsm_update_rules(void)
+ {
+ struct ima_rule_entry *entry, *tmp;
+ int result;
+ int i;
+
+ mutex_lock(&ima_rules_mutex);
+ list_for_each_entry_safe(entry, tmp, &ima_policy_rules, list) {
+ for (i = 0; i < MAX_LSM_RULES; i++) {
+ if (!entry->lsm[i].rule)
+ continue;
+ result = security_filter_rule_init(entry->lsm[i].type,
+ Audit_equal,
+ entry->lsm[i].args_p,
+ &entry->lsm[i].rule);
+ BUG_ON(!entry->lsm[i].rule);
+ }
+ }
+ mutex_unlock(&ima_rules_mutex);
+ }
+
/**
* ima_match_rules - determine whether an inode matches the measure rule.
* @rule: a pointer to a rule
if ((rule->flags & IMA_FSMAGIC)
&& rule->fsmagic != inode->i_sb->s_magic)
return false;
+ if ((rule->flags & IMA_FSUUID) &&
+ memcmp(rule->fsuuid, inode->i_sb->s_uuid, sizeof(rule->fsuuid)))
+ return false;
if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid))
return false;
if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid))
for (i = 0; i < MAX_LSM_RULES; i++) {
int rc = 0;
u32 osid, sid;
+ int retried = 0;
if (!rule->lsm[i].rule)
continue;
-
+ retry:
switch (i) {
case LSM_OBJ_USER:
case LSM_OBJ_ROLE:
default:
break;
}
+ if ((rc < 0) && (!retried)) {
+ retried = 1;
+ ima_lsm_update_rules();
+ goto retry;
+ }
if (!rc)
return false;
}
return true;
}
+ /*
+ * In addition to knowing that we need to appraise the file in general,
+ * we need to differentiate between calling hooks, for hook specific rules.
+ */
+ static int get_subaction(struct ima_rule_entry *rule, int func)
+ {
+ if (!(rule->flags & IMA_FUNC))
+ return IMA_FILE_APPRAISE;
+
+ switch(func) {
+ case MMAP_CHECK:
+ return IMA_MMAP_APPRAISE;
+ case BPRM_CHECK:
+ return IMA_BPRM_APPRAISE;
+ case MODULE_CHECK:
+ return IMA_MODULE_APPRAISE;
+ case FILE_CHECK:
+ default:
+ return IMA_FILE_APPRAISE;
+ }
+ }
+
/**
* ima_match_policy - decision based on LSM and other conditions
* @inode: pointer to an inode for which the policy decision is being made
if (!ima_match_rules(entry, inode, func, mask))
continue;
+ action |= entry->flags & IMA_ACTION_FLAGS;
+
action |= entry->action & IMA_DO_MASK;
+ if (entry->action & IMA_APPRAISE)
+ action |= get_subaction(entry, func);
+
if (entry->action & IMA_DO_MASK)
actmask &= ~(entry->action | entry->action << 1);
else
Opt_audit,
Opt_obj_user, Opt_obj_role, Opt_obj_type,
Opt_subj_user, Opt_subj_role, Opt_subj_type,
- Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner
+ Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner,
+ Opt_appraise_type, Opt_fsuuid
};
static match_table_t policy_tokens = {
{Opt_func, "func=%s"},
{Opt_mask, "mask=%s"},
{Opt_fsmagic, "fsmagic=%s"},
+ {Opt_fsuuid, "fsuuid=%s"},
{Opt_uid, "uid=%s"},
{Opt_fowner, "fowner=%s"},
+ {Opt_appraise_type, "appraise_type=%s"},
{Opt_err, NULL}
};
static int ima_lsm_rule_init(struct ima_rule_entry *entry,
- char *args, int lsm_rule, int audit_type)
+ substring_t *args, int lsm_rule, int audit_type)
{
int result;
if (entry->lsm[lsm_rule].rule)
return -EINVAL;
+ entry->lsm[lsm_rule].args_p = match_strdup(args);
+ if (!entry->lsm[lsm_rule].args_p)
+ return -ENOMEM;
+
entry->lsm[lsm_rule].type = audit_type;
result = security_filter_rule_init(entry->lsm[lsm_rule].type,
- Audit_equal, args,
+ Audit_equal,
+ entry->lsm[lsm_rule].args_p,
&entry->lsm[lsm_rule].rule);
- if (!entry->lsm[lsm_rule].rule)
+ if (!entry->lsm[lsm_rule].rule) {
+ kfree(entry->lsm[lsm_rule].args_p);
return -EINVAL;
+ }
+
return result;
}
entry->func = FILE_CHECK;
else if (strcmp(args[0].from, "MODULE_CHECK") == 0)
entry->func = MODULE_CHECK;
- else if (strcmp(args[0].from, "FILE_MMAP") == 0)
- entry->func = FILE_MMAP;
+ else if ((strcmp(args[0].from, "FILE_MMAP") == 0)
+ || (strcmp(args[0].from, "MMAP_CHECK") == 0))
+ entry->func = MMAP_CHECK;
else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
entry->func = BPRM_CHECK;
else
if (!result)
entry->flags |= IMA_FSMAGIC;
break;
+ case Opt_fsuuid:
+ ima_log_string(ab, "fsuuid", args[0].from);
+
+ if (memchr_inv(entry->fsuuid, 0x00,
+ sizeof(entry->fsuuid))) {
+ result = -EINVAL;
+ break;
+ }
+
+ part_pack_uuid(args[0].from, entry->fsuuid);
+ entry->flags |= IMA_FSUUID;
+ result = 0;
+ break;
case Opt_uid:
ima_log_string(ab, "uid", args[0].from);
break;
case Opt_obj_user:
ima_log_string(ab, "obj_user", args[0].from);
- result = ima_lsm_rule_init(entry, args[0].from,
+ result = ima_lsm_rule_init(entry, args,
LSM_OBJ_USER,
AUDIT_OBJ_USER);
break;
case Opt_obj_role:
ima_log_string(ab, "obj_role", args[0].from);
- result = ima_lsm_rule_init(entry, args[0].from,
+ result = ima_lsm_rule_init(entry, args,
LSM_OBJ_ROLE,
AUDIT_OBJ_ROLE);
break;
case Opt_obj_type:
ima_log_string(ab, "obj_type", args[0].from);
- result = ima_lsm_rule_init(entry, args[0].from,
+ result = ima_lsm_rule_init(entry, args,
LSM_OBJ_TYPE,
AUDIT_OBJ_TYPE);
break;
case Opt_subj_user:
ima_log_string(ab, "subj_user", args[0].from);
- result = ima_lsm_rule_init(entry, args[0].from,
+ result = ima_lsm_rule_init(entry, args,
LSM_SUBJ_USER,
AUDIT_SUBJ_USER);
break;
case Opt_subj_role:
ima_log_string(ab, "subj_role", args[0].from);
- result = ima_lsm_rule_init(entry, args[0].from,
+ result = ima_lsm_rule_init(entry, args,
LSM_SUBJ_ROLE,
AUDIT_SUBJ_ROLE);
break;
case Opt_subj_type:
ima_log_string(ab, "subj_type", args[0].from);
- result = ima_lsm_rule_init(entry, args[0].from,
+ result = ima_lsm_rule_init(entry, args,
LSM_SUBJ_TYPE,
AUDIT_SUBJ_TYPE);
break;
+ case Opt_appraise_type:
+ if (entry->action != APPRAISE) {
+ result = -EINVAL;
+ break;
+ }
+
+ ima_log_string(ab, "appraise_type", args[0].from);
+ if ((strcmp(args[0].from, "imasig")) == 0)
+ entry->flags |= IMA_DIGSIG_REQUIRED;
+ else
+ result = -EINVAL;
+ break;
case Opt_err:
ima_log_string(ab, "UNKNOWN", p);
result = -EINVAL;
}
if (!result && (entry->action == UNKNOWN))
result = -EINVAL;
-
+ else if (entry->func == MODULE_CHECK)
+ ima_appraise |= IMA_APPRAISE_MODULES;
audit_log_format(ab, "res=%d", !result);
audit_log_end(ab);
return result;
void ima_delete_rules(void)
{
struct ima_rule_entry *entry, *tmp;
+ int i;
mutex_lock(&ima_rules_mutex);
list_for_each_entry_safe(entry, tmp, &ima_policy_rules, list) {
+ for (i = 0; i < MAX_LSM_RULES; i++)
+ kfree(entry->lsm[i].args_p);
+
list_del(&entry->list);
kfree(entry);
}