Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756794Ab0DUVvH (ORCPT ); Wed, 21 Apr 2010 17:51:07 -0400 Received: from e31.co.us.ibm.com ([32.97.110.149]:42332 "EHLO e31.co.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756685Ab0DUVu7 (ORCPT ); Wed, 21 Apr 2010 17:50:59 -0400 From: Mimi Zohar To: linux-kernel@vger.kernel.org Cc: linux-security-module@vger.kernel.org, Mimi Zohar , James Morris , David Safford , Dave Hansen , Mimi Zohar Subject: [PATCH 03/14] xattr: define vfs_getxattr_alloc and vfs_xattr_cmp Date: Wed, 21 Apr 2010 17:49:43 -0400 Message-Id: <1271886594-3719-4-git-send-email-zohar@linux.vnet.ibm.com> X-Mailer: git-send-email 1.6.6.1 In-Reply-To: <1271886594-3719-1-git-send-email-zohar@linux.vnet.ibm.com> References: <1271886594-3719-1-git-send-email-zohar@linux.vnet.ibm.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3109 Lines: 100 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 diff --git a/fs/xattr.c b/fs/xattr.c index 46f87e8..341ad71 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -159,6 +159,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) { diff --git a/include/linux/xattr.h b/include/linux/xattr.h index d079bec..8698de3 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -68,7 +68,10 @@ ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size); int generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); int generic_removexattr(struct dentry *dentry, const char *name); - +ssize_t vfs_getxattr_alloc(struct dentry *dentry, const char *name, + char **xattr_value, size_t size, gfp_t flags); +int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name, + const char *value, size_t size, gfp_t flags); #endif /* __KERNEL__ */ #endif /* _LINUX_XATTR_H */ -- 1.6.6.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/