blob: 4be2e7666d02791bf26d2f8f6113e6000db1f0e3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 File: fs/xattr.c
3
4 Extended attribute handling.
5
6 Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
7 Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com>
8 Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
9 */
10#include <linux/fs.h>
11#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <linux/file.h>
13#include <linux/xattr.h>
Dave Hansen18f335a2008-02-15 14:37:38 -080014#include <linux/mount.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <linux/namei.h>
16#include <linux/security.h>
17#include <linux/syscalls.h>
18#include <linux/module.h>
Robert Love0eeca282005-07-12 17:06:03 -040019#include <linux/fsnotify.h>
Amy Griffis73241cc2005-11-03 16:00:25 +000020#include <linux/audit.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <asm/uaccess.h>
22
Christoph Hellwig5be196e2006-01-09 20:51:55 -080023
akpm@osdl.orge0ad7b02006-01-09 20:51:56 -080024/*
25 * Check permissions for extended attribute access. This is a bit complicated
26 * because different namespaces have very different rules.
27 */
28static int
29xattr_permission(struct inode *inode, const char *name, int mask)
30{
31 /*
32 * We can never set or remove an extended attribute on a read-only
33 * filesystem or on an immutable / append-only inode.
34 */
35 if (mask & MAY_WRITE) {
akpm@osdl.orge0ad7b02006-01-09 20:51:56 -080036 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
37 return -EPERM;
38 }
39
40 /*
41 * No restriction for security.* and system.* from the VFS. Decision
42 * on these is left to the underlying filesystem / security module.
43 */
44 if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
45 !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
46 return 0;
47
48 /*
Andreas Gruenbacher55b23bd2011-05-27 14:50:36 +020049 * The trusted.* namespace can only be accessed by privileged users.
akpm@osdl.orge0ad7b02006-01-09 20:51:56 -080050 */
Andreas Gruenbacher55b23bd2011-05-27 14:50:36 +020051 if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
52 if (!capable(CAP_SYS_ADMIN))
53 return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
54 return 0;
55 }
akpm@osdl.orge0ad7b02006-01-09 20:51:56 -080056
Andreas Gruenbacher55b23bd2011-05-27 14:50:36 +020057 /*
58 * In the user.* namespace, only regular files and directories can have
Andreas Gruenbacherf1f2d872006-11-02 22:07:29 -080059 * extended attributes. For sticky directories, only the owner and
Andreas Gruenbacher55b23bd2011-05-27 14:50:36 +020060 * privileged users can write attributes.
Andreas Gruenbacherf1f2d872006-11-02 22:07:29 -080061 */
akpm@osdl.orge0ad7b02006-01-09 20:51:56 -080062 if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
Andreas Gruenbacherf1f2d872006-11-02 22:07:29 -080063 if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
Andreas Gruenbacher55b23bd2011-05-27 14:50:36 +020064 return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
Andreas Gruenbacherf1f2d872006-11-02 22:07:29 -080065 if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
Serge E. Hallyn2e149672011-03-23 16:43:26 -070066 (mask & MAY_WRITE) && !inode_owner_or_capable(inode))
akpm@osdl.orge0ad7b02006-01-09 20:51:56 -080067 return -EPERM;
68 }
69
Al Virof419a2e2008-07-22 00:07:17 -040070 return inode_permission(inode, mask);
akpm@osdl.orge0ad7b02006-01-09 20:51:56 -080071}
72
David P. Quigleyb1ab7e42009-09-03 14:25:56 -040073/**
74 * __vfs_setxattr_noperm - perform setxattr operation without performing
75 * permission checks.
76 *
77 * @dentry - object to perform setxattr on
78 * @name - xattr name to set
79 * @value - value to set @name to
80 * @size - size of @value
81 * @flags - flags to pass into filesystem operations
82 *
83 * returns the result of the internal setxattr or setsecurity operations.
84 *
85 * This function requires the caller to lock the inode's i_mutex before it
86 * is executed. It also assumes that the caller will make the appropriate
87 * permission checks.
88 */
89int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
90 const void *value, size_t size, int flags)
Christoph Hellwig5be196e2006-01-09 20:51:55 -080091{
92 struct inode *inode = dentry->d_inode;
David P. Quigleyb1ab7e42009-09-03 14:25:56 -040093 int error = -EOPNOTSUPP;
Christoph Hellwig5be196e2006-01-09 20:51:55 -080094
Christoph Hellwig5be196e2006-01-09 20:51:55 -080095 if (inode->i_op->setxattr) {
96 error = inode->i_op->setxattr(dentry, name, value, size, flags);
97 if (!error) {
98 fsnotify_xattr(dentry);
99 security_inode_post_setxattr(dentry, name, value,
100 size, flags);
101 }
102 } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
akpm@osdl.orge0ad7b02006-01-09 20:51:56 -0800103 XATTR_SECURITY_PREFIX_LEN)) {
104 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
Christoph Hellwig5be196e2006-01-09 20:51:55 -0800105 error = security_inode_setsecurity(inode, suffix, value,
106 size, flags);
107 if (!error)
108 fsnotify_xattr(dentry);
109 }
David P. Quigleyb1ab7e42009-09-03 14:25:56 -0400110
111 return error;
112}
113
114
115int
116vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
117 size_t size, int flags)
118{
119 struct inode *inode = dentry->d_inode;
120 int error;
121
122 error = xattr_permission(inode, name, MAY_WRITE);
123 if (error)
124 return error;
125
126 mutex_lock(&inode->i_mutex);
127 error = security_inode_setxattr(dentry, name, value, size, flags);
128 if (error)
129 goto out;
130
131 error = __vfs_setxattr_noperm(dentry, name, value, size, flags);
132
Christoph Hellwig5be196e2006-01-09 20:51:55 -0800133out:
134 mutex_unlock(&inode->i_mutex);
135 return error;
136}
137EXPORT_SYMBOL_GPL(vfs_setxattr);
138
139ssize_t
David P. Quigley42492592008-02-04 22:29:39 -0800140xattr_getsecurity(struct inode *inode, const char *name, void *value,
141 size_t size)
142{
143 void *buffer = NULL;
144 ssize_t len;
145
146 if (!value || !size) {
147 len = security_inode_getsecurity(inode, name, &buffer, false);
148 goto out_noalloc;
149 }
150
151 len = security_inode_getsecurity(inode, name, &buffer, true);
152 if (len < 0)
153 return len;
154 if (size < len) {
155 len = -ERANGE;
156 goto out;
157 }
158 memcpy(value, buffer, len);
159out:
160 security_release_secctx(buffer, len);
161out_noalloc:
162 return len;
163}
164EXPORT_SYMBOL_GPL(xattr_getsecurity);
165
166ssize_t
David Howells8f0cfa52008-04-29 00:59:41 -0700167vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
Christoph Hellwig5be196e2006-01-09 20:51:55 -0800168{
169 struct inode *inode = dentry->d_inode;
170 int error;
171
akpm@osdl.orge0ad7b02006-01-09 20:51:56 -0800172 error = xattr_permission(inode, name, MAY_READ);
173 if (error)
174 return error;
175
Christoph Hellwig5be196e2006-01-09 20:51:55 -0800176 error = security_inode_getxattr(dentry, name);
177 if (error)
178 return error;
179
Christoph Hellwig5be196e2006-01-09 20:51:55 -0800180 if (!strncmp(name, XATTR_SECURITY_PREFIX,
akpm@osdl.orge0ad7b02006-01-09 20:51:56 -0800181 XATTR_SECURITY_PREFIX_LEN)) {
182 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
David P. Quigley42492592008-02-04 22:29:39 -0800183 int ret = xattr_getsecurity(inode, suffix, value, size);
Christoph Hellwig5be196e2006-01-09 20:51:55 -0800184 /*
185 * Only overwrite the return value if a security module
186 * is actually active.
187 */
David P. Quigley4bea5802008-02-04 22:29:40 -0800188 if (ret == -EOPNOTSUPP)
189 goto nolsm;
190 return ret;
Christoph Hellwig5be196e2006-01-09 20:51:55 -0800191 }
David P. Quigley4bea5802008-02-04 22:29:40 -0800192nolsm:
193 if (inode->i_op->getxattr)
194 error = inode->i_op->getxattr(dentry, name, value, size);
195 else
196 error = -EOPNOTSUPP;
Christoph Hellwig5be196e2006-01-09 20:51:55 -0800197
198 return error;
199}
200EXPORT_SYMBOL_GPL(vfs_getxattr);
201
Bill Nottingham659564c2006-10-09 16:10:48 -0400202ssize_t
203vfs_listxattr(struct dentry *d, char *list, size_t size)
204{
205 ssize_t error;
206
207 error = security_inode_listxattr(d);
208 if (error)
209 return error;
210 error = -EOPNOTSUPP;
Al Viroacfa4382008-12-04 10:06:33 -0500211 if (d->d_inode->i_op->listxattr) {
Bill Nottingham659564c2006-10-09 16:10:48 -0400212 error = d->d_inode->i_op->listxattr(d, list, size);
213 } else {
214 error = security_inode_listsecurity(d->d_inode, list, size);
215 if (size && error > size)
216 error = -ERANGE;
217 }
218 return error;
219}
220EXPORT_SYMBOL_GPL(vfs_listxattr);
221
Christoph Hellwig5be196e2006-01-09 20:51:55 -0800222int
David Howells8f0cfa52008-04-29 00:59:41 -0700223vfs_removexattr(struct dentry *dentry, const char *name)
Christoph Hellwig5be196e2006-01-09 20:51:55 -0800224{
225 struct inode *inode = dentry->d_inode;
226 int error;
227
228 if (!inode->i_op->removexattr)
229 return -EOPNOTSUPP;
230
akpm@osdl.orge0ad7b02006-01-09 20:51:56 -0800231 error = xattr_permission(inode, name, MAY_WRITE);
232 if (error)
233 return error;
234
Christoph Hellwig5be196e2006-01-09 20:51:55 -0800235 error = security_inode_removexattr(dentry, name);
236 if (error)
237 return error;
238
239 mutex_lock(&inode->i_mutex);
240 error = inode->i_op->removexattr(dentry, name);
241 mutex_unlock(&inode->i_mutex);
242
243 if (!error)
244 fsnotify_xattr(dentry);
245 return error;
246}
247EXPORT_SYMBOL_GPL(vfs_removexattr);
248
249
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250/*
251 * Extended attribute SET operations
252 */
253static long
David Howells8f0cfa52008-04-29 00:59:41 -0700254setxattr(struct dentry *d, const char __user *name, const void __user *value,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 size_t size, int flags)
256{
257 int error;
258 void *kvalue = NULL;
259 char kname[XATTR_NAME_MAX + 1];
260
261 if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
262 return -EINVAL;
263
264 error = strncpy_from_user(kname, name, sizeof(kname));
265 if (error == 0 || error == sizeof(kname))
266 error = -ERANGE;
267 if (error < 0)
268 return error;
269
270 if (size) {
271 if (size > XATTR_SIZE_MAX)
272 return -E2BIG;
Li Zefan3939fcd2009-04-08 15:06:12 +0800273 kvalue = memdup_user(value, size);
274 if (IS_ERR(kvalue))
275 return PTR_ERR(kvalue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 }
277
Christoph Hellwig5be196e2006-01-09 20:51:55 -0800278 error = vfs_setxattr(d, kname, kvalue, size, flags);
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800279 kfree(kvalue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 return error;
281}
282
Heiko Carstens64fd1de2009-01-14 14:14:14 +0100283SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
284 const char __user *, name, const void __user *, value,
285 size_t, size, int, flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286{
Al Viro2d8f3032008-07-22 09:59:21 -0400287 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 int error;
289
Al Viro2d8f3032008-07-22 09:59:21 -0400290 error = user_path(pathname, &path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 if (error)
292 return error;
Al Viro2d8f3032008-07-22 09:59:21 -0400293 error = mnt_want_write(path.mnt);
Dave Hansen18f335a2008-02-15 14:37:38 -0800294 if (!error) {
Al Viro2d8f3032008-07-22 09:59:21 -0400295 error = setxattr(path.dentry, name, value, size, flags);
296 mnt_drop_write(path.mnt);
Dave Hansen18f335a2008-02-15 14:37:38 -0800297 }
Al Viro2d8f3032008-07-22 09:59:21 -0400298 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 return error;
300}
301
Heiko Carstens64fd1de2009-01-14 14:14:14 +0100302SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname,
303 const char __user *, name, const void __user *, value,
304 size_t, size, int, flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305{
Al Viro2d8f3032008-07-22 09:59:21 -0400306 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 int error;
308
Al Viro2d8f3032008-07-22 09:59:21 -0400309 error = user_lpath(pathname, &path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 if (error)
311 return error;
Al Viro2d8f3032008-07-22 09:59:21 -0400312 error = mnt_want_write(path.mnt);
Dave Hansen18f335a2008-02-15 14:37:38 -0800313 if (!error) {
Al Viro2d8f3032008-07-22 09:59:21 -0400314 error = setxattr(path.dentry, name, value, size, flags);
315 mnt_drop_write(path.mnt);
Dave Hansen18f335a2008-02-15 14:37:38 -0800316 }
Al Viro2d8f3032008-07-22 09:59:21 -0400317 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 return error;
319}
320
Heiko Carstens64fd1de2009-01-14 14:14:14 +0100321SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
322 const void __user *,value, size_t, size, int, flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323{
324 struct file *f;
Amy Griffis73241cc2005-11-03 16:00:25 +0000325 struct dentry *dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 int error = -EBADF;
327
328 f = fget(fd);
329 if (!f)
330 return error;
Josef "Jeff" Sipek0f7fc9e2006-12-08 02:36:35 -0800331 dentry = f->f_path.dentry;
Al Viro5a190ae2007-06-07 12:19:32 -0400332 audit_inode(NULL, dentry);
npiggin@suse.de96029c42009-04-26 20:25:55 +1000333 error = mnt_want_write_file(f);
Dave Hansen18f335a2008-02-15 14:37:38 -0800334 if (!error) {
335 error = setxattr(dentry, name, value, size, flags);
336 mnt_drop_write(f->f_path.mnt);
337 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 fput(f);
339 return error;
340}
341
342/*
343 * Extended attribute GET operations
344 */
345static ssize_t
David Howells8f0cfa52008-04-29 00:59:41 -0700346getxattr(struct dentry *d, const char __user *name, void __user *value,
347 size_t size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348{
349 ssize_t error;
350 void *kvalue = NULL;
351 char kname[XATTR_NAME_MAX + 1];
352
353 error = strncpy_from_user(kname, name, sizeof(kname));
354 if (error == 0 || error == sizeof(kname))
355 error = -ERANGE;
356 if (error < 0)
357 return error;
358
359 if (size) {
360 if (size > XATTR_SIZE_MAX)
361 size = XATTR_SIZE_MAX;
James Morrisd381d8a2005-10-30 14:59:22 -0800362 kvalue = kzalloc(size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 if (!kvalue)
364 return -ENOMEM;
365 }
366
Christoph Hellwig5be196e2006-01-09 20:51:55 -0800367 error = vfs_getxattr(d, kname, kvalue, size);
Stephen Smalleyf549d6c2005-09-03 15:55:18 -0700368 if (error > 0) {
369 if (size && copy_to_user(value, kvalue, error))
370 error = -EFAULT;
371 } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
372 /* The file system tried to returned a value bigger
373 than XATTR_SIZE_MAX bytes. Not possible. */
374 error = -E2BIG;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 }
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800376 kfree(kvalue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 return error;
378}
379
Heiko Carstens64fd1de2009-01-14 14:14:14 +0100380SYSCALL_DEFINE4(getxattr, const char __user *, pathname,
381 const char __user *, name, void __user *, value, size_t, size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382{
Al Viro2d8f3032008-07-22 09:59:21 -0400383 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 ssize_t error;
385
Al Viro2d8f3032008-07-22 09:59:21 -0400386 error = user_path(pathname, &path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 if (error)
388 return error;
Al Viro2d8f3032008-07-22 09:59:21 -0400389 error = getxattr(path.dentry, name, value, size);
390 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 return error;
392}
393
Heiko Carstens64fd1de2009-01-14 14:14:14 +0100394SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname,
395 const char __user *, name, void __user *, value, size_t, size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396{
Al Viro2d8f3032008-07-22 09:59:21 -0400397 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 ssize_t error;
399
Al Viro2d8f3032008-07-22 09:59:21 -0400400 error = user_lpath(pathname, &path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 if (error)
402 return error;
Al Viro2d8f3032008-07-22 09:59:21 -0400403 error = getxattr(path.dentry, name, value, size);
404 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 return error;
406}
407
Heiko Carstens64fd1de2009-01-14 14:14:14 +0100408SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
409 void __user *, value, size_t, size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410{
411 struct file *f;
412 ssize_t error = -EBADF;
413
414 f = fget(fd);
415 if (!f)
416 return error;
Al Viro5a190ae2007-06-07 12:19:32 -0400417 audit_inode(NULL, f->f_path.dentry);
Josef "Jeff" Sipek0f7fc9e2006-12-08 02:36:35 -0800418 error = getxattr(f->f_path.dentry, name, value, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 fput(f);
420 return error;
421}
422
423/*
424 * Extended attribute LIST operations
425 */
426static ssize_t
427listxattr(struct dentry *d, char __user *list, size_t size)
428{
429 ssize_t error;
430 char *klist = NULL;
431
432 if (size) {
433 if (size > XATTR_LIST_MAX)
434 size = XATTR_LIST_MAX;
435 klist = kmalloc(size, GFP_KERNEL);
436 if (!klist)
437 return -ENOMEM;
438 }
439
Bill Nottingham659564c2006-10-09 16:10:48 -0400440 error = vfs_listxattr(d, klist, size);
Stephen Smalleyf549d6c2005-09-03 15:55:18 -0700441 if (error > 0) {
442 if (size && copy_to_user(list, klist, error))
443 error = -EFAULT;
444 } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
445 /* The file system tried to returned a list bigger
446 than XATTR_LIST_MAX bytes. Not possible. */
447 error = -E2BIG;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 }
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800449 kfree(klist);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 return error;
451}
452
Heiko Carstens64fd1de2009-01-14 14:14:14 +0100453SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list,
454 size_t, size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455{
Al Viro2d8f3032008-07-22 09:59:21 -0400456 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 ssize_t error;
458
Al Viro2d8f3032008-07-22 09:59:21 -0400459 error = user_path(pathname, &path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 if (error)
461 return error;
Al Viro2d8f3032008-07-22 09:59:21 -0400462 error = listxattr(path.dentry, list, size);
463 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 return error;
465}
466
Heiko Carstens64fd1de2009-01-14 14:14:14 +0100467SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list,
468 size_t, size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469{
Al Viro2d8f3032008-07-22 09:59:21 -0400470 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 ssize_t error;
472
Al Viro2d8f3032008-07-22 09:59:21 -0400473 error = user_lpath(pathname, &path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 if (error)
475 return error;
Al Viro2d8f3032008-07-22 09:59:21 -0400476 error = listxattr(path.dentry, list, size);
477 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 return error;
479}
480
Heiko Carstens64fd1de2009-01-14 14:14:14 +0100481SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482{
483 struct file *f;
484 ssize_t error = -EBADF;
485
486 f = fget(fd);
487 if (!f)
488 return error;
Al Viro5a190ae2007-06-07 12:19:32 -0400489 audit_inode(NULL, f->f_path.dentry);
Josef "Jeff" Sipek0f7fc9e2006-12-08 02:36:35 -0800490 error = listxattr(f->f_path.dentry, list, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 fput(f);
492 return error;
493}
494
495/*
496 * Extended attribute REMOVE operations
497 */
498static long
David Howells8f0cfa52008-04-29 00:59:41 -0700499removexattr(struct dentry *d, const char __user *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500{
501 int error;
502 char kname[XATTR_NAME_MAX + 1];
503
504 error = strncpy_from_user(kname, name, sizeof(kname));
505 if (error == 0 || error == sizeof(kname))
506 error = -ERANGE;
507 if (error < 0)
508 return error;
509
Christoph Hellwig5be196e2006-01-09 20:51:55 -0800510 return vfs_removexattr(d, kname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511}
512
Heiko Carstens64fd1de2009-01-14 14:14:14 +0100513SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
514 const char __user *, name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515{
Al Viro2d8f3032008-07-22 09:59:21 -0400516 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 int error;
518
Al Viro2d8f3032008-07-22 09:59:21 -0400519 error = user_path(pathname, &path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 if (error)
521 return error;
Al Viro2d8f3032008-07-22 09:59:21 -0400522 error = mnt_want_write(path.mnt);
Dave Hansen18f335a2008-02-15 14:37:38 -0800523 if (!error) {
Al Viro2d8f3032008-07-22 09:59:21 -0400524 error = removexattr(path.dentry, name);
525 mnt_drop_write(path.mnt);
Dave Hansen18f335a2008-02-15 14:37:38 -0800526 }
Al Viro2d8f3032008-07-22 09:59:21 -0400527 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 return error;
529}
530
Heiko Carstens6a6160a2009-01-14 14:14:15 +0100531SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
532 const char __user *, name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533{
Al Viro2d8f3032008-07-22 09:59:21 -0400534 struct path path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 int error;
536
Al Viro2d8f3032008-07-22 09:59:21 -0400537 error = user_lpath(pathname, &path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 if (error)
539 return error;
Al Viro2d8f3032008-07-22 09:59:21 -0400540 error = mnt_want_write(path.mnt);
Dave Hansen18f335a2008-02-15 14:37:38 -0800541 if (!error) {
Al Viro2d8f3032008-07-22 09:59:21 -0400542 error = removexattr(path.dentry, name);
543 mnt_drop_write(path.mnt);
Dave Hansen18f335a2008-02-15 14:37:38 -0800544 }
Al Viro2d8f3032008-07-22 09:59:21 -0400545 path_put(&path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 return error;
547}
548
Heiko Carstens6a6160a2009-01-14 14:14:15 +0100549SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550{
551 struct file *f;
Amy Griffis73241cc2005-11-03 16:00:25 +0000552 struct dentry *dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 int error = -EBADF;
554
555 f = fget(fd);
556 if (!f)
557 return error;
Josef "Jeff" Sipek0f7fc9e2006-12-08 02:36:35 -0800558 dentry = f->f_path.dentry;
Al Viro5a190ae2007-06-07 12:19:32 -0400559 audit_inode(NULL, dentry);
npiggin@suse.de96029c42009-04-26 20:25:55 +1000560 error = mnt_want_write_file(f);
Dave Hansen18f335a2008-02-15 14:37:38 -0800561 if (!error) {
562 error = removexattr(dentry, name);
563 mnt_drop_write(f->f_path.mnt);
564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 fput(f);
566 return error;
567}
568
569
570static const char *
571strcmp_prefix(const char *a, const char *a_prefix)
572{
573 while (*a_prefix && *a == *a_prefix) {
574 a++;
575 a_prefix++;
576 }
577 return *a_prefix ? NULL : a;
578}
579
580/*
581 * In order to implement different sets of xattr operations for each xattr
582 * prefix with the generic xattr API, a filesystem should create a
583 * null-terminated array of struct xattr_handler (one for each prefix) and
584 * hang a pointer to it off of the s_xattr field of the superblock.
585 *
586 * The generic_fooxattr() functions will use this list to dispatch xattr
587 * operations to the correct xattr_handler.
588 */
589#define for_each_xattr_handler(handlers, handler) \
590 for ((handler) = *(handlers)++; \
591 (handler) != NULL; \
592 (handler) = *(handlers)++)
593
594/*
595 * Find the xattr_handler with the matching prefix.
596 */
Stephen Hemmingerbb435452010-05-13 17:53:14 -0700597static const struct xattr_handler *
598xattr_resolve_name(const struct xattr_handler **handlers, const char **name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599{
Stephen Hemmingerbb435452010-05-13 17:53:14 -0700600 const struct xattr_handler *handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601
602 if (!*name)
603 return NULL;
604
605 for_each_xattr_handler(handlers, handler) {
606 const char *n = strcmp_prefix(*name, handler->prefix);
607 if (n) {
608 *name = n;
609 break;
610 }
611 }
612 return handler;
613}
614
615/*
616 * Find the handler for the prefix and dispatch its get() operation.
617 */
618ssize_t
619generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
620{
Stephen Hemmingerbb435452010-05-13 17:53:14 -0700621 const struct xattr_handler *handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622
Christoph Hellwig431547b2009-11-13 09:52:56 +0000623 handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 if (!handler)
625 return -EOPNOTSUPP;
Christoph Hellwig431547b2009-11-13 09:52:56 +0000626 return handler->get(dentry, name, buffer, size, handler->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627}
628
629/*
630 * Combine the results of the list() operation from every xattr_handler in the
631 * list.
632 */
633ssize_t
634generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
635{
Stephen Hemmingerbb435452010-05-13 17:53:14 -0700636 const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 unsigned int size = 0;
638
639 if (!buffer) {
Christoph Hellwig431547b2009-11-13 09:52:56 +0000640 for_each_xattr_handler(handlers, handler) {
641 size += handler->list(dentry, NULL, 0, NULL, 0,
642 handler->flags);
643 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 } else {
645 char *buf = buffer;
646
647 for_each_xattr_handler(handlers, handler) {
Christoph Hellwig431547b2009-11-13 09:52:56 +0000648 size = handler->list(dentry, buf, buffer_size,
649 NULL, 0, handler->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 if (size > buffer_size)
651 return -ERANGE;
652 buf += size;
653 buffer_size -= size;
654 }
655 size = buf - buffer;
656 }
657 return size;
658}
659
660/*
661 * Find the handler for the prefix and dispatch its set() operation.
662 */
663int
664generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
665{
Stephen Hemmingerbb435452010-05-13 17:53:14 -0700666 const struct xattr_handler *handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667
668 if (size == 0)
669 value = ""; /* empty EA, do not remove */
Christoph Hellwig431547b2009-11-13 09:52:56 +0000670 handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 if (!handler)
672 return -EOPNOTSUPP;
Jan Karadf7e1302011-04-20 20:30:40 +0200673 return handler->set(dentry, name, value, size, flags, handler->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674}
675
676/*
677 * Find the handler for the prefix and dispatch its set() operation to remove
678 * any associated extended attribute.
679 */
680int
681generic_removexattr(struct dentry *dentry, const char *name)
682{
Stephen Hemmingerbb435452010-05-13 17:53:14 -0700683 const struct xattr_handler *handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
Christoph Hellwig431547b2009-11-13 09:52:56 +0000685 handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 if (!handler)
687 return -EOPNOTSUPP;
Christoph Hellwig431547b2009-11-13 09:52:56 +0000688 return handler->set(dentry, name, NULL, 0,
689 XATTR_REPLACE, handler->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690}
691
692EXPORT_SYMBOL(generic_getxattr);
693EXPORT_SYMBOL(generic_listxattr);
694EXPORT_SYMBOL(generic_setxattr);
695EXPORT_SYMBOL(generic_removexattr);