From 1601fbad2b14e0b8d4dbb55e749bfe31e972818a Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Wed, 9 Mar 2011 14:23:34 -0500 Subject: xattr: define vfs_getxattr_alloc and vfs_xattr_cmp vfs_getxattr_alloc() and vfs_xattr_cmp() are two new kernel xattr helper functions. vfs_getxattr_alloc() first allocates memory for the requested xattr and then retrieves it. vfs_xattr_cmp() compares a given value with the contents of an extended attribute. Signed-off-by: Mimi Zohar Acked-by: Serge Hallyn --- fs/xattr.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'fs/xattr.c') diff --git a/fs/xattr.c b/fs/xattr.c index f060663ab70c..851808c92b30 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -166,6 +166,64 @@ out_noalloc: } EXPORT_SYMBOL_GPL(xattr_getsecurity); +/* + * vfs_getxattr_alloc - allocate memory, if necessary, before calling getxattr + * + * Allocate memory, if not already allocated, or re-allocate correct size, + * before retrieving the extended attribute. + * + * Returns the result of alloc, if failed, or the getxattr operation. + */ +ssize_t +vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, + size_t xattr_size, gfp_t flags) +{ + struct inode *inode = dentry->d_inode; + char *value = *xattr_value; + int error; + + error = xattr_permission(inode, name, MAY_READ); + if (error) + return error; + + if (!inode->i_op->getxattr) + return -EOPNOTSUPP; + + error = inode->i_op->getxattr(dentry, name, NULL, 0); + if (error < 0) + return error; + + if (!value || (error > xattr_size)) { + value = krealloc(*xattr_value, error + 1, flags); + if (!value) + return -ENOMEM; + memset(value, 0, error + 1); + } + + error = inode->i_op->getxattr(dentry, name, value, error); + *xattr_value = value; + return error; +} + +/* Compare an extended attribute value with the given value */ +int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name, + const char *value, size_t size, gfp_t flags) +{ + char *xattr_value = NULL; + int rc; + + rc = vfs_getxattr_alloc(dentry, xattr_name, &xattr_value, 0, flags); + if (rc < 0) + return rc; + + if ((rc != size) || (memcmp(xattr_value, value, rc) != 0)) + rc = -EINVAL; + else + rc = 0; + kfree(xattr_value); + return rc; +} + ssize_t vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) { -- cgit v1.2.3 From c7b87de23b6fd5dfbe5c36601f29d6c515056343 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Wed, 9 Mar 2011 14:39:18 -0500 Subject: evm: evm_inode_post_removexattr When an EVM protected extended attribute is removed, update 'security.evm'. Signed-off-by: Mimi Zohar Acked-by: Serge Hallyn --- fs/xattr.c | 5 ++++- include/linux/evm.h | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'fs/xattr.c') diff --git a/fs/xattr.c b/fs/xattr.c index 851808c92b30..67583de8218c 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -301,8 +302,10 @@ vfs_removexattr(struct dentry *dentry, const char *name) error = inode->i_op->removexattr(dentry, name); mutex_unlock(&inode->i_mutex); - if (!error) + if (!error) { fsnotify_xattr(dentry); + evm_inode_post_removexattr(dentry, name); + } return error; } EXPORT_SYMBOL_GPL(vfs_removexattr); diff --git a/include/linux/evm.h b/include/linux/evm.h index 8b4e9e3b395e..a730782da563 100644 --- a/include/linux/evm.h +++ b/include/linux/evm.h @@ -22,6 +22,8 @@ extern void evm_inode_post_setxattr(struct dentry *dentry, const void *xattr_value, size_t xattr_value_len); extern int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name); +extern void evm_inode_post_removexattr(struct dentry *dentry, + const char *xattr_name); #else #ifdef CONFIG_INTEGRITY static inline enum integrity_status evm_verifyxattr(struct dentry *dentry, @@ -52,5 +54,12 @@ static inline int evm_inode_removexattr(struct dentry *dentry, { return 0; } + +static inline void evm_inode_post_removexattr(struct dentry *dentry, + const char *xattr_name) +{ + return; +} + #endif /* CONFIG_EVM_H */ #endif /* LINUX_EVM_H */ -- cgit v1.2.3