Skip to content

Commit

Permalink
ima: Move IMA-Appraisal to LSM infrastructure
Browse files Browse the repository at this point in the history
A few additional IMA hooks are needed to reset the cached appraisal
status, causing the file's integrity to be re-evaluated on next access.
Register these IMA-appraisal only functions separately from the rest of IMA
functions, as appraisal is a separate feature not necessarily enabled in
the kernel configuration.

Reuse the same approach as for other IMA functions, move hardcoded calls
from various places in the kernel to the LSM infrastructure. Declare the
functions as static and register them as hook implementations in
init_ima_appraise_lsm(), called by init_ima_lsm().

Also move the inline function ima_inode_remove_acl() from the public ima.h
header to ima_appraise.c.

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
Reviewed-by: Casey Schaufler <casey@schaufler-ca.com>
Acked-by: Christian Brauner <brauner@kernel.org>
Acked-by: Mimi Zohar <zohar@linux.ibm.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
  • Loading branch information
robertosassu authored and pcmoore committed Feb 16, 2024
1 parent cd3cec0 commit 84594c9
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 79 deletions.
2 changes: 0 additions & 2 deletions fs/attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include <linux/filelock.h>
#include <linux/security.h>
#include <linux/evm.h>
#include <linux/ima.h>

#include "internal.h"

Expand Down Expand Up @@ -503,7 +502,6 @@ int notify_change(struct mnt_idmap *idmap, struct dentry *dentry,
if (!error) {
fsnotify_change(dentry, ia_valid);
security_inode_post_setattr(idmap, dentry, ia_valid);
ima_inode_post_setattr(idmap, dentry, ia_valid);
evm_inode_post_setattr(idmap, dentry, ia_valid);
}

Expand Down
55 changes: 0 additions & 55 deletions include/linux/ima.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,66 +92,11 @@ static inline void ima_add_kexec_buffer(struct kimage *image)

#ifdef CONFIG_IMA_APPRAISE
extern bool is_ima_appraise_enabled(void);
extern void ima_inode_post_setattr(struct mnt_idmap *idmap,
struct dentry *dentry, int ia_valid);
extern int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
const char *xattr_name, const void *xattr_value,
size_t xattr_value_len, int flags);
extern int ima_inode_set_acl(struct mnt_idmap *idmap,
struct dentry *dentry, const char *acl_name,
struct posix_acl *kacl);
static inline int ima_inode_remove_acl(struct mnt_idmap *idmap,
struct dentry *dentry,
const char *acl_name)
{
return ima_inode_set_acl(idmap, dentry, acl_name, NULL);
}

extern int ima_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry,
const char *xattr_name);
#else
static inline bool is_ima_appraise_enabled(void)
{
return 0;
}

static inline void ima_inode_post_setattr(struct mnt_idmap *idmap,
struct dentry *dentry, int ia_valid)
{
return;
}

static inline int ima_inode_setxattr(struct mnt_idmap *idmap,
struct dentry *dentry,
const char *xattr_name,
const void *xattr_value,
size_t xattr_value_len,
int flags)
{
return 0;
}

static inline int ima_inode_set_acl(struct mnt_idmap *idmap,
struct dentry *dentry, const char *acl_name,
struct posix_acl *kacl)
{

return 0;
}

static inline int ima_inode_removexattr(struct mnt_idmap *idmap,
struct dentry *dentry,
const char *xattr_name)
{
return 0;
}

static inline int ima_inode_remove_acl(struct mnt_idmap *idmap,
struct dentry *dentry,
const char *acl_name)
{
return 0;
}
#endif /* CONFIG_IMA_APPRAISE */

#if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING)
Expand Down
5 changes: 5 additions & 0 deletions security/integrity/ima/ima.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value,
int xattr_len);
int ima_read_xattr(struct dentry *dentry,
struct evm_ima_xattr_data **xattr_value, int xattr_len);
void __init init_ima_appraise_lsm(const struct lsm_id *lsmid);

#else
static inline int ima_check_blacklist(struct integrity_iint_cache *iint,
Expand Down Expand Up @@ -385,6 +386,10 @@ static inline int ima_read_xattr(struct dentry *dentry,
return 0;
}

static inline void __init init_ima_appraise_lsm(const struct lsm_id *lsmid)
{
}

#endif /* CONFIG_IMA_APPRAISE */

#ifdef CONFIG_IMA_APPRAISE_MODSIG
Expand Down
38 changes: 29 additions & 9 deletions security/integrity/ima/ima_appraise.c
Original file line number Diff line number Diff line change
Expand Up @@ -636,8 +636,8 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
* This function is called from notify_change(), which expects the caller
* to lock the inode's i_mutex.
*/
void ima_inode_post_setattr(struct mnt_idmap *idmap,
struct dentry *dentry, int ia_valid)
static void ima_inode_post_setattr(struct mnt_idmap *idmap,
struct dentry *dentry, int ia_valid)
{
struct inode *inode = d_backing_inode(dentry);
struct integrity_iint_cache *iint;
Expand Down Expand Up @@ -750,9 +750,9 @@ static int validate_hash_algo(struct dentry *dentry,
return -EACCES;
}

int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
const char *xattr_name, const void *xattr_value,
size_t xattr_value_len, int flags)
static int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
const char *xattr_name, const void *xattr_value,
size_t xattr_value_len, int flags)
{
const struct evm_ima_xattr_data *xvalue = xattr_value;
int digsig = 0;
Expand Down Expand Up @@ -781,17 +781,17 @@ int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
return result;
}

int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
const char *acl_name, struct posix_acl *kacl)
static int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
const char *acl_name, struct posix_acl *kacl)
{
if (evm_revalidate_status(acl_name))
ima_reset_appraise_flags(d_backing_inode(dentry), 0);

return 0;
}

int ima_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry,
const char *xattr_name)
static int ima_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry,
const char *xattr_name)
{
int result;

Expand All @@ -803,3 +803,23 @@ int ima_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry,
}
return result;
}

static int ima_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry,
const char *acl_name)
{
return ima_inode_set_acl(idmap, dentry, acl_name, NULL);
}

static struct security_hook_list ima_appraise_hooks[] __ro_after_init = {
LSM_HOOK_INIT(inode_post_setattr, ima_inode_post_setattr),
LSM_HOOK_INIT(inode_setxattr, ima_inode_setxattr),
LSM_HOOK_INIT(inode_set_acl, ima_inode_set_acl),
LSM_HOOK_INIT(inode_removexattr, ima_inode_removexattr),
LSM_HOOK_INIT(inode_remove_acl, ima_inode_remove_acl),
};

void __init init_ima_appraise_lsm(const struct lsm_id *lsmid)
{
security_add_hooks(ima_appraise_hooks, ARRAY_SIZE(ima_appraise_hooks),
lsmid);
}
1 change: 1 addition & 0 deletions security/integrity/ima/ima_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,7 @@ static const struct lsm_id ima_lsmid = {
static int __init init_ima_lsm(void)
{
security_add_hooks(ima_hooks, ARRAY_SIZE(ima_hooks), &ima_lsmid);
init_ima_appraise_lsm(&ima_lsmid);
return 0;
}

Expand Down
13 changes: 0 additions & 13 deletions security/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include <linux/kernel_read_file.h>
#include <linux/lsm_hooks.h>
#include <linux/integrity.h>
#include <linux/ima.h>
#include <linux/evm.h>
#include <linux/fsnotify.h>
#include <linux/mman.h>
Expand Down Expand Up @@ -2308,9 +2307,6 @@ int security_inode_setxattr(struct mnt_idmap *idmap,

if (ret == 1)
ret = cap_inode_setxattr(dentry, name, value, size, flags);
if (ret)
return ret;
ret = ima_inode_setxattr(idmap, dentry, name, value, size, flags);
if (ret)
return ret;
return evm_inode_setxattr(idmap, dentry, name, value, size, flags);
Expand Down Expand Up @@ -2338,9 +2334,6 @@ int security_inode_set_acl(struct mnt_idmap *idmap,
return 0;
ret = call_int_hook(inode_set_acl, 0, idmap, dentry, acl_name,
kacl);
if (ret)
return ret;
ret = ima_inode_set_acl(idmap, dentry, acl_name, kacl);
if (ret)
return ret;
return evm_inode_set_acl(idmap, dentry, acl_name, kacl);
Expand Down Expand Up @@ -2401,9 +2394,6 @@ int security_inode_remove_acl(struct mnt_idmap *idmap,
if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
ret = call_int_hook(inode_remove_acl, 0, idmap, dentry, acl_name);
if (ret)
return ret;
ret = ima_inode_remove_acl(idmap, dentry, acl_name);
if (ret)
return ret;
return evm_inode_remove_acl(idmap, dentry, acl_name);
Expand Down Expand Up @@ -2503,9 +2493,6 @@ int security_inode_removexattr(struct mnt_idmap *idmap,
ret = call_int_hook(inode_removexattr, 1, idmap, dentry, name);
if (ret == 1)
ret = cap_inode_removexattr(idmap, dentry, name);
if (ret)
return ret;
ret = ima_inode_removexattr(idmap, dentry, name);
if (ret)
return ret;
return evm_inode_removexattr(idmap, dentry, name);
Expand Down

0 comments on commit 84594c9

Please sign in to comment.