Based on xattr_permission comments, the restriction to modify 'security' xattr is left up to the underlying fs or lsm. Ensure that not just anyone can modify or remove 'security.ima'. Signed-off-by: Mimi Zohar <zohar@xxxxxxxxxx> --- include/linux/ima.h | 13 +++++++++++++ security/integrity/ima/ima_main.c | 26 ++++++++++++++++++++++++++ security/security.c | 6 ++++++ 3 files changed, 45 insertions(+), 0 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index ce82e29..3307420 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -20,6 +20,9 @@ extern void ima_file_free(struct file *file); extern int ima_file_mmap(struct file *file, unsigned long prot); extern void ima_counts_get(struct file *file); extern void ima_inode_post_setattr(struct dentry *dentry); +extern int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, + const void *xattr_value, size_t xattr_value_len); +extern int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name); #else static inline int ima_bprm_check(struct linux_binprm *bprm) @@ -52,5 +55,15 @@ static inline void ima_inode_post_setattr(struct dentry *dentry) return; } +int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, + const void *xattr_value, size_t xattr_value_len) +{ + return 0; +} + +int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name) +{ + return 0; +} #endif /* CONFIG_IMA_H */ #endif /* _LINUX_IMA_H */ diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 9aae59e..62a7cf6 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -371,6 +371,32 @@ void ima_inode_post_setattr(struct dentry *dentry) return; } +/* + * ima_protect_xattr - protect 'security.ima' + * + * Ensure that not just anyone can modify or remove 'security.ima'. + */ +int ima_protect_xattr(struct dentry *dentry, const char *xattr_name, + const void *xattr_value, size_t xattr_value_len) +{ + if ((strcmp(xattr_name, XATTR_NAME_IMA) == 0) + && !capable(CAP_MAC_ADMIN)) + return -EPERM; + return 0; +} + +int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, + const void *xattr_value, size_t xattr_value_len) +{ + return ima_protect_xattr(dentry, xattr_name, xattr_value, + xattr_value_len); +} + +int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name) +{ + return ima_protect_xattr(dentry, xattr_name, NULL, 0); +} + static int __init init_ima(void) { int error; diff --git a/security/security.c b/security/security.c index c373c5f..53c6285 100644 --- a/security/security.c +++ b/security/security.c @@ -556,6 +556,9 @@ int security_inode_setxattr(struct dentry *dentry, const char *name, ret = security_ops->inode_setxattr(dentry, name, value, size, flags); if (ret) return ret; + ret = ima_inode_setxattr(dentry, name, value, size); + if (ret) + return ret; return evm_inode_setxattr(dentry, name, value, size); } @@ -591,6 +594,9 @@ int security_inode_removexattr(struct dentry *dentry, const char *name) ret = security_ops->inode_removexattr(dentry, name); if (ret) return ret; + ret = ima_inode_removexattr(dentry, name); + if (ret) + return ret; return evm_inode_removexattr(dentry, name); } -- 1.6.6.1 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html