aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xattr.c')
-rw-r--r--fs/xattr.c63
1 files changed, 62 insertions, 1 deletions
diff --git a/fs/xattr.c b/fs/xattr.c
index f060663ab70c..67583de8218c 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -14,6 +14,7 @@
14#include <linux/mount.h> 14#include <linux/mount.h>
15#include <linux/namei.h> 15#include <linux/namei.h>
16#include <linux/security.h> 16#include <linux/security.h>
17#include <linux/evm.h>
17#include <linux/syscalls.h> 18#include <linux/syscalls.h>
18#include <linux/module.h> 19#include <linux/module.h>
19#include <linux/fsnotify.h> 20#include <linux/fsnotify.h>
@@ -166,6 +167,64 @@ out_noalloc:
166} 167}
167EXPORT_SYMBOL_GPL(xattr_getsecurity); 168EXPORT_SYMBOL_GPL(xattr_getsecurity);
168 169
170/*
171 * vfs_getxattr_alloc - allocate memory, if necessary, before calling getxattr
172 *
173 * Allocate memory, if not already allocated, or re-allocate correct size,
174 * before retrieving the extended attribute.
175 *
176 * Returns the result of alloc, if failed, or the getxattr operation.
177 */
178ssize_t
179vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
180 size_t xattr_size, gfp_t flags)
181{
182 struct inode *inode = dentry->d_inode;
183 char *value = *xattr_value;
184 int error;
185
186 error = xattr_permission(inode, name, MAY_READ);
187 if (error)
188 return error;
189
190 if (!inode->i_op->getxattr)
191 return -EOPNOTSUPP;
192
193 error = inode->i_op->getxattr(dentry, name, NULL, 0);
194 if (error < 0)
195 return error;
196
197 if (!value || (error > xattr_size)) {
198 value = krealloc(*xattr_value, error + 1, flags);
199 if (!value)
200 return -ENOMEM;
201 memset(value, 0, error + 1);
202 }
203
204 error = inode->i_op->getxattr(dentry, name, value, error);
205 *xattr_value = value;
206 return error;
207}
208
209/* Compare an extended attribute value with the given value */
210int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name,
211 const char *value, size_t size, gfp_t flags)
212{
213 char *xattr_value = NULL;
214 int rc;
215
216 rc = vfs_getxattr_alloc(dentry, xattr_name, &xattr_value, 0, flags);
217 if (rc < 0)
218 return rc;
219
220 if ((rc != size) || (memcmp(xattr_value, value, rc) != 0))
221 rc = -EINVAL;
222 else
223 rc = 0;
224 kfree(xattr_value);
225 return rc;
226}
227
169ssize_t 228ssize_t
170vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) 229vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
171{ 230{
@@ -243,8 +302,10 @@ vfs_removexattr(struct dentry *dentry, const char *name)
243 error = inode->i_op->removexattr(dentry, name); 302 error = inode->i_op->removexattr(dentry, name);
244 mutex_unlock(&inode->i_mutex); 303 mutex_unlock(&inode->i_mutex);
245 304
246 if (!error) 305 if (!error) {
247 fsnotify_xattr(dentry); 306 fsnotify_xattr(dentry);
307 evm_inode_post_removexattr(dentry, name);
308 }
248 return error; 309 return error;
249} 310}
250EXPORT_SYMBOL_GPL(vfs_removexattr); 311EXPORT_SYMBOL_GPL(vfs_removexattr);