Commit cde9df82 authored by Roberto Sassu's avatar Roberto Sassu Committed by Zheng Zengkai
Browse files

ima: Generalize policy file operations



hulk inclusion
category: feature
feature: IMA Digest Lists extension
bugzilla: 46797

-------------------------------------------------

This patch renames ima_open_policy() and ima_release_policy() respectively
to ima_open_data_upload() and ima_release_data_upload(). They will be used
to implement file operations for interfaces allowing to load data from user
space.

A new flag (IMA_POLICY_BUSY) has been defined to prevent concurrent policy
upload.

Signed-off-by: default avatarRoberto Sassu <roberto.sassu@huawei.com>
Signed-off-by: default avatarTianxing Zhang <zhangtianxing3@huawei.com>
Reviewed-by: default avatarJason Yan <yanaijie@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent fd2fdf9d
Loading
Loading
Loading
Loading
+44 −16
Original line number Diff line number Diff line
@@ -395,9 +395,20 @@ static ssize_t ima_write_data(struct file *file, const char __user *buf,
}

enum ima_fs_flags {
	IMA_POLICY_BUSY,
	IMA_FS_BUSY,
};

static enum ima_fs_flags ima_get_dentry_flag(struct dentry *dentry)
{
	enum ima_fs_flags flag = IMA_FS_BUSY;

	if (dentry == ima_policy)
		flag = IMA_POLICY_BUSY;

	return flag;
}

static unsigned long ima_fs_flags;

#ifdef	CONFIG_IMA_READ_POLICY
@@ -410,40 +421,57 @@ static const struct seq_operations ima_policy_seqops = {
#endif

/*
 * ima_open_policy: sequentialize access to the policy file
 * ima_open_data_upload: sequentialize access to the data upload interface
 */
static int ima_open_policy(struct inode *inode, struct file *filp)
static int ima_open_data_upload(struct inode *inode, struct file *filp)
{
	struct dentry *dentry = file_dentry(filp);
	const struct seq_operations *seq_ops = NULL;
	enum ima_fs_flags flag = ima_get_dentry_flag(dentry);
	bool read_allowed = false;

	if (dentry == ima_policy) {
#ifdef	CONFIG_IMA_READ_POLICY
		read_allowed = true;
		seq_ops = &ima_policy_seqops;
#endif
	}

	if (!(filp->f_flags & O_WRONLY)) {
#ifndef	CONFIG_IMA_READ_POLICY
		if (!read_allowed)
			return -EACCES;
#else
		if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
			return -EACCES;
		if (!capable(CAP_SYS_ADMIN))
			return -EPERM;
		return seq_open(filp, &ima_policy_seqops);
#endif
		return seq_open(filp, seq_ops);
	}
	if (test_and_set_bit(IMA_FS_BUSY, &ima_fs_flags))
	if (test_and_set_bit(flag, &ima_fs_flags))
		return -EBUSY;
	return 0;
}

/*
 * ima_release_policy - start using the new measure policy rules.
 * ima_release_data_upload - start using the new measure policy rules.
 *
 * Initially, ima_measure points to the default policy rules, now
 * point to the new policy rules, and remove the securityfs policy file,
 * assuming a valid policy.
 */
static int ima_release_policy(struct inode *inode, struct file *file)
static int ima_release_data_upload(struct inode *inode, struct file *file)
{
	struct dentry *dentry = file_dentry(file);
	const char *cause = valid_policy ? "completed" : "failed";
	enum ima_fs_flags flag = ima_get_dentry_flag(dentry);

	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
		return seq_release(inode, file);

	if (dentry != ima_policy) {
		clear_bit(flag, &ima_fs_flags);
		return 0;
	}

	if (valid_policy && ima_check_policy() < 0) {
		cause = "failed";
		valid_policy = 0;
@@ -456,7 +484,7 @@ static int ima_release_policy(struct inode *inode, struct file *file)
	if (!valid_policy) {
		ima_delete_rules();
		valid_policy = 1;
		clear_bit(IMA_FS_BUSY, &ima_fs_flags);
		clear_bit(flag, &ima_fs_flags);
		return 0;
	}

@@ -465,18 +493,18 @@ static int ima_release_policy(struct inode *inode, struct file *file)
	securityfs_remove(ima_policy);
	ima_policy = NULL;
#elif defined(CONFIG_IMA_WRITE_POLICY)
	clear_bit(IMA_FS_BUSY, &ima_fs_flags);
	clear_bit(flag, &ima_fs_flags);
#elif defined(CONFIG_IMA_READ_POLICY)
	inode->i_mode &= ~S_IWUSR;
#endif
	return 0;
}

static const struct file_operations ima_measure_policy_ops = {
	.open = ima_open_policy,
static const struct file_operations ima_data_upload_ops = {
	.open = ima_open_data_upload,
	.write = ima_write_data,
	.read = seq_read,
	.release = ima_release_policy,
	.release = ima_release_data_upload,
	.llseek = generic_file_llseek,
};

@@ -520,7 +548,7 @@ int __init ima_fs_init(void)

	ima_policy = securityfs_create_file("policy", POLICY_FILE_FLAGS,
					    ima_dir, NULL,
					    &ima_measure_policy_ops);
					    &ima_data_upload_ops);
	if (IS_ERR(ima_policy))
		goto out;