Commit cd3cec0a authored by Roberto Sassu's avatar Roberto Sassu Committed by Paul Moore
Browse files

ima: Move to LSM infrastructure



Move hardcoded IMA function calls (not appraisal-specific functions) from
various places in the kernel to the LSM infrastructure, by introducing a
new LSM named 'ima' (at the end of the LSM list and always enabled like
'integrity').

Having IMA before EVM in the Makefile is sufficient to preserve the
relative order of the new 'ima' LSM in respect to the upcoming 'evm' LSM,
and thus the order of IMA and EVM function calls as when they were
hardcoded.

Make moved functions as static (except ima_post_key_create_or_update(),
which is not in ima_main.c), and register them as implementation of the
respective hooks in the new function init_ima_lsm().

Select CONFIG_SECURITY_PATH, to ensure that the path-based LSM hook
path_post_mknod is always available and ima_post_path_mknod() is always
executed to mark files as new, as before the move.

A slight difference is that IMA and EVM functions registered for the
inode_post_setattr, inode_post_removexattr, path_post_mknod,
inode_post_create_tmpfile, inode_post_set_acl and inode_post_remove_acl
won't be executed for private inodes. Since those inodes are supposed to be
fs-internal, they should not be of interest to IMA or EVM. The S_PRIVATE
flag is used for anonymous inodes, hugetlbfs, reiserfs xattrs, XFS scrub
and kernel-internal tmpfs files.

Conditionally register ima_post_key_create_or_update() if
CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS is enabled. Also, conditionally register
ima_kernel_module_request() if CONFIG_INTEGRITY_ASYMMETRIC_KEYS is enabled.

Finally, add the LSM_ID_IMA case in lsm_list_modules_test.c.

Signed-off-by: default avatarRoberto Sassu <roberto.sassu@huawei.com>
Acked-by: default avatarChuck Lever <chuck.lever@oracle.com>
Acked-by: default avatarCasey Schaufler <casey@schaufler-ca.com>
Acked-by: default avatarChristian Brauner <brauner@kernel.org>
Reviewed-by: default avatarStefan Berger <stefanb@linux.ibm.com>
Reviewed-by: default avatarMimi Zohar <zohar@linux.ibm.com>
Acked-by: default avatarMimi Zohar <zohar@linux.ibm.com>
Signed-off-by: default avatarPaul Moore <paul@paul-moore.com>
parent 06cca511
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@
#include <linux/percpu_counter.h>
#include <linux/percpu.h>
#include <linux/task_work.h>
#include <linux/ima.h>
#include <linux/swap.h>
#include <linux/kmemleak.h>

@@ -368,7 +367,6 @@ static void __fput(struct file *file)
	locks_remove_file(file);

	security_file_release(file);
	ima_file_free(file);
	if (unlikely(file->f_flags & FASYNC)) {
		if (file->f_op->fasync)
			file->f_op->fasync(-1, file, 0);
+0 −6
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@
#include <linux/fsnotify.h>
#include <linux/personality.h>
#include <linux/security.h>
#include <linux/ima.h>
#include <linux/syscalls.h>
#include <linux/mount.h>
#include <linux/audit.h>
@@ -3641,8 +3640,6 @@ static int do_open(struct nameidata *nd,
		error = vfs_open(&nd->path, file);
	if (!error)
		error = security_file_post_open(file, op->acc_mode);
	if (!error)
		error = ima_file_check(file, op->acc_mode);
	if (!error && do_truncate)
		error = handle_truncate(idmap, file);
	if (unlikely(error > 0)) {
@@ -3706,7 +3703,6 @@ static int vfs_tmpfile(struct mnt_idmap *idmap,
		spin_unlock(&inode->i_lock);
	}
	security_inode_post_create_tmpfile(idmap, inode);
	ima_post_create_tmpfile(idmap, inode);
	return 0;
}

@@ -4052,8 +4048,6 @@ static int do_mknodat(int dfd, struct filename *name, umode_t mode,
		case 0: case S_IFREG:
			error = vfs_create(idmap, path.dentry->d_inode,
					   dentry, mode, true);
			if (!error)
				ima_post_path_mknod(idmap, dentry);
			break;
		case S_IFCHR: case S_IFBLK:
			error = vfs_mknod(idmap, path.dentry->d_inode,
+0 −7
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@
#include <linux/posix_acl_xattr.h>
#include <linux/xattr.h>
#include <linux/jhash.h>
#include <linux/ima.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
@@ -883,12 +882,6 @@ __nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
		goto out;
	}

	host_err = ima_file_check(file, may_flags);
	if (host_err) {
		fput(file);
		goto out;
	}

	if (may_flags & NFSD_MAY_64BIT_COOKIE)
		file->f_mode |= FMODE_64BITHASH;
	else
+0 −1
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@
#include <linux/audit.h>
#include <linux/falloc.h>
#include <linux/fs_struct.h>
#include <linux/ima.h>
#include <linux/dnotify.h>
#include <linux/compat.h>
#include <linux/mnt_idmapping.h>
+0 −104
Original line number Diff line number Diff line
@@ -16,24 +16,6 @@ struct linux_binprm;

#ifdef CONFIG_IMA
extern enum hash_algo ima_get_current_hash_algo(void);
extern int ima_bprm_check(struct linux_binprm *bprm);
extern int ima_file_check(struct file *file, int mask);
extern void ima_post_create_tmpfile(struct mnt_idmap *idmap,
				    struct inode *inode);
extern void ima_file_free(struct file *file);
extern int ima_file_mmap(struct file *file, unsigned long reqprot,
			 unsigned long prot, unsigned long flags);
extern int ima_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
			     unsigned long prot);
extern int ima_load_data(enum kernel_load_data_id id, bool contents);
extern int ima_post_load_data(char *buf, loff_t size,
			      enum kernel_load_data_id id, char *description);
extern int ima_read_file(struct file *file, enum kernel_read_file_id id,
			 bool contents);
extern int ima_post_read_file(struct file *file, char *buf, loff_t size,
			      enum kernel_read_file_id id);
extern void ima_post_path_mknod(struct mnt_idmap *idmap,
				struct dentry *dentry);
extern int ima_file_hash(struct file *file, char *buf, size_t buf_size);
extern int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size);
extern void ima_kexec_cmdline(int kernel_fd, const void *buf, int size);
@@ -58,68 +40,6 @@ static inline enum hash_algo ima_get_current_hash_algo(void)
	return HASH_ALGO__LAST;
}

static inline int ima_bprm_check(struct linux_binprm *bprm)
{
	return 0;
}

static inline int ima_file_check(struct file *file, int mask)
{
	return 0;
}

static inline void ima_post_create_tmpfile(struct mnt_idmap *idmap,
					   struct inode *inode)
{
}

static inline void ima_file_free(struct file *file)
{
	return;
}

static inline int ima_file_mmap(struct file *file, unsigned long reqprot,
				unsigned long prot, unsigned long flags)
{
	return 0;
}

static inline int ima_file_mprotect(struct vm_area_struct *vma,
				    unsigned long reqprot, unsigned long prot)
{
	return 0;
}

static inline int ima_load_data(enum kernel_load_data_id id, bool contents)
{
	return 0;
}

static inline int ima_post_load_data(char *buf, loff_t size,
				     enum kernel_load_data_id id,
				     char *description)
{
	return 0;
}

static inline int ima_read_file(struct file *file, enum kernel_read_file_id id,
				bool contents)
{
	return 0;
}

static inline int ima_post_read_file(struct file *file, char *buf, loff_t size,
				     enum kernel_read_file_id id)
{
	return 0;
}

static inline void ima_post_path_mknod(struct mnt_idmap *idmap,
				       struct dentry *dentry)
{
	return;
}

static inline int ima_file_hash(struct file *file, char *buf, size_t buf_size)
{
	return -EOPNOTSUPP;
@@ -170,20 +90,6 @@ static inline void ima_add_kexec_buffer(struct kimage *image)
{}
#endif

#ifdef CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS
extern void ima_post_key_create_or_update(struct key *keyring,
					  struct key *key,
					  const void *payload, size_t plen,
					  unsigned long flags, bool create);
#else
static inline void ima_post_key_create_or_update(struct key *keyring,
						 struct key *key,
						 const void *payload,
						 size_t plen,
						 unsigned long flags,
						 bool create) {}
#endif  /* CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS */

#ifdef CONFIG_IMA_APPRAISE
extern bool is_ima_appraise_enabled(void);
extern void ima_inode_post_setattr(struct mnt_idmap *idmap,
@@ -256,14 +162,4 @@ static inline bool ima_appraise_signature(enum kernel_read_file_id func)
	return false;
}
#endif /* CONFIG_IMA_APPRAISE && CONFIG_INTEGRITY_TRUSTED_KEYRING */

#if defined(CONFIG_IMA) && defined(CONFIG_INTEGRITY_ASYMMETRIC_KEYS)
extern int ima_kernel_module_request(char *kmod_name);
#else
static inline int ima_kernel_module_request(char *kmod_name)
{
	return 0;
}

#endif
#endif /* _LINUX_IMA_H */
Loading