Blame view

fs/xattr.c 23.5 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
201
202
203
204
205
206
207
208
209
210
211
212
  
  	return error;
  }
  
  
  int
  vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
  		size_t size, int flags)
  {
  	struct inode *inode = dentry->d_inode;
  	int error;
  
  	error = xattr_permission(inode, name, MAY_WRITE);
  	if (error)
  		return error;
5955102c9   Al Viro   wrappers for ->i_...
213
  	inode_lock(inode);
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
214
215
216
217
218
  	error = security_inode_setxattr(dentry, name, value, size, flags);
  	if (error)
  		goto out;
  
  	error = __vfs_setxattr_noperm(dentry, name, value, size, flags);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
219
  out:
5955102c9   Al Viro   wrappers for ->i_...
220
  	inode_unlock(inode);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
221
222
223
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_setxattr);
2220c5b0a   Al Viro   make xattr_getsec...
224
  static 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
  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...
245
  	kfree(buffer);
424925940   David P. Quigley   VFS/Security: Rew...
246
247
248
  out_noalloc:
  	return len;
  }
424925940   David P. Quigley   VFS/Security: Rew...
249

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
  	if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) {
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
340
  		error = inode->i_op->listxattr(dentry, list, size);
659564c8a   Bill Nottingham   [PATCH] Introduce...
341
  	} else {
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
342
  		error = security_inode_listsecurity(inode, list, size);
659564c8a   Bill Nottingham   [PATCH] Introduce...
343
344
345
346
347
348
  		if (size && error > size)
  			error = -ERANGE;
  	}
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_listxattr);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
349
  int
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
350
  __vfs_removexattr(struct dentry *dentry, const char *name)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
351
  {
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
352
353
  	struct inode *inode = d_inode(dentry);
  	const struct xattr_handler *handler;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
354

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

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

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

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

e409de992   Andreas Gruenbacher   9p: xattr simplif...
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
  /**
   * 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 ...
753
  	size_t prefix_len = strlen(xattr_prefix(handler));
e409de992   Andreas Gruenbacher   9p: xattr simplif...
754
755
756
757
  
  	return name - prefix_len;
  }
  EXPORT_SYMBOL(xattr_full_name);
38f386574   Aristeu Rozanski   xattr: extract si...
758
759
760
761
762
763
764
765
766
767
  /*
   * 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...
768
  	if (len < sizeof(*new_xattr))
38f386574   Aristeu Rozanski   xattr: extract si...
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
  		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 ...
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
  /**
   * 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...
822
823
  {
  	struct simple_xattr *xattr;
433858469   David Rientjes   fs, xattr: fix bu...
824
  	struct simple_xattr *new_xattr = NULL;
38f386574   Aristeu Rozanski   xattr: extract si...
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
  	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...
870
871
872
873
  static bool xattr_is_trusted(const char *name)
  {
  	return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
  }
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
874
875
876
877
878
879
880
881
882
883
884
885
886
  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...
887
888
889
  /*
   * xattr LIST operation for in-memory/pseudo filesystems
   */
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
890
891
  ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
  			  char *buffer, size_t size)
38f386574   Aristeu Rozanski   xattr: extract si...
892
893
894
  {
  	bool trusted = capable(CAP_SYS_ADMIN);
  	struct simple_xattr *xattr;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
895
  	ssize_t remaining_size = size;
0e9a7da51   Mateusz Guzik   xattr handlers: p...
896
  	int err = 0;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
897
898
  
  #ifdef CONFIG_FS_POSIX_ACL
ffc4c9222   Andreas Gruenbacher   sysfs: Do not ret...
899
900
901
902
903
904
905
906
907
908
909
910
911
  	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 ...
912
913
  	}
  #endif
38f386574   Aristeu Rozanski   xattr: extract si...
914
915
916
  
  	spin_lock(&xattrs->lock);
  	list_for_each_entry(xattr, &xattrs->head, list) {
38f386574   Aristeu Rozanski   xattr: extract si...
917
918
919
  		/* skip "trusted." attributes for unprivileged callers */
  		if (!trusted && xattr_is_trusted(xattr->name))
  			continue;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
920
921
  		err = xattr_list_one(&buffer, &remaining_size, xattr->name);
  		if (err)
0e9a7da51   Mateusz Guzik   xattr handlers: p...
922
  			break;
38f386574   Aristeu Rozanski   xattr: extract si...
923
924
  	}
  	spin_unlock(&xattrs->lock);
0e9a7da51   Mateusz Guzik   xattr handlers: p...
925
  	return err ? err : size - remaining_size;
38f386574   Aristeu Rozanski   xattr: extract si...
926
  }
4895768b6   Aristeu Rozanski   fs: add missing d...
927
928
929
  /*
   * Adds an extended attribute to the list
   */
38f386574   Aristeu Rozanski   xattr: extract si...
930
931
932
933
934
935
936
  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);
  }