Blame view

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

7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
25
  #include <linux/uaccess.h>
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
26

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

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

69b457329   Andi Kleen   Cache xattr secur...
172
173
  	if (issec)
  		inode->i_flags &= ~S_NOSEC;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
174
  	if (inode->i_opflags & IOP_XATTR) {
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
175
  		error = __vfs_setxattr(dentry, inode, name, value, size, flags);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
176
177
178
179
180
  		if (!error) {
  			fsnotify_xattr(dentry);
  			security_inode_post_setxattr(dentry, name, value,
  						     size, flags);
  		}
4a5901537   Andreas Gruenbacher   xattr: Fix settin...
181
  	} else {
5f6e59ae8   Andreas Gruenbacher   vfs: Use IOP_XATT...
182
183
  		if (unlikely(is_bad_inode(inode)))
  			return -EIO;
4a5901537   Andreas Gruenbacher   xattr: Fix settin...
184
185
186
187
188
189
190
191
192
193
194
195
  	}
  	if (error == -EAGAIN) {
  		error = -EOPNOTSUPP;
  
  		if (issec) {
  			const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
  
  			error = security_inode_setsecurity(inode, suffix, value,
  							   size, flags);
  			if (!error)
  				fsnotify_xattr(dentry);
  		}
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
196
  	}
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  
  	return error;
  }
  
  
  int
  vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
  		size_t size, int flags)
  {
  	struct inode *inode = dentry->d_inode;
  	int error;
  
  	error = xattr_permission(inode, name, MAY_WRITE);
  	if (error)
  		return error;
5955102c9   Al Viro   wrappers for ->i_...
212
  	inode_lock(inode);
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
213
214
215
216
217
  	error = security_inode_setxattr(dentry, name, value, size, flags);
  	if (error)
  		goto out;
  
  	error = __vfs_setxattr_noperm(dentry, name, value, size, flags);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
218
  out:
5955102c9   Al Viro   wrappers for ->i_...
219
  	inode_unlock(inode);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
220
221
222
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_setxattr);
2220c5b0a   Al Viro   make xattr_getsec...
223
  static ssize_t
424925940   David P. Quigley   VFS/Security: Rew...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  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...
244
  	kfree(buffer);
424925940   David P. Quigley   VFS/Security: Rew...
245
246
247
  out_noalloc:
  	return len;
  }
424925940   David P. Quigley   VFS/Security: Rew...
248

1601fbad2   Mimi Zohar   xattr: define vfs...
249
250
251
252
253
254
255
256
257
258
259
260
  /*
   * 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...
261
  	const struct xattr_handler *handler;
1601fbad2   Mimi Zohar   xattr: define vfs...
262
263
264
265
266
267
268
  	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...
269
270
271
272
  	handler = xattr_resolve_name(inode, &name);
  	if (IS_ERR(handler))
  		return PTR_ERR(handler);
  	if (!handler->get)
1601fbad2   Mimi Zohar   xattr: define vfs...
273
  		return -EOPNOTSUPP;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
274
  	error = handler->get(handler, dentry, inode, name, NULL, 0);
1601fbad2   Mimi Zohar   xattr: define vfs...
275
276
277
278
279
280
281
282
283
  	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...
284
  	error = handler->get(handler, dentry, inode, name, value, error);
1601fbad2   Mimi Zohar   xattr: define vfs...
285
286
287
  	*xattr_value = value;
  	return error;
  }
424925940   David P. Quigley   VFS/Security: Rew...
288
  ssize_t
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
289
290
291
  __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
  	       void *value, size_t size)
  {
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
292
293
294
295
296
297
  	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_...
298
  		return -EOPNOTSUPP;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
299
  	return handler->get(handler, dentry, inode, name, value, size);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
300
301
302
303
  }
  EXPORT_SYMBOL(__vfs_getxattr);
  
  ssize_t
8f0cfa52a   David Howells   xattr: add missin...
304
  vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
305
306
307
  {
  	struct inode *inode = dentry->d_inode;
  	int error;
e0ad7b073   Andrew Morton   [PATCH] move xatt...
308
309
310
  	error = xattr_permission(inode, name, MAY_READ);
  	if (error)
  		return error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
311
312
313
  	error = security_inode_getxattr(dentry, name);
  	if (error)
  		return error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
314
  	if (!strncmp(name, XATTR_SECURITY_PREFIX,
e0ad7b073   Andrew Morton   [PATCH] move xatt...
315
316
  				XATTR_SECURITY_PREFIX_LEN)) {
  		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
424925940   David P. Quigley   VFS/Security: Rew...
317
  		int ret = xattr_getsecurity(inode, suffix, value, size);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
318
319
320
321
  		/*
  		 * Only overwrite the return value if a security module
  		 * is actually active.
  		 */
4bea58053   David P. Quigley   VFS: Reorder vfs_...
322
323
324
  		if (ret == -EOPNOTSUPP)
  			goto nolsm;
  		return ret;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
325
  	}
4bea58053   David P. Quigley   VFS: Reorder vfs_...
326
  nolsm:
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
327
  	return __vfs_getxattr(dentry, inode, name, value, size);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
328
329
  }
  EXPORT_SYMBOL_GPL(vfs_getxattr);
659564c8a   Bill Nottingham   [PATCH] Introduce...
330
  ssize_t
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
331
  vfs_listxattr(struct dentry *dentry, char *list, size_t size)
659564c8a   Bill Nottingham   [PATCH] Introduce...
332
  {
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
333
  	struct inode *inode = d_inode(dentry);
659564c8a   Bill Nottingham   [PATCH] Introduce...
334
  	ssize_t error;
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
335
  	error = security_inode_listxattr(dentry);
659564c8a   Bill Nottingham   [PATCH] Introduce...
336
337
  	if (error)
  		return error;
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
338
  	if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) {
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
339
  		error = inode->i_op->listxattr(dentry, list, size);
659564c8a   Bill Nottingham   [PATCH] Introduce...
340
  	} else {
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
341
  		error = security_inode_listsecurity(inode, list, size);
659564c8a   Bill Nottingham   [PATCH] Introduce...
342
343
344
345
346
347
  		if (size && error > size)
  			error = -ERANGE;
  	}
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_listxattr);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
348
  int
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
349
  __vfs_removexattr(struct dentry *dentry, const char *name)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
350
  {
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
351
352
  	struct inode *inode = d_inode(dentry);
  	const struct xattr_handler *handler;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
353

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

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

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

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

e409de992   Andreas Gruenbacher   9p: xattr simplif...
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
  /**
   * 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 ...
752
  	size_t prefix_len = strlen(xattr_prefix(handler));
e409de992   Andreas Gruenbacher   9p: xattr simplif...
753
754
755
756
  
  	return name - prefix_len;
  }
  EXPORT_SYMBOL(xattr_full_name);
38f386574   Aristeu Rozanski   xattr: extract si...
757
758
759
760
761
762
763
764
765
766
  /*
   * 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...
767
  	if (len < sizeof(*new_xattr))
38f386574   Aristeu Rozanski   xattr: extract si...
768
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
  		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 ...
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
  /**
   * 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...
821
822
  {
  	struct simple_xattr *xattr;
433858469   David Rientjes   fs, xattr: fix bu...
823
  	struct simple_xattr *new_xattr = NULL;
38f386574   Aristeu Rozanski   xattr: extract si...
824
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
  	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...
869
870
871
872
  static bool xattr_is_trusted(const char *name)
  {
  	return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
  }
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
873
874
875
876
877
878
879
880
881
882
883
884
885
  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...
886
887
888
  /*
   * xattr LIST operation for in-memory/pseudo filesystems
   */
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
889
890
  ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
  			  char *buffer, size_t size)
38f386574   Aristeu Rozanski   xattr: extract si...
891
892
893
  {
  	bool trusted = capable(CAP_SYS_ADMIN);
  	struct simple_xattr *xattr;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
894
  	ssize_t remaining_size = size;
0e9a7da51   Mateusz Guzik   xattr handlers: p...
895
  	int err = 0;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
896
897
  
  #ifdef CONFIG_FS_POSIX_ACL
ffc4c9222   Andreas Gruenbacher   sysfs: Do not ret...
898
899
900
901
902
903
904
905
906
907
908
909
910
  	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 ...
911
912
  	}
  #endif
38f386574   Aristeu Rozanski   xattr: extract si...
913
914
915
  
  	spin_lock(&xattrs->lock);
  	list_for_each_entry(xattr, &xattrs->head, list) {
38f386574   Aristeu Rozanski   xattr: extract si...
916
917
918
  		/* skip "trusted." attributes for unprivileged callers */
  		if (!trusted && xattr_is_trusted(xattr->name))
  			continue;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
919
920
  		err = xattr_list_one(&buffer, &remaining_size, xattr->name);
  		if (err)
0e9a7da51   Mateusz Guzik   xattr handlers: p...
921
  			break;
38f386574   Aristeu Rozanski   xattr: extract si...
922
923
  	}
  	spin_unlock(&xattrs->lock);
0e9a7da51   Mateusz Guzik   xattr handlers: p...
924
  	return err ? err : size - remaining_size;
38f386574   Aristeu Rozanski   xattr: extract si...
925
  }
4895768b6   Aristeu Rozanski   fs: add missing d...
926
927
928
  /*
   * Adds an extended attribute to the list
   */
38f386574   Aristeu Rozanski   xattr: extract si...
929
930
931
932
933
934
935
  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);
  }