Blame view

fs/xattr.c 25.2 KB
457c89965   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
9
10
11
12
  /*
    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
13
14
  #include <linux/file.h>
  #include <linux/xattr.h>
18f335aff   Dave Hansen   [PATCH] r/o bind ...
15
  #include <linux/mount.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
  #include <linux/namei.h>
  #include <linux/security.h>
c7b87de23   Mimi Zohar   evm: evm_inode_po...
18
  #include <linux/evm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
  #include <linux/syscalls.h>
630d9c472   Paul Gortmaker   fs: reduce the us...
20
  #include <linux/export.h>
0eeca2830   Robert Love   [PATCH] inotify
21
  #include <linux/fsnotify.h>
73241ccca   Amy Griffis   [PATCH] Collect m...
22
  #include <linux/audit.h>
0d08d7b7e   Andrew Morton   fs/xattr.c:listxa...
23
  #include <linux/vmalloc.h>
2f6f0654a   Eric W. Biederman   userns: Convert v...
24
  #include <linux/posix_acl_xattr.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25

7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
26
  #include <linux/uaccess.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
  
  	return error;
  }
11e64146d   Frank van der Linden   xattr: break dele...
201
202
203
204
205
206
207
208
209
210
211
212
  /**
   * __vfs_setxattr_locked: set an extended attribute while holding the inode
   * lock
   *
   *  @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
   *  @delegated_inode - on return, will contain an inode pointer that
   *  a delegation was broken on, NULL if none.
   */
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
213
  int
11e64146d   Frank van der Linden   xattr: break dele...
214
215
216
  __vfs_setxattr_locked(struct dentry *dentry, const char *name,
  		const void *value, size_t size, int flags,
  		struct inode **delegated_inode)
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
217
218
219
220
221
222
223
  {
  	struct inode *inode = dentry->d_inode;
  	int error;
  
  	error = xattr_permission(inode, name, MAY_WRITE);
  	if (error)
  		return error;
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
224
225
226
  	error = security_inode_setxattr(dentry, name, value, size, flags);
  	if (error)
  		goto out;
11e64146d   Frank van der Linden   xattr: break dele...
227
228
229
  	error = try_break_deleg(inode, delegated_inode);
  	if (error)
  		goto out;
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
230
  	error = __vfs_setxattr_noperm(dentry, name, value, size, flags);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
231
  out:
11e64146d   Frank van der Linden   xattr: break dele...
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
  	return error;
  }
  EXPORT_SYMBOL_GPL(__vfs_setxattr_locked);
  
  int
  vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
  		size_t size, int flags)
  {
  	struct inode *inode = dentry->d_inode;
  	struct inode *delegated_inode = NULL;
  	int error;
  
  retry_deleg:
  	inode_lock(inode);
  	error = __vfs_setxattr_locked(dentry, name, value, size, flags,
  	    &delegated_inode);
5955102c9   Al Viro   wrappers for ->i_...
248
  	inode_unlock(inode);
11e64146d   Frank van der Linden   xattr: break dele...
249
250
251
252
253
254
  
  	if (delegated_inode) {
  		error = break_deleg_wait(&delegated_inode);
  		if (!error)
  			goto retry_deleg;
  	}
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
255
256
257
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_setxattr);
2220c5b0a   Al Viro   make xattr_getsec...
258
  static ssize_t
424925940   David P. Quigley   VFS/Security: Rew...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
  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...
279
  	kfree(buffer);
424925940   David P. Quigley   VFS/Security: Rew...
280
281
282
  out_noalloc:
  	return len;
  }
424925940   David P. Quigley   VFS/Security: Rew...
283

1601fbad2   Mimi Zohar   xattr: define vfs...
284
285
286
287
288
289
290
291
292
293
294
295
  /*
   * 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...
296
  	const struct xattr_handler *handler;
1601fbad2   Mimi Zohar   xattr: define vfs...
297
298
299
300
301
302
303
  	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...
304
305
306
307
  	handler = xattr_resolve_name(inode, &name);
  	if (IS_ERR(handler))
  		return PTR_ERR(handler);
  	if (!handler->get)
1601fbad2   Mimi Zohar   xattr: define vfs...
308
  		return -EOPNOTSUPP;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
309
  	error = handler->get(handler, dentry, inode, name, NULL, 0);
1601fbad2   Mimi Zohar   xattr: define vfs...
310
311
312
313
314
315
316
317
318
  	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...
319
  	error = handler->get(handler, dentry, inode, name, value, error);
1601fbad2   Mimi Zohar   xattr: define vfs...
320
321
322
  	*xattr_value = value;
  	return error;
  }
424925940   David P. Quigley   VFS/Security: Rew...
323
  ssize_t
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
324
325
326
  __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
  	       void *value, size_t size)
  {
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
327
328
329
330
331
332
  	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_...
333
  		return -EOPNOTSUPP;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
334
  	return handler->get(handler, dentry, inode, name, value, size);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
335
336
337
338
  }
  EXPORT_SYMBOL(__vfs_getxattr);
  
  ssize_t
8f0cfa52a   David Howells   xattr: add missin...
339
  vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
340
341
342
  {
  	struct inode *inode = dentry->d_inode;
  	int error;
e0ad7b073   Andrew Morton   [PATCH] move xatt...
343
344
345
  	error = xattr_permission(inode, name, MAY_READ);
  	if (error)
  		return error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
346
347
348
  	error = security_inode_getxattr(dentry, name);
  	if (error)
  		return error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
349
  	if (!strncmp(name, XATTR_SECURITY_PREFIX,
e0ad7b073   Andrew Morton   [PATCH] move xatt...
350
351
  				XATTR_SECURITY_PREFIX_LEN)) {
  		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
424925940   David P. Quigley   VFS/Security: Rew...
352
  		int ret = xattr_getsecurity(inode, suffix, value, size);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
353
354
355
356
  		/*
  		 * Only overwrite the return value if a security module
  		 * is actually active.
  		 */
4bea58053   David P. Quigley   VFS: Reorder vfs_...
357
358
359
  		if (ret == -EOPNOTSUPP)
  			goto nolsm;
  		return ret;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
360
  	}
4bea58053   David P. Quigley   VFS: Reorder vfs_...
361
  nolsm:
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
362
  	return __vfs_getxattr(dentry, inode, name, value, size);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
363
364
  }
  EXPORT_SYMBOL_GPL(vfs_getxattr);
659564c8a   Bill Nottingham   [PATCH] Introduce...
365
  ssize_t
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
366
  vfs_listxattr(struct dentry *dentry, char *list, size_t size)
659564c8a   Bill Nottingham   [PATCH] Introduce...
367
  {
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
368
  	struct inode *inode = d_inode(dentry);
659564c8a   Bill Nottingham   [PATCH] Introduce...
369
  	ssize_t error;
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
370
  	error = security_inode_listxattr(dentry);
659564c8a   Bill Nottingham   [PATCH] Introduce...
371
372
  	if (error)
  		return error;
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
373
  	if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) {
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
374
  		error = inode->i_op->listxattr(dentry, list, size);
659564c8a   Bill Nottingham   [PATCH] Introduce...
375
  	} else {
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
376
  		error = security_inode_listsecurity(inode, list, size);
659564c8a   Bill Nottingham   [PATCH] Introduce...
377
378
379
380
381
382
  		if (size && error > size)
  			error = -ERANGE;
  	}
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_listxattr);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
383
  int
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
384
  __vfs_removexattr(struct dentry *dentry, const char *name)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
385
  {
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
386
387
  	struct inode *inode = d_inode(dentry);
  	const struct xattr_handler *handler;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
388

6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
389
390
391
392
  	handler = xattr_resolve_name(inode, &name);
  	if (IS_ERR(handler))
  		return PTR_ERR(handler);
  	if (!handler->set)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
393
  		return -EOPNOTSUPP;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
394
  	return handler->set(handler, dentry, inode, name, NULL, 0, XATTR_REPLACE);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
395
396
  }
  EXPORT_SYMBOL(__vfs_removexattr);
11e64146d   Frank van der Linden   xattr: break dele...
397
398
399
400
401
402
403
404
405
  /**
   * __vfs_removexattr_locked: set an extended attribute while holding the inode
   * lock
   *
   *  @dentry - object to perform setxattr on
   *  @name - name of xattr to remove
   *  @delegated_inode - on return, will contain an inode pointer that
   *  a delegation was broken on, NULL if none.
   */
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
406
  int
11e64146d   Frank van der Linden   xattr: break dele...
407
408
  __vfs_removexattr_locked(struct dentry *dentry, const char *name,
  		struct inode **delegated_inode)
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
409
410
411
  {
  	struct inode *inode = dentry->d_inode;
  	int error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
412

e0ad7b073   Andrew Morton   [PATCH] move xatt...
413
414
415
  	error = xattr_permission(inode, name, MAY_WRITE);
  	if (error)
  		return error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
416
  	error = security_inode_removexattr(dentry, name);
7c51bb00c   Dmitry Kasatkin   evm: fix potentia...
417
418
  	if (error)
  		goto out;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
419

11e64146d   Frank van der Linden   xattr: break dele...
420
421
422
  	error = try_break_deleg(inode, delegated_inode);
  	if (error)
  		goto out;
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
423
  	error = __vfs_removexattr(dentry, name);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
424

c7b87de23   Mimi Zohar   evm: evm_inode_po...
425
  	if (!error) {
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
426
  		fsnotify_xattr(dentry);
c7b87de23   Mimi Zohar   evm: evm_inode_po...
427
428
  		evm_inode_post_removexattr(dentry, name);
  	}
7c51bb00c   Dmitry Kasatkin   evm: fix potentia...
429
430
  
  out:
11e64146d   Frank van der Linden   xattr: break dele...
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  	return error;
  }
  EXPORT_SYMBOL_GPL(__vfs_removexattr_locked);
  
  int
  vfs_removexattr(struct dentry *dentry, const char *name)
  {
  	struct inode *inode = dentry->d_inode;
  	struct inode *delegated_inode = NULL;
  	int error;
  
  retry_deleg:
  	inode_lock(inode);
  	error = __vfs_removexattr_locked(dentry, name, &delegated_inode);
5955102c9   Al Viro   wrappers for ->i_...
445
  	inode_unlock(inode);
11e64146d   Frank van der Linden   xattr: break dele...
446
447
448
449
450
451
  
  	if (delegated_inode) {
  		error = break_deleg_wait(&delegated_inode);
  		if (!error)
  			goto retry_deleg;
  	}
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
452
453
454
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_removexattr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
456
457
458
  /*
   * Extended attribute SET operations
   */
  static long
8f0cfa52a   David Howells   xattr: add missin...
459
  setxattr(struct dentry *d, const char __user *name, const void __user *value,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
  	 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[...
478
479
480
  		kvalue = kvmalloc(size, GFP_KERNEL);
  		if (!kvalue)
  			return -ENOMEM;
44c824982   Andrew Morton   fs/xattr.c:setxat...
481
482
483
484
  		if (copy_from_user(kvalue, value, size)) {
  			error = -EFAULT;
  			goto out;
  		}
2f6f0654a   Eric W. Biederman   userns: Convert v...
485
486
487
  		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...
488
489
490
491
492
493
  		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
494
  	}
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
495
  	error = vfs_setxattr(d, kname, kvalue, size, flags);
44c824982   Andrew Morton   fs/xattr.c:setxat...
496
  out:
0b2a6f231   Richard Weinberger   fs: xattr: Use kv...
497
  	kvfree(kvalue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
499
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
500
501
502
  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
503
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
504
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
  	int error;
68f1bb8bb   Jeff Layton   vfs: allow setxat...
506
507
  retry:
  	error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
509
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
510
  	error = mnt_want_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
511
  	if (!error) {
2d8f30380   Al Viro   [PATCH] sanitize ...
512
513
  		error = setxattr(path.dentry, name, value, size, flags);
  		mnt_drop_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
514
  	}
2d8f30380   Al Viro   [PATCH] sanitize ...
515
  	path_put(&path);
68f1bb8bb   Jeff Layton   vfs: allow setxat...
516
517
518
519
  	if (retry_estale(error, lookup_flags)) {
  		lookup_flags |= LOOKUP_REVAL;
  		goto retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
521
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
522
523
524
525
526
527
  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...
528
529
530
  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
531
  {
8cc431165   Eric Biggers   vfs: Deduplicate ...
532
  	return path_setxattr(pathname, name, value, size, flags, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
534
535
  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
536
  {
2903ff019   Al Viro   switch simple cas...
537
  	struct fd f = fdget(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
  	int error = -EBADF;
2903ff019   Al Viro   switch simple cas...
539
  	if (!f.file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
  		return error;
9f45f5bf3   Al Viro   new helper: audit...
541
  	audit_file(f.file);
6742cee04   Miklos Szeredi   Revert "ovl: don'...
542
  	error = mnt_want_write_file(f.file);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
543
  	if (!error) {
9f45f5bf3   Al Viro   new helper: audit...
544
  		error = setxattr(f.file->f_path.dentry, name, value, size, flags);
6742cee04   Miklos Szeredi   Revert "ovl: don'...
545
  		mnt_drop_write_file(f.file);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
546
  	}
2903ff019   Al Viro   switch simple cas...
547
  	fdput(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548
549
550
551
552
553
554
  	return error;
  }
  
  /*
   * Extended attribute GET operations
   */
  static ssize_t
8f0cfa52a   David Howells   xattr: add missin...
555
556
  getxattr(struct dentry *d, const char __user *name, void __user *value,
  	 size_t size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
558
559
560
561
562
563
564
565
566
567
568
569
570
  {
  	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[...
571
572
573
  		kvalue = kvzalloc(size, GFP_KERNEL);
  		if (!kvalue)
  			return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
  	}
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
575
  	error = vfs_getxattr(d, kname, kvalue, size);
f549d6c18   Stephen Smalley   [PATCH] Generic V...
576
  	if (error > 0) {
2f6f0654a   Eric W. Biederman   userns: Convert v...
577
578
  		if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
  		    (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
82c9a927b   Christian Brauner   getxattr: use cor...
579
  			posix_acl_fix_xattr_to_user(kvalue, error);
f549d6c18   Stephen Smalley   [PATCH] Generic V...
580
581
582
583
584
585
  		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
586
  	}
0b2a6f231   Richard Weinberger   fs: xattr: Use kv...
587
588
  
  	kvfree(kvalue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
590
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
591
592
593
  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
594
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
595
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
  	ssize_t error;
60e66b48c   Jeff Layton   vfs: make getxatt...
597
598
  retry:
  	error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
600
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
601
602
  	error = getxattr(path.dentry, name, value, size);
  	path_put(&path);
60e66b48c   Jeff Layton   vfs: make getxatt...
603
604
605
606
  	if (retry_estale(error, lookup_flags)) {
  		lookup_flags |= LOOKUP_REVAL;
  		goto retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
607
608
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
609
610
611
612
613
  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...
614
615
  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
616
  {
8cc431165   Eric Biggers   vfs: Deduplicate ...
617
  	return path_getxattr(pathname, name, value, size, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
619
620
  SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
  		void __user *, value, size_t, size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
621
  {
2903ff019   Al Viro   switch simple cas...
622
  	struct fd f = fdget(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
  	ssize_t error = -EBADF;
2903ff019   Al Viro   switch simple cas...
624
  	if (!f.file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
  		return error;
9f45f5bf3   Al Viro   new helper: audit...
626
  	audit_file(f.file);
2903ff019   Al Viro   switch simple cas...
627
628
  	error = getxattr(f.file->f_path.dentry, name, value, size);
  	fdput(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
  	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[...
644
645
646
  		klist = kvmalloc(size, GFP_KERNEL);
  		if (!klist)
  			return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
  	}
659564c8a   Bill Nottingham   [PATCH] Introduce...
648
  	error = vfs_listxattr(d, klist, size);
f549d6c18   Stephen Smalley   [PATCH] Generic V...
649
650
651
652
653
654
655
  	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
656
  	}
0b2a6f231   Richard Weinberger   fs: xattr: Use kv...
657
658
  
  	kvfree(klist);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
661
662
  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
663
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
664
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
  	ssize_t error;
10a90cf36   Jeff Layton   vfs: make listxat...
666
667
  retry:
  	error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
669
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
670
671
  	error = listxattr(path.dentry, list, size);
  	path_put(&path);
10a90cf36   Jeff Layton   vfs: make listxat...
672
673
674
675
  	if (retry_estale(error, lookup_flags)) {
  		lookup_flags |= LOOKUP_REVAL;
  		goto retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
677
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
678
679
680
681
682
  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...
683
684
  SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list,
  		size_t, size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
  {
8cc431165   Eric Biggers   vfs: Deduplicate ...
686
  	return path_listxattr(pathname, list, size, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
688
  SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
689
  {
2903ff019   Al Viro   switch simple cas...
690
  	struct fd f = fdget(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
  	ssize_t error = -EBADF;
2903ff019   Al Viro   switch simple cas...
692
  	if (!f.file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
  		return error;
9f45f5bf3   Al Viro   new helper: audit...
694
  	audit_file(f.file);
2903ff019   Al Viro   switch simple cas...
695
696
  	error = listxattr(f.file->f_path.dentry, list, size);
  	fdput(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697
698
699
700
701
702
703
  	return error;
  }
  
  /*
   * Extended attribute REMOVE operations
   */
  static long
8f0cfa52a   David Howells   xattr: add missin...
704
  removexattr(struct dentry *d, const char __user *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
706
707
708
709
710
711
712
713
  {
  	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_*...
714
  	return vfs_removexattr(d, kname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
716
717
  static int path_removexattr(const char __user *pathname,
  			    const char __user *name, unsigned int lookup_flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
718
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
719
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
  	int error;
12f062129   Jeff Layton   vfs: make removex...
721
722
  retry:
  	error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723
724
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
725
  	error = mnt_want_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
726
  	if (!error) {
2d8f30380   Al Viro   [PATCH] sanitize ...
727
728
  		error = removexattr(path.dentry, name);
  		mnt_drop_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
729
  	}
2d8f30380   Al Viro   [PATCH] sanitize ...
730
  	path_put(&path);
12f062129   Jeff Layton   vfs: make removex...
731
732
733
734
  	if (retry_estale(error, lookup_flags)) {
  		lookup_flags |= LOOKUP_REVAL;
  		goto retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735
736
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
737
738
739
740
741
  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...
742
743
  SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
  		const char __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
  {
8cc431165   Eric Biggers   vfs: Deduplicate ...
745
  	return path_removexattr(pathname, name, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
  }
6a6160a7b   Heiko Carstens   [CVE-2009-0029] S...
747
  SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
  {
2903ff019   Al Viro   switch simple cas...
749
  	struct fd f = fdget(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
  	int error = -EBADF;
2903ff019   Al Viro   switch simple cas...
751
  	if (!f.file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
  		return error;
9f45f5bf3   Al Viro   new helper: audit...
753
  	audit_file(f.file);
6742cee04   Miklos Szeredi   Revert "ovl: don'...
754
  	error = mnt_want_write_file(f.file);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
755
  	if (!error) {
9f45f5bf3   Al Viro   new helper: audit...
756
  		error = removexattr(f.file->f_path.dentry, name);
6742cee04   Miklos Szeredi   Revert "ovl: don'...
757
  		mnt_drop_write_file(f.file);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
758
  	}
2903ff019   Al Viro   switch simple cas...
759
  	fdput(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
761
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
764
765
766
767
768
   * 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...
769
  	const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
770
771
772
  	unsigned int size = 0;
  
  	if (!buffer) {
431547b3c   Christoph Hellwig   sanitize xattr ha...
773
  		for_each_xattr_handler(handlers, handler) {
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
774
775
  			if (!handler->name ||
  			    (handler->list && !handler->list(dentry)))
c4803c497   Andreas Gruenbacher   nfs: Move call to...
776
  				continue;
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
777
  			size += strlen(handler->name) + 1;
431547b3c   Christoph Hellwig   sanitize xattr ha...
778
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
780
  	} else {
  		char *buf = buffer;
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
781
  		size_t len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
782
783
  
  		for_each_xattr_handler(handlers, handler) {
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
784
785
  			if (!handler->name ||
  			    (handler->list && !handler->list(dentry)))
c4803c497   Andreas Gruenbacher   nfs: Move call to...
786
  				continue;
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
787
788
  			len = strlen(handler->name);
  			if (len + 1 > buffer_size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
  				return -ERANGE;
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
790
791
792
  			memcpy(buf, handler->name, len + 1);
  			buf += len + 1;
  			buffer_size -= len + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
793
794
795
796
797
  		}
  		size = buf - buffer;
  	}
  	return size;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798
  EXPORT_SYMBOL(generic_listxattr);
38f386574   Aristeu Rozanski   xattr: extract si...
799

e409de992   Andreas Gruenbacher   9p: xattr simplif...
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
  /**
   * 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 ...
818
  	size_t prefix_len = strlen(xattr_prefix(handler));
e409de992   Andreas Gruenbacher   9p: xattr simplif...
819
820
821
822
  
  	return name - prefix_len;
  }
  EXPORT_SYMBOL(xattr_full_name);
38f386574   Aristeu Rozanski   xattr: extract si...
823
824
825
826
827
828
829
830
831
832
  /*
   * 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...
833
  	if (len < sizeof(*new_xattr))
38f386574   Aristeu Rozanski   xattr: extract si...
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
  		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 ...
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
  /**
   * 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...
887
888
  {
  	struct simple_xattr *xattr;
433858469   David Rientjes   fs, xattr: fix bu...
889
  	struct simple_xattr *new_xattr = NULL;
38f386574   Aristeu Rozanski   xattr: extract si...
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
  	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...
935
936
937
938
  static bool xattr_is_trusted(const char *name)
  {
  	return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
  }
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
939
940
941
942
943
944
945
946
947
948
949
950
951
  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...
952
953
954
  /*
   * xattr LIST operation for in-memory/pseudo filesystems
   */
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
955
956
  ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
  			  char *buffer, size_t size)
38f386574   Aristeu Rozanski   xattr: extract si...
957
958
959
  {
  	bool trusted = capable(CAP_SYS_ADMIN);
  	struct simple_xattr *xattr;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
960
  	ssize_t remaining_size = size;
0e9a7da51   Mateusz Guzik   xattr handlers: p...
961
  	int err = 0;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
962
963
  
  #ifdef CONFIG_FS_POSIX_ACL
ffc4c9222   Andreas Gruenbacher   sysfs: Do not ret...
964
965
966
967
968
969
970
971
972
973
974
975
976
  	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 ...
977
978
  	}
  #endif
38f386574   Aristeu Rozanski   xattr: extract si...
979
980
981
  
  	spin_lock(&xattrs->lock);
  	list_for_each_entry(xattr, &xattrs->head, list) {
38f386574   Aristeu Rozanski   xattr: extract si...
982
983
984
  		/* skip "trusted." attributes for unprivileged callers */
  		if (!trusted && xattr_is_trusted(xattr->name))
  			continue;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
985
986
  		err = xattr_list_one(&buffer, &remaining_size, xattr->name);
  		if (err)
0e9a7da51   Mateusz Guzik   xattr handlers: p...
987
  			break;
38f386574   Aristeu Rozanski   xattr: extract si...
988
989
  	}
  	spin_unlock(&xattrs->lock);
0e9a7da51   Mateusz Guzik   xattr handlers: p...
990
  	return err ? err : size - remaining_size;
38f386574   Aristeu Rozanski   xattr: extract si...
991
  }
4895768b6   Aristeu Rozanski   fs: add missing d...
992
993
994
  /*
   * Adds an extended attribute to the list
   */
38f386574   Aristeu Rozanski   xattr: extract si...
995
996
997
998
999
1000
1001
  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);
  }