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

0d08d7b7e   Andrew Morton   fs/xattr.c:listxa...
25
  #include <asm/uaccess.h>
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
26

b6ba11773   Andreas Gruenbacher   vfs: Move xattr_r...
27
28
29
30
31
32
33
34
35
36
37
38
  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...
39
40
41
   * 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...
42
43
44
45
46
47
48
49
50
51
52
   */
  #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...
53
  xattr_resolve_name(struct inode *inode, const char **name)
b6ba11773   Andreas Gruenbacher   vfs: Move xattr_r...
54
  {
d0a5b995a   Andreas Gruenbacher   vfs: Add IOP_XATT...
55
  	const struct xattr_handler **handlers = inode->i_sb->s_xattr;
b6ba11773   Andreas Gruenbacher   vfs: Move xattr_r...
56
  	const struct xattr_handler *handler;
5f6e59ae8   Andreas Gruenbacher   vfs: Use IOP_XATT...
57
58
59
  	if (!(inode->i_opflags & IOP_XATTR)) {
  		if (unlikely(is_bad_inode(inode)))
  			return ERR_PTR(-EIO);
d0a5b995a   Andreas Gruenbacher   vfs: Add IOP_XATT...
60
  		return ERR_PTR(-EOPNOTSUPP);
5f6e59ae8   Andreas Gruenbacher   vfs: Use IOP_XATT...
61
  	}
b6ba11773   Andreas Gruenbacher   vfs: Move xattr_r...
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  	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...
78
79
80
81
82
83
84
85
86
87
88
89
  /*
   * 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...
90
91
  		if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  			return -EPERM;
0bd23d09b   Eric W. Biederman   vfs: Don't modify...
92
93
94
95
96
97
98
  		/*
  		 * 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...
99
100
101
102
103
104
105
106
107
108
109
  	}
  
  	/*
  	 * 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 ...
110
  	 * The trusted.* namespace can only be accessed by privileged users.
e0ad7b073   Andrew Morton   [PATCH] move xatt...
111
  	 */
55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
112
113
114
115
116
  	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...
117

55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
118
119
  	/*
  	 * In the user.* namespace, only regular files and directories can have
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
120
  	 * extended attributes. For sticky directories, only the owner and
55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
121
  	 * privileged users can write attributes.
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
122
  	 */
e0ad7b073   Andrew Morton   [PATCH] move xatt...
123
  	if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
124
  		if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
125
  			return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
126
  		if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
2e1496707   Serge E. Hallyn   userns: rename is...
127
  		    (mask & MAY_WRITE) && !inode_owner_or_capable(inode))
e0ad7b073   Andrew Morton   [PATCH] move xatt...
128
129
  			return -EPERM;
  	}
f419a2e3b   Al Viro   [PATCH] kill name...
130
  	return inode_permission(inode, mask);
e0ad7b073   Andrew Morton   [PATCH] move xatt...
131
  }
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
132
133
134
135
  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...
136
137
138
139
140
141
  	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_...
142
  		return -EOPNOTSUPP;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
143
144
145
  	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_...
146
147
  }
  EXPORT_SYMBOL(__vfs_setxattr);
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  /**
   *  __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_*...
166
167
  {
  	struct inode *inode = dentry->d_inode;
4a5901537   Andreas Gruenbacher   xattr: Fix settin...
168
  	int error = -EAGAIN;
69b457329   Andi Kleen   Cache xattr secur...
169
170
  	int issec = !strncmp(name, XATTR_SECURITY_PREFIX,
  				   XATTR_SECURITY_PREFIX_LEN);
e0ad7b073   Andrew Morton   [PATCH] move xatt...
171

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

6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
356
357
358
359
  	handler = xattr_resolve_name(inode, &name);
  	if (IS_ERR(handler))
  		return PTR_ERR(handler);
  	if (!handler->set)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
360
  		return -EOPNOTSUPP;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
361
  	return handler->set(handler, dentry, inode, name, NULL, 0, XATTR_REPLACE);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
362
363
364
365
366
367
368
369
  }
  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_*...
370

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

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

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

e409de992   Andreas Gruenbacher   9p: xattr simplif...
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
  /**
   * 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 ...
757
  	size_t prefix_len = strlen(xattr_prefix(handler));
e409de992   Andreas Gruenbacher   9p: xattr simplif...
758
759
760
761
  
  	return name - prefix_len;
  }
  EXPORT_SYMBOL(xattr_full_name);
38f386574   Aristeu Rozanski   xattr: extract si...
762
763
764
765
766
767
768
769
770
771
  /*
   * 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...
772
  	if (len < sizeof(*new_xattr))
38f386574   Aristeu Rozanski   xattr: extract si...
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
808
809
  		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 ...
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
  /**
   * 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...
826
827
  {
  	struct simple_xattr *xattr;
433858469   David Rientjes   fs, xattr: fix bu...
828
  	struct simple_xattr *new_xattr = NULL;
38f386574   Aristeu Rozanski   xattr: extract si...
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
872
873
  	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...
874
875
876
877
  static bool xattr_is_trusted(const char *name)
  {
  	return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
  }
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
878
879
880
881
882
883
884
885
886
887
888
889
890
  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...
891
892
893
  /*
   * xattr LIST operation for in-memory/pseudo filesystems
   */
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
894
895
  ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
  			  char *buffer, size_t size)
38f386574   Aristeu Rozanski   xattr: extract si...
896
897
898
  {
  	bool trusted = capable(CAP_SYS_ADMIN);
  	struct simple_xattr *xattr;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
899
  	ssize_t remaining_size = size;
0e9a7da51   Mateusz Guzik   xattr handlers: p...
900
  	int err = 0;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
  
  #ifdef CONFIG_FS_POSIX_ACL
  	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;
  	}
  #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);
  }