From: Roberto Sassu roberto.sassu@huawei.com
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: Roberto Sassu roberto.sassu@huawei.com Signed-off-by: Tianxing Zhang zhangtianxing3@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Signed-off-by: Zhou Shuiqingzhoushuiqing2@huawei.com --- security/integrity/ima/ima_fs.c | 60 ++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 16 deletions(-)
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 57933bba19e8..b012f853f452 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -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 - return -EACCES; -#else + if (!read_allowed) + return -EACCES; 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, };
@@ -532,7 +560,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)) { ret = PTR_ERR(ima_policy); goto out;