Blame view

fs/xattr.c 18 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>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23

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

e0ad7b073   Andrew Morton   [PATCH] move xatt...
26
27
28
29
30
31
32
33
34
35
36
37
  /*
   * 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...
38
39
40
41
42
43
44
45
46
47
48
49
50
  		if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  			return -EPERM;
  	}
  
  	/*
  	 * 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 ...
51
  	 * The trusted.* namespace can only be accessed by privileged users.
e0ad7b073   Andrew Morton   [PATCH] move xatt...
52
  	 */
55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
53
54
55
56
57
  	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...
58

55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
59
60
  	/*
  	 * In the user.* namespace, only regular files and directories can have
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
61
  	 * extended attributes. For sticky directories, only the owner and
55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
62
  	 * privileged users can write attributes.
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
63
  	 */
e0ad7b073   Andrew Morton   [PATCH] move xatt...
64
  	if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
65
  		if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
66
  			return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
67
  		if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
2e1496707   Serge E. Hallyn   userns: rename is...
68
  		    (mask & MAY_WRITE) && !inode_owner_or_capable(inode))
e0ad7b073   Andrew Morton   [PATCH] move xatt...
69
70
  			return -EPERM;
  	}
f419a2e3b   Al Viro   [PATCH] kill name...
71
  	return inode_permission(inode, mask);
e0ad7b073   Andrew Morton   [PATCH] move xatt...
72
  }
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
  /**
   *  __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_*...
91
92
  {
  	struct inode *inode = dentry->d_inode;
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
93
  	int error = -EOPNOTSUPP;
69b457329   Andi Kleen   Cache xattr secur...
94
95
  	int issec = !strncmp(name, XATTR_SECURITY_PREFIX,
  				   XATTR_SECURITY_PREFIX_LEN);
e0ad7b073   Andrew Morton   [PATCH] move xatt...
96

69b457329   Andi Kleen   Cache xattr secur...
97
98
  	if (issec)
  		inode->i_flags &= ~S_NOSEC;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
99
100
101
102
103
104
105
  	if (inode->i_op->setxattr) {
  		error = inode->i_op->setxattr(dentry, name, value, size, flags);
  		if (!error) {
  			fsnotify_xattr(dentry);
  			security_inode_post_setxattr(dentry, name, value,
  						     size, flags);
  		}
69b457329   Andi Kleen   Cache xattr secur...
106
  	} else if (issec) {
e0ad7b073   Andrew Morton   [PATCH] move xatt...
107
  		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
108
109
110
111
112
  		error = security_inode_setsecurity(inode, suffix, value,
  						   size, flags);
  		if (!error)
  			fsnotify_xattr(dentry);
  	}
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  
  	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;
  
  	mutex_lock(&inode->i_mutex);
  	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_*...
135
136
137
138
139
140
141
  out:
  	mutex_unlock(&inode->i_mutex);
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_setxattr);
  
  ssize_t
424925940   David P. Quigley   VFS/Security: Rew...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  xattr_getsecurity(struct inode *inode, const char *name, void *value,
  			size_t size)
  {
  	void *buffer = NULL;
  	ssize_t len;
  
  	if (!value || !size) {
  		len = security_inode_getsecurity(inode, name, &buffer, false);
  		goto out_noalloc;
  	}
  
  	len = security_inode_getsecurity(inode, name, &buffer, true);
  	if (len < 0)
  		return len;
  	if (size < len) {
  		len = -ERANGE;
  		goto out;
  	}
  	memcpy(value, buffer, len);
  out:
  	security_release_secctx(buffer, len);
  out_noalloc:
  	return len;
  }
  EXPORT_SYMBOL_GPL(xattr_getsecurity);
1601fbad2   Mimi Zohar   xattr: define vfs...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  /*
   * 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)
  {
  	struct inode *inode = dentry->d_inode;
  	char *value = *xattr_value;
  	int error;
  
  	error = xattr_permission(inode, name, MAY_READ);
  	if (error)
  		return error;
  
  	if (!inode->i_op->getxattr)
  		return -EOPNOTSUPP;
  
  	error = inode->i_op->getxattr(dentry, name, NULL, 0);
  	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);
  	}
  
  	error = inode->i_op->getxattr(dentry, name, value, error);
  	*xattr_value = value;
  	return error;
  }
  
  /* Compare an extended attribute value with the given value */
  int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name,
  		  const char *value, size_t size, gfp_t flags)
  {
  	char *xattr_value = NULL;
  	int rc;
  
  	rc = vfs_getxattr_alloc(dentry, xattr_name, &xattr_value, 0, flags);
  	if (rc < 0)
  		return rc;
  
  	if ((rc != size) || (memcmp(xattr_value, value, rc) != 0))
  		rc = -EINVAL;
  	else
  		rc = 0;
  	kfree(xattr_value);
  	return rc;
  }
424925940   David P. Quigley   VFS/Security: Rew...
224
  ssize_t
8f0cfa52a   David Howells   xattr: add missin...
225
  vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
226
227
228
  {
  	struct inode *inode = dentry->d_inode;
  	int error;
e0ad7b073   Andrew Morton   [PATCH] move xatt...
229
230
231
  	error = xattr_permission(inode, name, MAY_READ);
  	if (error)
  		return error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
232
233
234
  	error = security_inode_getxattr(dentry, name);
  	if (error)
  		return error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
235
  	if (!strncmp(name, XATTR_SECURITY_PREFIX,
e0ad7b073   Andrew Morton   [PATCH] move xatt...
236
237
  				XATTR_SECURITY_PREFIX_LEN)) {
  		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
424925940   David P. Quigley   VFS/Security: Rew...
238
  		int ret = xattr_getsecurity(inode, suffix, value, size);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
239
240
241
242
  		/*
  		 * Only overwrite the return value if a security module
  		 * is actually active.
  		 */
4bea58053   David P. Quigley   VFS: Reorder vfs_...
243
244
245
  		if (ret == -EOPNOTSUPP)
  			goto nolsm;
  		return ret;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
246
  	}
4bea58053   David P. Quigley   VFS: Reorder vfs_...
247
248
249
250
251
  nolsm:
  	if (inode->i_op->getxattr)
  		error = inode->i_op->getxattr(dentry, name, value, size);
  	else
  		error = -EOPNOTSUPP;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
252
253
254
255
  
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_getxattr);
659564c8a   Bill Nottingham   [PATCH] Introduce...
256
257
258
259
260
261
262
263
264
  ssize_t
  vfs_listxattr(struct dentry *d, char *list, size_t size)
  {
  	ssize_t error;
  
  	error = security_inode_listxattr(d);
  	if (error)
  		return error;
  	error = -EOPNOTSUPP;
acfa4380e   Al Viro   inode->i_op is ne...
265
  	if (d->d_inode->i_op->listxattr) {
659564c8a   Bill Nottingham   [PATCH] Introduce...
266
267
268
269
270
271
272
273
274
  		error = d->d_inode->i_op->listxattr(d, list, size);
  	} else {
  		error = security_inode_listsecurity(d->d_inode, list, size);
  		if (size && error > size)
  			error = -ERANGE;
  	}
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_listxattr);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
275
  int
8f0cfa52a   David Howells   xattr: add missin...
276
  vfs_removexattr(struct dentry *dentry, const char *name)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
277
278
279
280
281
282
  {
  	struct inode *inode = dentry->d_inode;
  	int error;
  
  	if (!inode->i_op->removexattr)
  		return -EOPNOTSUPP;
e0ad7b073   Andrew Morton   [PATCH] move xatt...
283
284
285
  	error = xattr_permission(inode, name, MAY_WRITE);
  	if (error)
  		return error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
286
287
288
289
290
291
292
  	error = security_inode_removexattr(dentry, name);
  	if (error)
  		return error;
  
  	mutex_lock(&inode->i_mutex);
  	error = inode->i_op->removexattr(dentry, name);
  	mutex_unlock(&inode->i_mutex);
c7b87de23   Mimi Zohar   evm: evm_inode_po...
293
  	if (!error) {
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
294
  		fsnotify_xattr(dentry);
c7b87de23   Mimi Zohar   evm: evm_inode_po...
295
296
  		evm_inode_post_removexattr(dentry, name);
  	}
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
297
298
299
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_removexattr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
301
302
303
  /*
   * Extended attribute SET operations
   */
  static long
8f0cfa52a   David Howells   xattr: add missin...
304
  setxattr(struct dentry *d, const char __user *name, const void __user *value,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
306
307
308
  	 size_t size, int flags)
  {
  	int error;
  	void *kvalue = NULL;
44c824982   Andrew Morton   fs/xattr.c:setxat...
309
  	void *vvalue = NULL;	/* If non-NULL, we used vmalloc() */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
311
312
313
314
315
316
317
318
319
320
321
322
323
  	char kname[XATTR_NAME_MAX + 1];
  
  	if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
  		return -EINVAL;
  
  	error = strncpy_from_user(kname, name, sizeof(kname));
  	if (error == 0 || error == sizeof(kname))
  		error = -ERANGE;
  	if (error < 0)
  		return error;
  
  	if (size) {
  		if (size > XATTR_SIZE_MAX)
  			return -E2BIG;
44c824982   Andrew Morton   fs/xattr.c:setxat...
324
325
326
327
328
329
330
331
332
333
334
  		kvalue = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
  		if (!kvalue) {
  			vvalue = vmalloc(size);
  			if (!vvalue)
  				return -ENOMEM;
  			kvalue = vvalue;
  		}
  		if (copy_from_user(kvalue, value, size)) {
  			error = -EFAULT;
  			goto out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
  	}
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
336
  	error = vfs_setxattr(d, kname, kvalue, size, flags);
44c824982   Andrew Morton   fs/xattr.c:setxat...
337
338
339
340
341
  out:
  	if (vvalue)
  		vfree(vvalue);
  	else
  		kfree(kvalue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
343
  	return error;
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
344
345
346
  SYSCALL_DEFINE5(setxattr, 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
347
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
348
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
  	int error;
2d8f30380   Al Viro   [PATCH] sanitize ...
350
  	error = user_path(pathname, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
353
  	error = mnt_want_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
354
  	if (!error) {
2d8f30380   Al Viro   [PATCH] sanitize ...
355
356
  		error = setxattr(path.dentry, name, value, size, flags);
  		mnt_drop_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
357
  	}
2d8f30380   Al Viro   [PATCH] sanitize ...
358
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
360
  	return error;
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
361
362
363
  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
364
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
365
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
  	int error;
2d8f30380   Al Viro   [PATCH] sanitize ...
367
  	error = user_lpath(pathname, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
369
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
370
  	error = mnt_want_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
371
  	if (!error) {
2d8f30380   Al Viro   [PATCH] sanitize ...
372
373
  		error = setxattr(path.dentry, name, value, size, flags);
  		mnt_drop_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
374
  	}
2d8f30380   Al Viro   [PATCH] sanitize ...
375
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
377
  	return error;
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
378
379
  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
380
  {
7449af1e8   Al Viro   switch xattr sysc...
381
  	int fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
  	struct file *f;
73241ccca   Amy Griffis   [PATCH] Collect m...
383
  	struct dentry *dentry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
  	int error = -EBADF;
7449af1e8   Al Viro   switch xattr sysc...
385
  	f = fget_light(fd, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
  	if (!f)
  		return error;
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
388
  	dentry = f->f_path.dentry;
5a190ae69   Al Viro   [PATCH] pass dent...
389
  	audit_inode(NULL, dentry);
96029c4e0   npiggin@suse.de   fs: introduce mnt...
390
  	error = mnt_want_write_file(f);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
391
392
  	if (!error) {
  		error = setxattr(dentry, name, value, size, flags);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
393
  		mnt_drop_write_file(f);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
394
  	}
7449af1e8   Al Viro   switch xattr sysc...
395
  	fput_light(f, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
398
399
400
401
402
  	return error;
  }
  
  /*
   * Extended attribute GET operations
   */
  static ssize_t
8f0cfa52a   David Howells   xattr: add missin...
403
404
  getxattr(struct dentry *d, const char __user *name, void __user *value,
  	 size_t size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
406
407
  {
  	ssize_t error;
  	void *kvalue = NULL;
779302e67   Sasha Levin   fs/xattr.c:getxat...
408
  	void *vvalue = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
410
411
412
413
414
415
416
417
418
419
  	char kname[XATTR_NAME_MAX + 1];
  
  	error = strncpy_from_user(kname, name, sizeof(kname));
  	if (error == 0 || error == sizeof(kname))
  		error = -ERANGE;
  	if (error < 0)
  		return error;
  
  	if (size) {
  		if (size > XATTR_SIZE_MAX)
  			size = XATTR_SIZE_MAX;
779302e67   Sasha Levin   fs/xattr.c:getxat...
420
421
422
423
424
425
426
  		kvalue = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
  		if (!kvalue) {
  			vvalue = vmalloc(size);
  			if (!vvalue)
  				return -ENOMEM;
  			kvalue = vvalue;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
  	}
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
428
  	error = vfs_getxattr(d, kname, kvalue, size);
f549d6c18   Stephen Smalley   [PATCH] Generic V...
429
430
431
432
433
434
435
  	if (error > 0) {
  		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
436
  	}
779302e67   Sasha Levin   fs/xattr.c:getxat...
437
438
439
440
  	if (vvalue)
  		vfree(vvalue);
  	else
  		kfree(kvalue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
442
  	return error;
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
443
444
  SYSCALL_DEFINE4(getxattr, const char __user *, pathname,
  		const char __user *, name, void __user *, value, size_t, size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
446
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
  	ssize_t error;
2d8f30380   Al Viro   [PATCH] sanitize ...
448
  	error = user_path(pathname, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
450
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
451
452
  	error = getxattr(path.dentry, name, value, size);
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
  	return error;
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
455
456
  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
457
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
458
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
  	ssize_t error;
2d8f30380   Al Viro   [PATCH] sanitize ...
460
  	error = user_lpath(pathname, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
462
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
463
464
  	error = getxattr(path.dentry, name, value, size);
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
  	return error;
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
467
468
  SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
  		void __user *, value, size_t, size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  {
7449af1e8   Al Viro   switch xattr sysc...
470
  	int fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
471
472
  	struct file *f;
  	ssize_t error = -EBADF;
7449af1e8   Al Viro   switch xattr sysc...
473
  	f = fget_light(fd, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
  	if (!f)
  		return error;
5a190ae69   Al Viro   [PATCH] pass dent...
476
  	audit_inode(NULL, f->f_path.dentry);
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
477
  	error = getxattr(f->f_path.dentry, name, value, size);
7449af1e8   Al Viro   switch xattr sysc...
478
  	fput_light(f, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479
480
481
482
483
484
485
486
487
488
489
  	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;
0d08d7b7e   Andrew Morton   fs/xattr.c:listxa...
490
  	char *vlist = NULL;	/* If non-NULL, we used vmalloc() */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
492
493
494
  
  	if (size) {
  		if (size > XATTR_LIST_MAX)
  			size = XATTR_LIST_MAX;
703bf2d12   Dave Jones   fs/xattr.c: suppr...
495
  		klist = kmalloc(size, __GFP_NOWARN | GFP_KERNEL);
0d08d7b7e   Andrew Morton   fs/xattr.c:listxa...
496
497
498
499
500
501
  		if (!klist) {
  			vlist = vmalloc(size);
  			if (!vlist)
  				return -ENOMEM;
  			klist = vlist;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
  	}
659564c8a   Bill Nottingham   [PATCH] Introduce...
503
  	error = vfs_listxattr(d, klist, size);
f549d6c18   Stephen Smalley   [PATCH] Generic V...
504
505
506
507
508
509
510
  	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
511
  	}
0d08d7b7e   Andrew Morton   fs/xattr.c:listxa...
512
513
514
515
  	if (vlist)
  		vfree(vlist);
  	else
  		kfree(klist);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
  	return error;
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
518
519
  SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list,
  		size_t, size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
521
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
  	ssize_t error;
2d8f30380   Al Viro   [PATCH] sanitize ...
523
  	error = user_path(pathname, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524
525
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
526
527
  	error = listxattr(path.dentry, list, size);
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528
529
  	return error;
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
530
531
  SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list,
  		size_t, size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
533
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
  	ssize_t error;
2d8f30380   Al Viro   [PATCH] sanitize ...
535
  	error = user_lpath(pathname, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
537
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
538
539
  	error = listxattr(path.dentry, list, size);
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
541
  	return error;
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
542
  SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
  {
7449af1e8   Al Viro   switch xattr sysc...
544
  	int fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
546
  	struct file *f;
  	ssize_t error = -EBADF;
7449af1e8   Al Viro   switch xattr sysc...
547
  	f = fget_light(fd, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548
549
  	if (!f)
  		return error;
5a190ae69   Al Viro   [PATCH] pass dent...
550
  	audit_inode(NULL, f->f_path.dentry);
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
551
  	error = listxattr(f->f_path.dentry, list, size);
7449af1e8   Al Viro   switch xattr sysc...
552
  	fput_light(f, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
553
554
555
556
557
558
559
  	return error;
  }
  
  /*
   * Extended attribute REMOVE operations
   */
  static long
8f0cfa52a   David Howells   xattr: add missin...
560
  removexattr(struct dentry *d, const char __user *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
561
562
563
564
565
566
567
568
569
  {
  	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_*...
570
  	return vfs_removexattr(d, kname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
572
573
  SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
  		const char __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
575
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
  	int error;
2d8f30380   Al Viro   [PATCH] sanitize ...
577
  	error = user_path(pathname, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
579
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
580
  	error = mnt_want_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
581
  	if (!error) {
2d8f30380   Al Viro   [PATCH] sanitize ...
582
583
  		error = removexattr(path.dentry, name);
  		mnt_drop_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
584
  	}
2d8f30380   Al Viro   [PATCH] sanitize ...
585
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
587
  	return error;
  }
6a6160a7b   Heiko Carstens   [CVE-2009-0029] S...
588
589
  SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
  		const char __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
591
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
  	int error;
2d8f30380   Al Viro   [PATCH] sanitize ...
593
  	error = user_lpath(pathname, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
595
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
596
  	error = mnt_want_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
597
  	if (!error) {
2d8f30380   Al Viro   [PATCH] sanitize ...
598
599
  		error = removexattr(path.dentry, name);
  		mnt_drop_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
600
  	}
2d8f30380   Al Viro   [PATCH] sanitize ...
601
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
602
603
  	return error;
  }
6a6160a7b   Heiko Carstens   [CVE-2009-0029] S...
604
  SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
  {
7449af1e8   Al Viro   switch xattr sysc...
606
  	int fput_needed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
607
  	struct file *f;
73241ccca   Amy Griffis   [PATCH] Collect m...
608
  	struct dentry *dentry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
  	int error = -EBADF;
7449af1e8   Al Viro   switch xattr sysc...
610
  	f = fget_light(fd, &fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611
612
  	if (!f)
  		return error;
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
613
  	dentry = f->f_path.dentry;
5a190ae69   Al Viro   [PATCH] pass dent...
614
  	audit_inode(NULL, dentry);
96029c4e0   npiggin@suse.de   fs: introduce mnt...
615
  	error = mnt_want_write_file(f);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
616
617
  	if (!error) {
  		error = removexattr(dentry, name);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
618
  		mnt_drop_write_file(f);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
619
  	}
7449af1e8   Al Viro   switch xattr sysc...
620
  	fput_light(f, fput_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
  	return error;
  }
  
  
  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
   * prefix with the generic xattr API, 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.
   *
   * The generic_fooxattr() functions will use this list to dispatch xattr
   * operations to the correct xattr_handler.
   */
  #define for_each_xattr_handler(handlers, handler)		\
  		for ((handler) = *(handlers)++;			\
  			(handler) != NULL;			\
  			(handler) = *(handlers)++)
  
  /*
   * Find the xattr_handler with the matching prefix.
   */
bb4354538   Stephen Hemminger   fs: xattr_handler...
652
653
  static const struct xattr_handler *
  xattr_resolve_name(const struct xattr_handler **handlers, const char **name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
  {
bb4354538   Stephen Hemminger   fs: xattr_handler...
655
  	const struct xattr_handler *handler;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
  
  	if (!*name)
  		return NULL;
  
  	for_each_xattr_handler(handlers, handler) {
  		const char *n = strcmp_prefix(*name, handler->prefix);
  		if (n) {
  			*name = n;
  			break;
  		}
  	}
  	return handler;
  }
  
  /*
   * Find the handler for the prefix and dispatch its get() operation.
   */
  ssize_t
  generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
  {
bb4354538   Stephen Hemminger   fs: xattr_handler...
676
  	const struct xattr_handler *handler;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677

431547b3c   Christoph Hellwig   sanitize xattr ha...
678
  	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
680
  	if (!handler)
  		return -EOPNOTSUPP;
431547b3c   Christoph Hellwig   sanitize xattr ha...
681
  	return handler->get(dentry, name, buffer, size, handler->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
683
684
685
686
687
688
689
690
  }
  
  /*
   * 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...
691
  	const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
693
694
  	unsigned int size = 0;
  
  	if (!buffer) {
431547b3c   Christoph Hellwig   sanitize xattr ha...
695
696
697
698
  		for_each_xattr_handler(handlers, handler) {
  			size += handler->list(dentry, NULL, 0, NULL, 0,
  					      handler->flags);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
700
701
702
  	} else {
  		char *buf = buffer;
  
  		for_each_xattr_handler(handlers, handler) {
431547b3c   Christoph Hellwig   sanitize xattr ha...
703
704
  			size = handler->list(dentry, buf, buffer_size,
  					     NULL, 0, handler->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
  			if (size > buffer_size)
  				return -ERANGE;
  			buf += size;
  			buffer_size -= size;
  		}
  		size = buf - buffer;
  	}
  	return size;
  }
  
  /*
   * Find the handler for the prefix and dispatch its set() operation.
   */
  int
  generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
  {
bb4354538   Stephen Hemminger   fs: xattr_handler...
721
  	const struct xattr_handler *handler;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
723
724
  
  	if (size == 0)
  		value = "";  /* empty EA, do not remove */
431547b3c   Christoph Hellwig   sanitize xattr ha...
725
  	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
727
  	if (!handler)
  		return -EOPNOTSUPP;
df7e13038   Jan Kara   vfs: Pass setxatt...
728
  	return handler->set(dentry, name, value, size, flags, handler->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
729
730
731
732
733
734
735
736
737
  }
  
  /*
   * Find the handler for the prefix and dispatch its set() operation to remove
   * any associated extended attribute.
   */
  int
  generic_removexattr(struct dentry *dentry, const char *name)
  {
bb4354538   Stephen Hemminger   fs: xattr_handler...
738
  	const struct xattr_handler *handler;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739

431547b3c   Christoph Hellwig   sanitize xattr ha...
740
  	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
742
  	if (!handler)
  		return -EOPNOTSUPP;
431547b3c   Christoph Hellwig   sanitize xattr ha...
743
744
  	return handler->set(dentry, name, NULL, 0,
  			    XATTR_REPLACE, handler->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
746
747
748
749
750
  }
  
  EXPORT_SYMBOL(generic_getxattr);
  EXPORT_SYMBOL(generic_listxattr);
  EXPORT_SYMBOL(generic_setxattr);
  EXPORT_SYMBOL(generic_removexattr);