Blame view

fs/xattr.c 23.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
  /*
    File: fs/xattr.c
  
    Extended attribute handling.
  
    Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
    Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com>
    Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
   */
  #include <linux/fs.h>
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
  #include <linux/file.h>
  #include <linux/xattr.h>
18f335aff   Dave Hansen   [PATCH] r/o bind ...
14
  #include <linux/mount.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
  #include <linux/namei.h>
  #include <linux/security.h>
c7b87de23   Mimi Zohar   evm: evm_inode_po...
17
  #include <linux/evm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include <linux/syscalls.h>
630d9c472   Paul Gortmaker   fs: reduce the us...
19
  #include <linux/export.h>
0eeca2830   Robert Love   [PATCH] inotify
20
  #include <linux/fsnotify.h>
73241ccca   Amy Griffis   [PATCH] Collect m...
21
  #include <linux/audit.h>
0d08d7b7e   Andrew Morton   fs/xattr.c:listxa...
22
  #include <linux/vmalloc.h>
2f6f0654a   Eric W. Biederman   userns: Convert v...
23
  #include <linux/posix_acl_xattr.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24

7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
25
  #include <linux/uaccess.h>
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
26
  #include "internal.h"
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
27

b6ba11773   Andreas Gruenbacher   vfs: Move xattr_r...
28
29
30
31
32
33
34
35
36
37
38
39
  static const char *
  strcmp_prefix(const char *a, const char *a_prefix)
  {
  	while (*a_prefix && *a == *a_prefix) {
  		a++;
  		a_prefix++;
  	}
  	return *a_prefix ? NULL : a;
  }
  
  /*
   * In order to implement different sets of xattr operations for each xattr
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
40
41
42
   * prefix, a filesystem should create a null-terminated array of struct
   * xattr_handler (one for each prefix) and hang a pointer to it off of the
   * s_xattr field of the superblock.
b6ba11773   Andreas Gruenbacher   vfs: Move xattr_r...
43
44
45
46
47
48
49
50
51
52
53
   */
  #define for_each_xattr_handler(handlers, handler)		\
  	if (handlers)						\
  		for ((handler) = *(handlers)++;			\
  			(handler) != NULL;			\
  			(handler) = *(handlers)++)
  
  /*
   * Find the xattr_handler with the matching prefix.
   */
  static const struct xattr_handler *
d0a5b995a   Andreas Gruenbacher   vfs: Add IOP_XATT...
54
  xattr_resolve_name(struct inode *inode, const char **name)
b6ba11773   Andreas Gruenbacher   vfs: Move xattr_r...
55
  {
d0a5b995a   Andreas Gruenbacher   vfs: Add IOP_XATT...
56
  	const struct xattr_handler **handlers = inode->i_sb->s_xattr;
b6ba11773   Andreas Gruenbacher   vfs: Move xattr_r...
57
  	const struct xattr_handler *handler;
5f6e59ae8   Andreas Gruenbacher   vfs: Use IOP_XATT...
58
59
60
  	if (!(inode->i_opflags & IOP_XATTR)) {
  		if (unlikely(is_bad_inode(inode)))
  			return ERR_PTR(-EIO);
d0a5b995a   Andreas Gruenbacher   vfs: Add IOP_XATT...
61
  		return ERR_PTR(-EOPNOTSUPP);
5f6e59ae8   Andreas Gruenbacher   vfs: Use IOP_XATT...
62
  	}
b6ba11773   Andreas Gruenbacher   vfs: Move xattr_r...
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  	for_each_xattr_handler(handlers, handler) {
  		const char *n;
  
  		n = strcmp_prefix(*name, xattr_prefix(handler));
  		if (n) {
  			if (!handler->prefix ^ !*n) {
  				if (*n)
  					continue;
  				return ERR_PTR(-EINVAL);
  			}
  			*name = n;
  			return handler;
  		}
  	}
  	return ERR_PTR(-EOPNOTSUPP);
  }
e0ad7b073   Andrew Morton   [PATCH] move xatt...
79
80
81
82
83
84
85
86
87
88
89
90
  /*
   * Check permissions for extended attribute access.  This is a bit complicated
   * because different namespaces have very different rules.
   */
  static int
  xattr_permission(struct inode *inode, const char *name, int mask)
  {
  	/*
  	 * We can never set or remove an extended attribute on a read-only
  	 * filesystem  or on an immutable / append-only inode.
  	 */
  	if (mask & MAY_WRITE) {
e0ad7b073   Andrew Morton   [PATCH] move xatt...
91
92
  		if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  			return -EPERM;
0bd23d09b   Eric W. Biederman   vfs: Don't modify...
93
94
95
96
97
98
99
  		/*
  		 * Updating an xattr will likely cause i_uid and i_gid
  		 * to be writen back improperly if their true value is
  		 * unknown to the vfs.
  		 */
  		if (HAS_UNMAPPED_ID(inode))
  			return -EPERM;
e0ad7b073   Andrew Morton   [PATCH] move xatt...
100
101
102
103
104
105
106
107
108
109
110
  	}
  
  	/*
  	 * No restriction for security.* and system.* from the VFS.  Decision
  	 * on these is left to the underlying filesystem / security module.
  	 */
  	if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
  	    !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
  		return 0;
  
  	/*
55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
111
  	 * The trusted.* namespace can only be accessed by privileged users.
e0ad7b073   Andrew Morton   [PATCH] move xatt...
112
  	 */
55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
113
114
115
116
117
  	if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
  		if (!capable(CAP_SYS_ADMIN))
  			return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
  		return 0;
  	}
e0ad7b073   Andrew Morton   [PATCH] move xatt...
118

55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
119
120
  	/*
  	 * In the user.* namespace, only regular files and directories can have
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
121
  	 * extended attributes. For sticky directories, only the owner and
55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
122
  	 * privileged users can write attributes.
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
123
  	 */
e0ad7b073   Andrew Morton   [PATCH] move xatt...
124
  	if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
125
  		if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
126
  			return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
127
  		if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
2e1496707   Serge E. Hallyn   userns: rename is...
128
  		    (mask & MAY_WRITE) && !inode_owner_or_capable(inode))
e0ad7b073   Andrew Morton   [PATCH] move xatt...
129
130
  			return -EPERM;
  	}
f419a2e3b   Al Viro   [PATCH] kill name...
131
  	return inode_permission(inode, mask);
e0ad7b073   Andrew Morton   [PATCH] move xatt...
132
  }
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
133
134
135
136
  int
  __vfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
  	       const void *value, size_t size, int flags)
  {
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
137
138
139
140
141
142
  	const struct xattr_handler *handler;
  
  	handler = xattr_resolve_name(inode, &name);
  	if (IS_ERR(handler))
  		return PTR_ERR(handler);
  	if (!handler->set)
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
143
  		return -EOPNOTSUPP;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
144
145
146
  	if (size == 0)
  		value = "";  /* empty EA, do not remove */
  	return handler->set(handler, dentry, inode, name, value, size, flags);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
147
148
  }
  EXPORT_SYMBOL(__vfs_setxattr);
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  /**
   *  __vfs_setxattr_noperm - perform setxattr operation without performing
   *  permission checks.
   *
   *  @dentry - object to perform setxattr on
   *  @name - xattr name to set
   *  @value - value to set @name to
   *  @size - size of @value
   *  @flags - flags to pass into filesystem operations
   *
   *  returns the result of the internal setxattr or setsecurity operations.
   *
   *  This function requires the caller to lock the inode's i_mutex before it
   *  is executed. It also assumes that the caller will make the appropriate
   *  permission checks.
   */
  int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
  		const void *value, size_t size, int flags)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
167
168
  {
  	struct inode *inode = dentry->d_inode;
4a5901537   Andreas Gruenbacher   xattr: Fix settin...
169
  	int error = -EAGAIN;
69b457329   Andi Kleen   Cache xattr secur...
170
171
  	int issec = !strncmp(name, XATTR_SECURITY_PREFIX,
  				   XATTR_SECURITY_PREFIX_LEN);
e0ad7b073   Andrew Morton   [PATCH] move xatt...
172

69b457329   Andi Kleen   Cache xattr secur...
173
174
  	if (issec)
  		inode->i_flags &= ~S_NOSEC;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
175
  	if (inode->i_opflags & IOP_XATTR) {
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
176
  		error = __vfs_setxattr(dentry, inode, name, value, size, flags);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
177
178
179
180
181
  		if (!error) {
  			fsnotify_xattr(dentry);
  			security_inode_post_setxattr(dentry, name, value,
  						     size, flags);
  		}
4a5901537   Andreas Gruenbacher   xattr: Fix settin...
182
  	} else {
5f6e59ae8   Andreas Gruenbacher   vfs: Use IOP_XATT...
183
184
  		if (unlikely(is_bad_inode(inode)))
  			return -EIO;
4a5901537   Andreas Gruenbacher   xattr: Fix settin...
185
186
187
188
189
190
191
192
193
194
195
196
  	}
  	if (error == -EAGAIN) {
  		error = -EOPNOTSUPP;
  
  		if (issec) {
  			const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
  
  			error = security_inode_setsecurity(inode, suffix, value,
  							   size, flags);
  			if (!error)
  				fsnotify_xattr(dentry);
  		}
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
197
  	}
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
  
  	return error;
  }
  
  
  int
  vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
  		size_t size, int flags)
  {
  	struct inode *inode = dentry->d_inode;
  	int error;
  
  	error = xattr_permission(inode, name, MAY_WRITE);
  	if (error)
  		return error;
5955102c9   Al Viro   wrappers for ->i_...
213
  	inode_lock(inode);
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
214
215
216
217
218
  	error = security_inode_setxattr(dentry, name, value, size, flags);
  	if (error)
  		goto out;
  
  	error = __vfs_setxattr_noperm(dentry, name, value, size, flags);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
219
  out:
5955102c9   Al Viro   wrappers for ->i_...
220
  	inode_unlock(inode);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
221
222
223
224
225
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_setxattr);
  
  ssize_t
424925940   David P. Quigley   VFS/Security: Rew...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
  xattr_getsecurity(struct inode *inode, const char *name, void *value,
  			size_t size)
  {
  	void *buffer = NULL;
  	ssize_t len;
  
  	if (!value || !size) {
  		len = security_inode_getsecurity(inode, name, &buffer, false);
  		goto out_noalloc;
  	}
  
  	len = security_inode_getsecurity(inode, name, &buffer, true);
  	if (len < 0)
  		return len;
  	if (size < len) {
  		len = -ERANGE;
  		goto out;
  	}
  	memcpy(value, buffer, len);
  out:
57e7ba04d   Casey Schaufler   lsm: fix smack_in...
246
  	kfree(buffer);
424925940   David P. Quigley   VFS/Security: Rew...
247
248
249
250
  out_noalloc:
  	return len;
  }
  EXPORT_SYMBOL_GPL(xattr_getsecurity);
1601fbad2   Mimi Zohar   xattr: define vfs...
251
252
253
254
255
256
257
258
259
260
261
262
  /*
   * 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)
  {
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
263
  	const struct xattr_handler *handler;
1601fbad2   Mimi Zohar   xattr: define vfs...
264
265
266
267
268
269
270
  	struct inode *inode = dentry->d_inode;
  	char *value = *xattr_value;
  	int error;
  
  	error = xattr_permission(inode, name, MAY_READ);
  	if (error)
  		return error;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
271
272
273
274
  	handler = xattr_resolve_name(inode, &name);
  	if (IS_ERR(handler))
  		return PTR_ERR(handler);
  	if (!handler->get)
1601fbad2   Mimi Zohar   xattr: define vfs...
275
  		return -EOPNOTSUPP;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
276
  	error = handler->get(handler, dentry, inode, name, NULL, 0);
1601fbad2   Mimi Zohar   xattr: define vfs...
277
278
279
280
281
282
283
284
285
  	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);
  	}
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
286
  	error = handler->get(handler, dentry, inode, name, value, error);
1601fbad2   Mimi Zohar   xattr: define vfs...
287
288
289
  	*xattr_value = value;
  	return error;
  }
424925940   David P. Quigley   VFS/Security: Rew...
290
  ssize_t
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
291
292
293
  __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
  	       void *value, size_t size)
  {
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
294
295
296
297
298
299
  	const struct xattr_handler *handler;
  
  	handler = xattr_resolve_name(inode, &name);
  	if (IS_ERR(handler))
  		return PTR_ERR(handler);
  	if (!handler->get)
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
300
  		return -EOPNOTSUPP;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
301
  	return handler->get(handler, dentry, inode, name, value, size);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
302
303
304
305
  }
  EXPORT_SYMBOL(__vfs_getxattr);
  
  ssize_t
8f0cfa52a   David Howells   xattr: add missin...
306
  vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
307
308
309
  {
  	struct inode *inode = dentry->d_inode;
  	int error;
e0ad7b073   Andrew Morton   [PATCH] move xatt...
310
311
312
  	error = xattr_permission(inode, name, MAY_READ);
  	if (error)
  		return error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
313
314
315
  	error = security_inode_getxattr(dentry, name);
  	if (error)
  		return error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
316
  	if (!strncmp(name, XATTR_SECURITY_PREFIX,
e0ad7b073   Andrew Morton   [PATCH] move xatt...
317
318
  				XATTR_SECURITY_PREFIX_LEN)) {
  		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
424925940   David P. Quigley   VFS/Security: Rew...
319
  		int ret = xattr_getsecurity(inode, suffix, value, size);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
320
321
322
323
  		/*
  		 * Only overwrite the return value if a security module
  		 * is actually active.
  		 */
4bea58053   David P. Quigley   VFS: Reorder vfs_...
324
325
326
  		if (ret == -EOPNOTSUPP)
  			goto nolsm;
  		return ret;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
327
  	}
4bea58053   David P. Quigley   VFS: Reorder vfs_...
328
  nolsm:
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
329
  	return __vfs_getxattr(dentry, inode, name, value, size);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
330
331
  }
  EXPORT_SYMBOL_GPL(vfs_getxattr);
659564c8a   Bill Nottingham   [PATCH] Introduce...
332
  ssize_t
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
333
  vfs_listxattr(struct dentry *dentry, char *list, size_t size)
659564c8a   Bill Nottingham   [PATCH] Introduce...
334
  {
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
335
  	struct inode *inode = d_inode(dentry);
659564c8a   Bill Nottingham   [PATCH] Introduce...
336
  	ssize_t error;
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
337
  	error = security_inode_listxattr(dentry);
659564c8a   Bill Nottingham   [PATCH] Introduce...
338
339
  	if (error)
  		return error;
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
340
341
342
  	if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) {
  		error = -EOPNOTSUPP;
  		error = inode->i_op->listxattr(dentry, list, size);
659564c8a   Bill Nottingham   [PATCH] Introduce...
343
  	} else {
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
344
  		error = security_inode_listsecurity(inode, list, size);
659564c8a   Bill Nottingham   [PATCH] Introduce...
345
346
347
348
349
350
  		if (size && error > size)
  			error = -ERANGE;
  	}
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_listxattr);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
351
  int
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
352
  __vfs_removexattr(struct dentry *dentry, const char *name)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
353
  {
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
354
355
  	struct inode *inode = d_inode(dentry);
  	const struct xattr_handler *handler;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
356

6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
357
358
359
360
  	handler = xattr_resolve_name(inode, &name);
  	if (IS_ERR(handler))
  		return PTR_ERR(handler);
  	if (!handler->set)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
361
  		return -EOPNOTSUPP;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
362
  	return handler->set(handler, dentry, inode, name, NULL, 0, XATTR_REPLACE);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
363
364
365
366
367
368
369
370
  }
  EXPORT_SYMBOL(__vfs_removexattr);
  
  int
  vfs_removexattr(struct dentry *dentry, const char *name)
  {
  	struct inode *inode = dentry->d_inode;
  	int error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
371

e0ad7b073   Andrew Morton   [PATCH] move xatt...
372
373
374
  	error = xattr_permission(inode, name, MAY_WRITE);
  	if (error)
  		return error;
5955102c9   Al Viro   wrappers for ->i_...
375
  	inode_lock(inode);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
376
  	error = security_inode_removexattr(dentry, name);
7c51bb00c   Dmitry Kasatkin   evm: fix potentia...
377
378
  	if (error)
  		goto out;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
379

5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
380
  	error = __vfs_removexattr(dentry, name);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
381

c7b87de23   Mimi Zohar   evm: evm_inode_po...
382
  	if (!error) {
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
383
  		fsnotify_xattr(dentry);
c7b87de23   Mimi Zohar   evm: evm_inode_po...
384
385
  		evm_inode_post_removexattr(dentry, name);
  	}
7c51bb00c   Dmitry Kasatkin   evm: fix potentia...
386
387
  
  out:
5955102c9   Al Viro   wrappers for ->i_...
388
  	inode_unlock(inode);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
389
390
391
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_removexattr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
393
394
395
  /*
   * Extended attribute SET operations
   */
  static long
8f0cfa52a   David Howells   xattr: add missin...
396
  setxattr(struct dentry *d, const char __user *name, const void __user *value,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
  	 size_t size, int flags)
  {
  	int error;
  	void *kvalue = NULL;
  	char kname[XATTR_NAME_MAX + 1];
  
  	if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
  		return -EINVAL;
  
  	error = strncpy_from_user(kname, name, sizeof(kname));
  	if (error == 0 || error == sizeof(kname))
  		error = -ERANGE;
  	if (error < 0)
  		return error;
  
  	if (size) {
  		if (size > XATTR_SIZE_MAX)
  			return -E2BIG;
752ade68c   Michal Hocko   treewide: use kv[...
415
416
417
  		kvalue = kvmalloc(size, GFP_KERNEL);
  		if (!kvalue)
  			return -ENOMEM;
44c824982   Andrew Morton   fs/xattr.c:setxat...
418
419
420
421
  		if (copy_from_user(kvalue, value, size)) {
  			error = -EFAULT;
  			goto out;
  		}
2f6f0654a   Eric W. Biederman   userns: Convert v...
422
423
424
  		if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
  		    (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
  			posix_acl_fix_xattr_from_user(kvalue, size);
8db6c34f1   Serge E. Hallyn   Introduce v3 name...
425
426
427
428
429
430
  		else if (strcmp(kname, XATTR_NAME_CAPS) == 0) {
  			error = cap_convert_nscap(d, &kvalue, size);
  			if (error < 0)
  				goto out;
  			size = error;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
  	}
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
432
  	error = vfs_setxattr(d, kname, kvalue, size, flags);
44c824982   Andrew Morton   fs/xattr.c:setxat...
433
  out:
0b2a6f231   Richard Weinberger   fs: xattr: Use kv...
434
  	kvfree(kvalue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
436
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
437
438
439
  static int path_setxattr(const char __user *pathname,
  			 const char __user *name, const void __user *value,
  			 size_t size, int flags, unsigned int lookup_flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
441
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
  	int error;
68f1bb8bb   Jeff Layton   vfs: allow setxat...
443
444
  retry:
  	error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
446
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
447
  	error = mnt_want_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
448
  	if (!error) {
2d8f30380   Al Viro   [PATCH] sanitize ...
449
450
  		error = setxattr(path.dentry, name, value, size, flags);
  		mnt_drop_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
451
  	}
2d8f30380   Al Viro   [PATCH] sanitize ...
452
  	path_put(&path);
68f1bb8bb   Jeff Layton   vfs: allow setxat...
453
454
455
456
  	if (retry_estale(error, lookup_flags)) {
  		lookup_flags |= LOOKUP_REVAL;
  		goto retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
458
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
459
460
461
462
463
464
  SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
  		const char __user *, name, const void __user *, value,
  		size_t, size, int, flags)
  {
  	return path_setxattr(pathname, name, value, size, flags, LOOKUP_FOLLOW);
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
465
466
467
  SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname,
  		const char __user *, name, const void __user *, value,
  		size_t, size, int, flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
  {
8cc431165   Eric Biggers   vfs: Deduplicate ...
469
  	return path_setxattr(pathname, name, value, size, flags, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
471
472
  SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
  		const void __user *,value, size_t, size, int, flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
  {
2903ff019   Al Viro   switch simple cas...
474
  	struct fd f = fdget(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
  	int error = -EBADF;
2903ff019   Al Viro   switch simple cas...
476
  	if (!f.file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
  		return error;
9f45f5bf3   Al Viro   new helper: audit...
478
  	audit_file(f.file);
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
479
  	error = mnt_want_write_file_path(f.file);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
480
  	if (!error) {
9f45f5bf3   Al Viro   new helper: audit...
481
  		error = setxattr(f.file->f_path.dentry, name, value, size, flags);
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
482
  		mnt_drop_write_file_path(f.file);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
483
  	}
2903ff019   Al Viro   switch simple cas...
484
  	fdput(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
486
487
488
489
490
491
  	return error;
  }
  
  /*
   * Extended attribute GET operations
   */
  static ssize_t
8f0cfa52a   David Howells   xattr: add missin...
492
493
  getxattr(struct dentry *d, const char __user *name, void __user *value,
  	 size_t size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
495
496
497
498
499
500
501
502
503
504
505
506
507
  {
  	ssize_t error;
  	void *kvalue = NULL;
  	char kname[XATTR_NAME_MAX + 1];
  
  	error = strncpy_from_user(kname, name, sizeof(kname));
  	if (error == 0 || error == sizeof(kname))
  		error = -ERANGE;
  	if (error < 0)
  		return error;
  
  	if (size) {
  		if (size > XATTR_SIZE_MAX)
  			size = XATTR_SIZE_MAX;
752ade68c   Michal Hocko   treewide: use kv[...
508
509
510
  		kvalue = kvzalloc(size, GFP_KERNEL);
  		if (!kvalue)
  			return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
  	}
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
512
  	error = vfs_getxattr(d, kname, kvalue, size);
f549d6c18   Stephen Smalley   [PATCH] Generic V...
513
  	if (error > 0) {
2f6f0654a   Eric W. Biederman   userns: Convert v...
514
515
  		if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
  		    (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
ff0791f46   Christian Brauner   getxattr: use cor...
516
  			posix_acl_fix_xattr_to_user(kvalue, error);
f549d6c18   Stephen Smalley   [PATCH] Generic V...
517
518
519
520
521
522
  		if (size && copy_to_user(value, kvalue, error))
  			error = -EFAULT;
  	} else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
  		/* The file system tried to returned a value bigger
  		   than XATTR_SIZE_MAX bytes. Not possible. */
  		error = -E2BIG;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
  	}
0b2a6f231   Richard Weinberger   fs: xattr: Use kv...
524
525
  
  	kvfree(kvalue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
527
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
528
529
530
  static ssize_t path_getxattr(const char __user *pathname,
  			     const char __user *name, void __user *value,
  			     size_t size, unsigned int lookup_flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
532
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
  	ssize_t error;
60e66b48c   Jeff Layton   vfs: make getxatt...
534
535
  retry:
  	error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
537
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
538
539
  	error = getxattr(path.dentry, name, value, size);
  	path_put(&path);
60e66b48c   Jeff Layton   vfs: make getxatt...
540
541
542
543
  	if (retry_estale(error, lookup_flags)) {
  		lookup_flags |= LOOKUP_REVAL;
  		goto retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
545
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
546
547
548
549
550
  SYSCALL_DEFINE4(getxattr, const char __user *, pathname,
  		const char __user *, name, void __user *, value, size_t, size)
  {
  	return path_getxattr(pathname, name, value, size, LOOKUP_FOLLOW);
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
551
552
  SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname,
  		const char __user *, name, void __user *, value, size_t, size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
553
  {
8cc431165   Eric Biggers   vfs: Deduplicate ...
554
  	return path_getxattr(pathname, name, value, size, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
556
557
  SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
  		void __user *, value, size_t, size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
  {
2903ff019   Al Viro   switch simple cas...
559
  	struct fd f = fdget(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
560
  	ssize_t error = -EBADF;
2903ff019   Al Viro   switch simple cas...
561
  	if (!f.file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
  		return error;
9f45f5bf3   Al Viro   new helper: audit...
563
  	audit_file(f.file);
2903ff019   Al Viro   switch simple cas...
564
565
  	error = getxattr(f.file->f_path.dentry, name, value, size);
  	fdput(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
  	return error;
  }
  
  /*
   * Extended attribute LIST operations
   */
  static ssize_t
  listxattr(struct dentry *d, char __user *list, size_t size)
  {
  	ssize_t error;
  	char *klist = NULL;
  
  	if (size) {
  		if (size > XATTR_LIST_MAX)
  			size = XATTR_LIST_MAX;
752ade68c   Michal Hocko   treewide: use kv[...
581
582
583
  		klist = kvmalloc(size, GFP_KERNEL);
  		if (!klist)
  			return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
  	}
659564c8a   Bill Nottingham   [PATCH] Introduce...
585
  	error = vfs_listxattr(d, klist, size);
f549d6c18   Stephen Smalley   [PATCH] Generic V...
586
587
588
589
590
591
592
  	if (error > 0) {
  		if (size && copy_to_user(list, klist, error))
  			error = -EFAULT;
  	} else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
  		/* The file system tried to returned a list bigger
  		   than XATTR_LIST_MAX bytes. Not possible. */
  		error = -E2BIG;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
  	}
0b2a6f231   Richard Weinberger   fs: xattr: Use kv...
594
595
  
  	kvfree(klist);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
597
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
598
599
  static ssize_t path_listxattr(const char __user *pathname, char __user *list,
  			      size_t size, unsigned int lookup_flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
601
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
602
  	ssize_t error;
10a90cf36   Jeff Layton   vfs: make listxat...
603
604
  retry:
  	error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
606
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
607
608
  	error = listxattr(path.dentry, list, size);
  	path_put(&path);
10a90cf36   Jeff Layton   vfs: make listxat...
609
610
611
612
  	if (retry_estale(error, lookup_flags)) {
  		lookup_flags |= LOOKUP_REVAL;
  		goto retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
614
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
615
616
617
618
619
  SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list,
  		size_t, size)
  {
  	return path_listxattr(pathname, list, size, LOOKUP_FOLLOW);
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
620
621
  SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list,
  		size_t, size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
  {
8cc431165   Eric Biggers   vfs: Deduplicate ...
623
  	return path_listxattr(pathname, list, size, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
624
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
625
  SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
  {
2903ff019   Al Viro   switch simple cas...
627
  	struct fd f = fdget(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
628
  	ssize_t error = -EBADF;
2903ff019   Al Viro   switch simple cas...
629
  	if (!f.file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
  		return error;
9f45f5bf3   Al Viro   new helper: audit...
631
  	audit_file(f.file);
2903ff019   Al Viro   switch simple cas...
632
633
  	error = listxattr(f.file->f_path.dentry, list, size);
  	fdput(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
635
636
637
638
639
640
  	return error;
  }
  
  /*
   * Extended attribute REMOVE operations
   */
  static long
8f0cfa52a   David Howells   xattr: add missin...
641
  removexattr(struct dentry *d, const char __user *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
643
644
645
646
647
648
649
650
  {
  	int error;
  	char kname[XATTR_NAME_MAX + 1];
  
  	error = strncpy_from_user(kname, name, sizeof(kname));
  	if (error == 0 || error == sizeof(kname))
  		error = -ERANGE;
  	if (error < 0)
  		return error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
651
  	return vfs_removexattr(d, kname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
653
654
  static int path_removexattr(const char __user *pathname,
  			    const char __user *name, unsigned int lookup_flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
656
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
  	int error;
12f062129   Jeff Layton   vfs: make removex...
658
659
  retry:
  	error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
660
661
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
662
  	error = mnt_want_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
663
  	if (!error) {
2d8f30380   Al Viro   [PATCH] sanitize ...
664
665
  		error = removexattr(path.dentry, name);
  		mnt_drop_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
666
  	}
2d8f30380   Al Viro   [PATCH] sanitize ...
667
  	path_put(&path);
12f062129   Jeff Layton   vfs: make removex...
668
669
670
671
  	if (retry_estale(error, lookup_flags)) {
  		lookup_flags |= LOOKUP_REVAL;
  		goto retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
673
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
674
675
676
677
678
  SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
  		const char __user *, name)
  {
  	return path_removexattr(pathname, name, LOOKUP_FOLLOW);
  }
6a6160a7b   Heiko Carstens   [CVE-2009-0029] S...
679
680
  SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
  		const char __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
  {
8cc431165   Eric Biggers   vfs: Deduplicate ...
682
  	return path_removexattr(pathname, name, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683
  }
6a6160a7b   Heiko Carstens   [CVE-2009-0029] S...
684
  SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
  {
2903ff019   Al Viro   switch simple cas...
686
  	struct fd f = fdget(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
  	int error = -EBADF;
2903ff019   Al Viro   switch simple cas...
688
  	if (!f.file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
689
  		return error;
9f45f5bf3   Al Viro   new helper: audit...
690
  	audit_file(f.file);
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
691
  	error = mnt_want_write_file_path(f.file);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
692
  	if (!error) {
9f45f5bf3   Al Viro   new helper: audit...
693
  		error = removexattr(f.file->f_path.dentry, name);
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
694
  		mnt_drop_write_file_path(f.file);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
695
  	}
2903ff019   Al Viro   switch simple cas...
696
  	fdput(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697
698
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
701
702
703
704
705
   * Combine the results of the list() operation from every xattr_handler in the
   * list.
   */
  ssize_t
  generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
  {
bb4354538   Stephen Hemminger   fs: xattr_handler...
706
  	const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707
708
709
  	unsigned int size = 0;
  
  	if (!buffer) {
431547b3c   Christoph Hellwig   sanitize xattr ha...
710
  		for_each_xattr_handler(handlers, handler) {
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
711
712
  			if (!handler->name ||
  			    (handler->list && !handler->list(dentry)))
c4803c497   Andreas Gruenbacher   nfs: Move call to...
713
  				continue;
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
714
  			size += strlen(handler->name) + 1;
431547b3c   Christoph Hellwig   sanitize xattr ha...
715
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
717
  	} else {
  		char *buf = buffer;
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
718
  		size_t len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
720
  
  		for_each_xattr_handler(handlers, handler) {
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
721
722
  			if (!handler->name ||
  			    (handler->list && !handler->list(dentry)))
c4803c497   Andreas Gruenbacher   nfs: Move call to...
723
  				continue;
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
724
725
  			len = strlen(handler->name);
  			if (len + 1 > buffer_size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
  				return -ERANGE;
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
727
728
729
  			memcpy(buf, handler->name, len + 1);
  			buf += len + 1;
  			buffer_size -= len + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730
731
732
733
734
  		}
  		size = buf - buffer;
  	}
  	return size;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735
  EXPORT_SYMBOL(generic_listxattr);
38f386574   Aristeu Rozanski   xattr: extract si...
736

e409de992   Andreas Gruenbacher   9p: xattr simplif...
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
  /**
   * xattr_full_name  -  Compute full attribute name from suffix
   *
   * @handler:	handler of the xattr_handler operation
   * @name:	name passed to the xattr_handler operation
   *
   * The get and set xattr handler operations are called with the remainder of
   * the attribute name after skipping the handler's prefix: for example, "foo"
   * is passed to the get operation of a handler with prefix "user." to get
   * attribute "user.foo".  The full name is still "there" in the name though.
   *
   * Note: the list xattr handler operation when called from the vfs is passed a
   * NULL name; some file systems use this operation internally, with varying
   * semantics.
   */
  const char *xattr_full_name(const struct xattr_handler *handler,
  			    const char *name)
  {
98e9cb571   Andreas Gruenbacher   vfs: Distinguish ...
755
  	size_t prefix_len = strlen(xattr_prefix(handler));
e409de992   Andreas Gruenbacher   9p: xattr simplif...
756
757
758
759
  
  	return name - prefix_len;
  }
  EXPORT_SYMBOL(xattr_full_name);
38f386574   Aristeu Rozanski   xattr: extract si...
760
761
762
763
764
765
766
767
768
769
  /*
   * Allocate new xattr and copy in the value; but leave the name to callers.
   */
  struct simple_xattr *simple_xattr_alloc(const void *value, size_t size)
  {
  	struct simple_xattr *new_xattr;
  	size_t len;
  
  	/* wrap around? */
  	len = sizeof(*new_xattr) + size;
4e66d445d   Hugh Dickins   simple_xattr: per...
770
  	if (len < sizeof(*new_xattr))
38f386574   Aristeu Rozanski   xattr: extract si...
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
  		return NULL;
  
  	new_xattr = kmalloc(len, GFP_KERNEL);
  	if (!new_xattr)
  		return NULL;
  
  	new_xattr->size = size;
  	memcpy(new_xattr->value, value, size);
  	return new_xattr;
  }
  
  /*
   * xattr GET operation for in-memory/pseudo filesystems
   */
  int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
  		     void *buffer, size_t size)
  {
  	struct simple_xattr *xattr;
  	int ret = -ENODATA;
  
  	spin_lock(&xattrs->lock);
  	list_for_each_entry(xattr, &xattrs->head, list) {
  		if (strcmp(name, xattr->name))
  			continue;
  
  		ret = xattr->size;
  		if (buffer) {
  			if (size < xattr->size)
  				ret = -ERANGE;
  			else
  				memcpy(buffer, xattr->value, xattr->size);
  		}
  		break;
  	}
  	spin_unlock(&xattrs->lock);
  	return ret;
  }
aa7c5241c   Andreas Gruenbacher   tmpfs: Use xattr ...
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
  /**
   * simple_xattr_set - xattr SET operation for in-memory/pseudo filesystems
   * @xattrs: target simple_xattr list
   * @name: name of the extended attribute
   * @value: value of the xattr. If %NULL, will remove the attribute.
   * @size: size of the new xattr
   * @flags: %XATTR_{CREATE|REPLACE}
   *
   * %XATTR_CREATE is set, the xattr shouldn't exist already; otherwise fails
   * with -EEXIST.  If %XATTR_REPLACE is set, the xattr should exist;
   * otherwise, fails with -ENODATA.
   *
   * Returns 0 on success, -errno on failure.
   */
  int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
  		     const void *value, size_t size, int flags)
38f386574   Aristeu Rozanski   xattr: extract si...
824
825
  {
  	struct simple_xattr *xattr;
433858469   David Rientjes   fs, xattr: fix bu...
826
  	struct simple_xattr *new_xattr = NULL;
38f386574   Aristeu Rozanski   xattr: extract si...
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
  	int err = 0;
  
  	/* value == NULL means remove */
  	if (value) {
  		new_xattr = simple_xattr_alloc(value, size);
  		if (!new_xattr)
  			return -ENOMEM;
  
  		new_xattr->name = kstrdup(name, GFP_KERNEL);
  		if (!new_xattr->name) {
  			kfree(new_xattr);
  			return -ENOMEM;
  		}
  	}
  
  	spin_lock(&xattrs->lock);
  	list_for_each_entry(xattr, &xattrs->head, list) {
  		if (!strcmp(name, xattr->name)) {
  			if (flags & XATTR_CREATE) {
  				xattr = new_xattr;
  				err = -EEXIST;
  			} else if (new_xattr) {
  				list_replace(&xattr->list, &new_xattr->list);
  			} else {
  				list_del(&xattr->list);
  			}
  			goto out;
  		}
  	}
  	if (flags & XATTR_REPLACE) {
  		xattr = new_xattr;
  		err = -ENODATA;
  	} else {
  		list_add(&new_xattr->list, &xattrs->head);
  		xattr = NULL;
  	}
  out:
  	spin_unlock(&xattrs->lock);
  	if (xattr) {
  		kfree(xattr->name);
  		kfree(xattr);
  	}
  	return err;
  
  }
38f386574   Aristeu Rozanski   xattr: extract si...
872
873
874
875
  static bool xattr_is_trusted(const char *name)
  {
  	return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
  }
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
876
877
878
879
880
881
882
883
884
885
886
887
888
  static int xattr_list_one(char **buffer, ssize_t *remaining_size,
  			  const char *name)
  {
  	size_t len = strlen(name) + 1;
  	if (*buffer) {
  		if (*remaining_size < len)
  			return -ERANGE;
  		memcpy(*buffer, name, len);
  		*buffer += len;
  	}
  	*remaining_size -= len;
  	return 0;
  }
38f386574   Aristeu Rozanski   xattr: extract si...
889
890
891
  /*
   * xattr LIST operation for in-memory/pseudo filesystems
   */
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
892
893
  ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
  			  char *buffer, size_t size)
38f386574   Aristeu Rozanski   xattr: extract si...
894
895
896
  {
  	bool trusted = capable(CAP_SYS_ADMIN);
  	struct simple_xattr *xattr;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
897
  	ssize_t remaining_size = size;
0e9a7da51   Mateusz Guzik   xattr handlers: p...
898
  	int err = 0;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
899
900
  
  #ifdef CONFIG_FS_POSIX_ACL
b420b7b79   Andreas Gruenbacher   sysfs: Do not ret...
901
902
903
904
905
906
907
908
909
910
911
912
913
  	if (IS_POSIXACL(inode)) {
  		if (inode->i_acl) {
  			err = xattr_list_one(&buffer, &remaining_size,
  					     XATTR_NAME_POSIX_ACL_ACCESS);
  			if (err)
  				return err;
  		}
  		if (inode->i_default_acl) {
  			err = xattr_list_one(&buffer, &remaining_size,
  					     XATTR_NAME_POSIX_ACL_DEFAULT);
  			if (err)
  				return err;
  		}
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
914
915
  	}
  #endif
38f386574   Aristeu Rozanski   xattr: extract si...
916
917
918
  
  	spin_lock(&xattrs->lock);
  	list_for_each_entry(xattr, &xattrs->head, list) {
38f386574   Aristeu Rozanski   xattr: extract si...
919
920
921
  		/* skip "trusted." attributes for unprivileged callers */
  		if (!trusted && xattr_is_trusted(xattr->name))
  			continue;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
922
923
  		err = xattr_list_one(&buffer, &remaining_size, xattr->name);
  		if (err)
0e9a7da51   Mateusz Guzik   xattr handlers: p...
924
  			break;
38f386574   Aristeu Rozanski   xattr: extract si...
925
926
  	}
  	spin_unlock(&xattrs->lock);
0e9a7da51   Mateusz Guzik   xattr handlers: p...
927
  	return err ? err : size - remaining_size;
38f386574   Aristeu Rozanski   xattr: extract si...
928
  }
4895768b6   Aristeu Rozanski   fs: add missing d...
929
930
931
  /*
   * Adds an extended attribute to the list
   */
38f386574   Aristeu Rozanski   xattr: extract si...
932
933
934
935
936
937
938
  void simple_xattr_list_add(struct simple_xattrs *xattrs,
  			   struct simple_xattr *new_xattr)
  {
  	spin_lock(&xattrs->lock);
  	list_add(&new_xattr->list, &xattrs->head);
  	spin_unlock(&xattrs->lock);
  }