Blame view

fs/xattr.c 27.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
  /*
   * Check permissions for extended attribute access.  This is a bit complicated
   * because different namespaces have very different rules.
   */
  static int
c7c7a1a18   Tycho Andersen   xattr: handle idm...
84
85
  xattr_permission(struct user_namespace *mnt_userns, struct inode *inode,
  		 const char *name, int mask)
e0ad7b073   Andrew Morton   [PATCH] move xatt...
86
87
88
89
90
91
  {
  	/*
  	 * 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...
92
93
  		if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  			return -EPERM;
0bd23d09b   Eric W. Biederman   vfs: Don't modify...
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.
  		 */
ba73d9874   Christian Brauner   namei: handle idm...
99
  		if (HAS_UNMAPPED_ID(mnt_userns, inode))
0bd23d09b   Eric W. Biederman   vfs: Don't modify...
100
  			return -EPERM;
e0ad7b073   Andrew Morton   [PATCH] move xatt...
101
102
103
104
105
106
107
108
109
110
111
  	}
  
  	/*
  	 * 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 ...
112
  	 * The trusted.* namespace can only be accessed by privileged users.
e0ad7b073   Andrew Morton   [PATCH] move xatt...
113
  	 */
55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
114
115
116
117
118
  	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...
119

55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
120
121
  	/*
  	 * In the user.* namespace, only regular files and directories can have
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
122
  	 * extended attributes. For sticky directories, only the owner and
55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
123
  	 * privileged users can write attributes.
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
124
  	 */
e0ad7b073   Andrew Morton   [PATCH] move xatt...
125
  	if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
126
  		if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
55b23bde1   Andreas Gruenbacher   xattr: Fix error ...
127
  			return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
f1f2d8713   Andreas Gruenbacher   [PATCH] Fix user....
128
  		if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
21cb47be6   Christian Brauner   inode: make init ...
129
  		    (mask & MAY_WRITE) &&
c7c7a1a18   Tycho Andersen   xattr: handle idm...
130
  		    !inode_owner_or_capable(mnt_userns, inode))
e0ad7b073   Andrew Morton   [PATCH] move xatt...
131
132
  			return -EPERM;
  	}
c7c7a1a18   Tycho Andersen   xattr: handle idm...
133
  	return inode_permission(mnt_userns, inode, mask);
e0ad7b073   Andrew Morton   [PATCH] move xatt...
134
  }
cab8d289c   Frank van der Linden   xattr: add a func...
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  /*
   * Look for any handler that deals with the specified namespace.
   */
  int
  xattr_supported_namespace(struct inode *inode, const char *prefix)
  {
  	const struct xattr_handler **handlers = inode->i_sb->s_xattr;
  	const struct xattr_handler *handler;
  	size_t preflen;
  
  	if (!(inode->i_opflags & IOP_XATTR)) {
  		if (unlikely(is_bad_inode(inode)))
  			return -EIO;
  		return -EOPNOTSUPP;
  	}
  
  	preflen = strlen(prefix);
  
  	for_each_xattr_handler(handlers, handler) {
  		if (!strncmp(xattr_prefix(handler), prefix, preflen))
  			return 0;
  	}
  
  	return -EOPNOTSUPP;
  }
  EXPORT_SYMBOL(xattr_supported_namespace);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
161
  int
c7c7a1a18   Tycho Andersen   xattr: handle idm...
162
163
164
  __vfs_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry,
  	       struct inode *inode, const char *name, const void *value,
  	       size_t size, int flags)
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
165
  {
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
166
167
168
169
170
171
  	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_...
172
  		return -EOPNOTSUPP;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
173
174
  	if (size == 0)
  		value = "";  /* empty EA, do not remove */
c7c7a1a18   Tycho Andersen   xattr: handle idm...
175
  	return handler->set(handler, mnt_userns, dentry, inode, name, value,
e65ce2a50   Christian Brauner   acl: handle idmap...
176
  			    size, flags);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
177
178
  }
  EXPORT_SYMBOL(__vfs_setxattr);
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
179
180
181
182
  /**
   *  __vfs_setxattr_noperm - perform setxattr operation without performing
   *  permission checks.
   *
6961fed42   Randy Dunlap   xattr: fix kernel...
183
184
185
186
187
188
   *  @mnt_userns: user namespace of the mount the inode was found from
   *  @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
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
189
190
191
192
193
194
195
   *
   *  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.
   */
c7c7a1a18   Tycho Andersen   xattr: handle idm...
196
197
198
  int __vfs_setxattr_noperm(struct user_namespace *mnt_userns,
  			  struct dentry *dentry, const char *name,
  			  const void *value, size_t size, int flags)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
199
200
  {
  	struct inode *inode = dentry->d_inode;
4a5901537   Andreas Gruenbacher   xattr: Fix settin...
201
  	int error = -EAGAIN;
69b457329   Andi Kleen   Cache xattr secur...
202
203
  	int issec = !strncmp(name, XATTR_SECURITY_PREFIX,
  				   XATTR_SECURITY_PREFIX_LEN);
e0ad7b073   Andrew Morton   [PATCH] move xatt...
204

69b457329   Andi Kleen   Cache xattr secur...
205
206
  	if (issec)
  		inode->i_flags &= ~S_NOSEC;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
207
  	if (inode->i_opflags & IOP_XATTR) {
c7c7a1a18   Tycho Andersen   xattr: handle idm...
208
209
  		error = __vfs_setxattr(mnt_userns, dentry, inode, name, value,
  				       size, flags);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
210
211
212
213
214
  		if (!error) {
  			fsnotify_xattr(dentry);
  			security_inode_post_setxattr(dentry, name, value,
  						     size, flags);
  		}
4a5901537   Andreas Gruenbacher   xattr: Fix settin...
215
  	} else {
5f6e59ae8   Andreas Gruenbacher   vfs: Use IOP_XATT...
216
217
  		if (unlikely(is_bad_inode(inode)))
  			return -EIO;
4a5901537   Andreas Gruenbacher   xattr: Fix settin...
218
219
220
221
222
223
224
225
226
227
228
229
  	}
  	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_*...
230
  	}
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
231
232
233
  
  	return error;
  }
08b5d5014   Frank van der Linden   xattr: break dele...
234
  /**
da5c1c0bb   Randy Dunlap   fs/xattr.c: fix k...
235
   * __vfs_setxattr_locked - set an extended attribute while holding the inode
08b5d5014   Frank van der Linden   xattr: break dele...
236
237
   * lock
   *
6961fed42   Randy Dunlap   xattr: fix kernel...
238
   *  @mnt_userns: user namespace of the mount of the target inode
da5c1c0bb   Randy Dunlap   fs/xattr.c: fix k...
239
240
241
242
243
244
   *  @dentry: object to perform setxattr on
   *  @name: xattr name to set
   *  @value: value to set @name to
   *  @size: size of @value
   *  @flags: flags to pass into filesystem operations
   *  @delegated_inode: on return, will contain an inode pointer that
08b5d5014   Frank van der Linden   xattr: break dele...
245
246
   *  a delegation was broken on, NULL if none.
   */
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
247
  int
c7c7a1a18   Tycho Andersen   xattr: handle idm...
248
249
250
  __vfs_setxattr_locked(struct user_namespace *mnt_userns, struct dentry *dentry,
  		      const char *name, const void *value, size_t size,
  		      int flags, struct inode **delegated_inode)
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
251
252
253
  {
  	struct inode *inode = dentry->d_inode;
  	int error;
c7c7a1a18   Tycho Andersen   xattr: handle idm...
254
  	error = xattr_permission(mnt_userns, inode, name, MAY_WRITE);
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
255
256
  	if (error)
  		return error;
71bc356f9   Christian Brauner   commoncap: handle...
257
258
  	error = security_inode_setxattr(mnt_userns, dentry, name, value, size,
  					flags);
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
259
260
  	if (error)
  		goto out;
08b5d5014   Frank van der Linden   xattr: break dele...
261
262
263
  	error = try_break_deleg(inode, delegated_inode);
  	if (error)
  		goto out;
c7c7a1a18   Tycho Andersen   xattr: handle idm...
264
265
  	error = __vfs_setxattr_noperm(mnt_userns, dentry, name, value,
  				      size, flags);
b1ab7e4b2   David P. Quigley   VFS: Factor out p...
266

5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
267
  out:
08b5d5014   Frank van der Linden   xattr: break dele...
268
269
270
271
272
  	return error;
  }
  EXPORT_SYMBOL_GPL(__vfs_setxattr_locked);
  
  int
c7c7a1a18   Tycho Andersen   xattr: handle idm...
273
274
  vfs_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry,
  	     const char *name, const void *value, size_t size, int flags)
08b5d5014   Frank van der Linden   xattr: break dele...
275
276
277
  {
  	struct inode *inode = dentry->d_inode;
  	struct inode *delegated_inode = NULL;
7c03e2cda   Miklos Szeredi   vfs: move cap_con...
278
  	const void  *orig_value = value;
08b5d5014   Frank van der Linden   xattr: break dele...
279
  	int error;
7c03e2cda   Miklos Szeredi   vfs: move cap_con...
280
  	if (size && strcmp(name, XATTR_NAME_CAPS) == 0) {
c7c7a1a18   Tycho Andersen   xattr: handle idm...
281
  		error = cap_convert_nscap(mnt_userns, dentry, &value, size);
7c03e2cda   Miklos Szeredi   vfs: move cap_con...
282
283
284
285
  		if (error < 0)
  			return error;
  		size = error;
  	}
08b5d5014   Frank van der Linden   xattr: break dele...
286
287
  retry_deleg:
  	inode_lock(inode);
c7c7a1a18   Tycho Andersen   xattr: handle idm...
288
289
  	error = __vfs_setxattr_locked(mnt_userns, dentry, name, value, size,
  				      flags, &delegated_inode);
5955102c9   Al Viro   wrappers for ->i_...
290
  	inode_unlock(inode);
08b5d5014   Frank van der Linden   xattr: break dele...
291
292
293
294
295
296
  
  	if (delegated_inode) {
  		error = break_deleg_wait(&delegated_inode);
  		if (!error)
  			goto retry_deleg;
  	}
7c03e2cda   Miklos Szeredi   vfs: move cap_con...
297
298
  	if (value != orig_value)
  		kfree(value);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
299
300
301
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_setxattr);
2220c5b0a   Al Viro   make xattr_getsec...
302
  static ssize_t
71bc356f9   Christian Brauner   commoncap: handle...
303
304
  xattr_getsecurity(struct user_namespace *mnt_userns, struct inode *inode,
  		  const char *name, void *value, size_t size)
424925940   David P. Quigley   VFS/Security: Rew...
305
306
307
308
309
  {
  	void *buffer = NULL;
  	ssize_t len;
  
  	if (!value || !size) {
71bc356f9   Christian Brauner   commoncap: handle...
310
311
  		len = security_inode_getsecurity(mnt_userns, inode, name,
  						 &buffer, false);
424925940   David P. Quigley   VFS/Security: Rew...
312
313
  		goto out_noalloc;
  	}
71bc356f9   Christian Brauner   commoncap: handle...
314
315
  	len = security_inode_getsecurity(mnt_userns, inode, name, &buffer,
  					 true);
424925940   David P. Quigley   VFS/Security: Rew...
316
317
318
319
320
321
322
323
  	if (len < 0)
  		return len;
  	if (size < len) {
  		len = -ERANGE;
  		goto out;
  	}
  	memcpy(value, buffer, len);
  out:
57e7ba04d   Casey Schaufler   lsm: fix smack_in...
324
  	kfree(buffer);
424925940   David P. Quigley   VFS/Security: Rew...
325
326
327
  out_noalloc:
  	return len;
  }
424925940   David P. Quigley   VFS/Security: Rew...
328

1601fbad2   Mimi Zohar   xattr: define vfs...
329
330
331
332
333
334
335
336
337
  /*
   * 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
c7c7a1a18   Tycho Andersen   xattr: handle idm...
338
339
340
  vfs_getxattr_alloc(struct user_namespace *mnt_userns, struct dentry *dentry,
  		   const char *name, char **xattr_value, size_t xattr_size,
  		   gfp_t flags)
1601fbad2   Mimi Zohar   xattr: define vfs...
341
  {
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
342
  	const struct xattr_handler *handler;
1601fbad2   Mimi Zohar   xattr: define vfs...
343
344
345
  	struct inode *inode = dentry->d_inode;
  	char *value = *xattr_value;
  	int error;
c7c7a1a18   Tycho Andersen   xattr: handle idm...
346
  	error = xattr_permission(mnt_userns, inode, name, MAY_READ);
1601fbad2   Mimi Zohar   xattr: define vfs...
347
348
  	if (error)
  		return error;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
349
350
351
352
  	handler = xattr_resolve_name(inode, &name);
  	if (IS_ERR(handler))
  		return PTR_ERR(handler);
  	if (!handler->get)
1601fbad2   Mimi Zohar   xattr: define vfs...
353
  		return -EOPNOTSUPP;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
354
  	error = handler->get(handler, dentry, inode, name, NULL, 0);
1601fbad2   Mimi Zohar   xattr: define vfs...
355
356
357
358
359
360
361
362
363
  	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...
364
  	error = handler->get(handler, dentry, inode, name, value, error);
1601fbad2   Mimi Zohar   xattr: define vfs...
365
366
367
  	*xattr_value = value;
  	return error;
  }
424925940   David P. Quigley   VFS/Security: Rew...
368
  ssize_t
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
369
370
371
  __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
  	       void *value, size_t size)
  {
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
372
373
374
375
376
377
  	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_...
378
  		return -EOPNOTSUPP;
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
379
  	return handler->get(handler, dentry, inode, name, value, size);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
380
381
382
383
  }
  EXPORT_SYMBOL(__vfs_getxattr);
  
  ssize_t
c7c7a1a18   Tycho Andersen   xattr: handle idm...
384
385
  vfs_getxattr(struct user_namespace *mnt_userns, struct dentry *dentry,
  	     const char *name, void *value, size_t size)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
386
387
388
  {
  	struct inode *inode = dentry->d_inode;
  	int error;
c7c7a1a18   Tycho Andersen   xattr: handle idm...
389
  	error = xattr_permission(mnt_userns, inode, name, MAY_READ);
e0ad7b073   Andrew Morton   [PATCH] move xatt...
390
391
  	if (error)
  		return error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
392
393
394
  	error = security_inode_getxattr(dentry, name);
  	if (error)
  		return error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
395
  	if (!strncmp(name, XATTR_SECURITY_PREFIX,
e0ad7b073   Andrew Morton   [PATCH] move xatt...
396
397
  				XATTR_SECURITY_PREFIX_LEN)) {
  		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
71bc356f9   Christian Brauner   commoncap: handle...
398
399
  		int ret = xattr_getsecurity(mnt_userns, inode, suffix, value,
  					    size);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
400
401
402
403
  		/*
  		 * Only overwrite the return value if a security module
  		 * is actually active.
  		 */
4bea58053   David P. Quigley   VFS: Reorder vfs_...
404
405
406
  		if (ret == -EOPNOTSUPP)
  			goto nolsm;
  		return ret;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
407
  	}
4bea58053   David P. Quigley   VFS: Reorder vfs_...
408
  nolsm:
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
409
  	return __vfs_getxattr(dentry, inode, name, value, size);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
410
411
  }
  EXPORT_SYMBOL_GPL(vfs_getxattr);
659564c8a   Bill Nottingham   [PATCH] Introduce...
412
  ssize_t
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
413
  vfs_listxattr(struct dentry *dentry, char *list, size_t size)
659564c8a   Bill Nottingham   [PATCH] Introduce...
414
  {
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
415
  	struct inode *inode = d_inode(dentry);
659564c8a   Bill Nottingham   [PATCH] Introduce...
416
  	ssize_t error;
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
417
  	error = security_inode_listxattr(dentry);
659564c8a   Bill Nottingham   [PATCH] Introduce...
418
419
  	if (error)
  		return error;
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
420
  	if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) {
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
421
  		error = inode->i_op->listxattr(dentry, list, size);
659564c8a   Bill Nottingham   [PATCH] Introduce...
422
  	} else {
bf3ee7136   Andreas Gruenbacher   vfs: Check for th...
423
  		error = security_inode_listsecurity(inode, list, size);
659564c8a   Bill Nottingham   [PATCH] Introduce...
424
425
426
427
428
429
  		if (size && error > size)
  			error = -ERANGE;
  	}
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_listxattr);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
430
  int
c7c7a1a18   Tycho Andersen   xattr: handle idm...
431
432
  __vfs_removexattr(struct user_namespace *mnt_userns, struct dentry *dentry,
  		  const char *name)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
433
  {
6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
434
435
  	struct inode *inode = d_inode(dentry);
  	const struct xattr_handler *handler;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
436

6c6ef9f26   Andreas Gruenbacher   xattr: Stop calli...
437
438
439
440
  	handler = xattr_resolve_name(inode, &name);
  	if (IS_ERR(handler))
  		return PTR_ERR(handler);
  	if (!handler->set)
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
441
  		return -EOPNOTSUPP;
c7c7a1a18   Tycho Andersen   xattr: handle idm...
442
443
  	return handler->set(handler, mnt_userns, dentry, inode, name, NULL, 0,
  			    XATTR_REPLACE);
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
444
445
  }
  EXPORT_SYMBOL(__vfs_removexattr);
08b5d5014   Frank van der Linden   xattr: break dele...
446
  /**
da5c1c0bb   Randy Dunlap   fs/xattr.c: fix k...
447
   * __vfs_removexattr_locked - set an extended attribute while holding the inode
08b5d5014   Frank van der Linden   xattr: break dele...
448
449
   * lock
   *
6961fed42   Randy Dunlap   xattr: fix kernel...
450
   *  @mnt_userns: user namespace of the mount of the target inode
da5c1c0bb   Randy Dunlap   fs/xattr.c: fix k...
451
452
453
   *  @dentry: object to perform setxattr on
   *  @name: name of xattr to remove
   *  @delegated_inode: on return, will contain an inode pointer that
08b5d5014   Frank van der Linden   xattr: break dele...
454
455
   *  a delegation was broken on, NULL if none.
   */
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
456
  int
c7c7a1a18   Tycho Andersen   xattr: handle idm...
457
458
459
  __vfs_removexattr_locked(struct user_namespace *mnt_userns,
  			 struct dentry *dentry, const char *name,
  			 struct inode **delegated_inode)
5d6c31910   Andreas Gruenbacher   xattr: Add __vfs_...
460
461
462
  {
  	struct inode *inode = dentry->d_inode;
  	int error;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
463

c7c7a1a18   Tycho Andersen   xattr: handle idm...
464
  	error = xattr_permission(mnt_userns, inode, name, MAY_WRITE);
e0ad7b073   Andrew Morton   [PATCH] move xatt...
465
466
  	if (error)
  		return error;
71bc356f9   Christian Brauner   commoncap: handle...
467
  	error = security_inode_removexattr(mnt_userns, dentry, name);
7c51bb00c   Dmitry Kasatkin   evm: fix potentia...
468
469
  	if (error)
  		goto out;
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
470

08b5d5014   Frank van der Linden   xattr: break dele...
471
472
473
  	error = try_break_deleg(inode, delegated_inode);
  	if (error)
  		goto out;
c7c7a1a18   Tycho Andersen   xattr: handle idm...
474
  	error = __vfs_removexattr(mnt_userns, dentry, name);
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
475

c7b87de23   Mimi Zohar   evm: evm_inode_po...
476
  	if (!error) {
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
477
  		fsnotify_xattr(dentry);
c7b87de23   Mimi Zohar   evm: evm_inode_po...
478
479
  		evm_inode_post_removexattr(dentry, name);
  	}
7c51bb00c   Dmitry Kasatkin   evm: fix potentia...
480
481
  
  out:
08b5d5014   Frank van der Linden   xattr: break dele...
482
483
484
485
486
  	return error;
  }
  EXPORT_SYMBOL_GPL(__vfs_removexattr_locked);
  
  int
c7c7a1a18   Tycho Andersen   xattr: handle idm...
487
488
  vfs_removexattr(struct user_namespace *mnt_userns, struct dentry *dentry,
  		const char *name)
08b5d5014   Frank van der Linden   xattr: break dele...
489
490
491
492
493
494
495
  {
  	struct inode *inode = dentry->d_inode;
  	struct inode *delegated_inode = NULL;
  	int error;
  
  retry_deleg:
  	inode_lock(inode);
c7c7a1a18   Tycho Andersen   xattr: handle idm...
496
497
  	error = __vfs_removexattr_locked(mnt_userns, dentry,
  					 name, &delegated_inode);
5955102c9   Al Viro   wrappers for ->i_...
498
  	inode_unlock(inode);
08b5d5014   Frank van der Linden   xattr: break dele...
499
500
501
502
503
504
  
  	if (delegated_inode) {
  		error = break_deleg_wait(&delegated_inode);
  		if (!error)
  			goto retry_deleg;
  	}
5be196e5f   Christoph Hellwig   [PATCH] add vfs_*...
505
506
507
  	return error;
  }
  EXPORT_SYMBOL_GPL(vfs_removexattr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
509
510
511
  /*
   * Extended attribute SET operations
   */
  static long
c7c7a1a18   Tycho Andersen   xattr: handle idm...
512
513
514
  setxattr(struct user_namespace *mnt_userns, struct dentry *d,
  	 const char __user *name, const void __user *value, size_t size,
  	 int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
  {
  	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[...
532
533
534
  		kvalue = kvmalloc(size, GFP_KERNEL);
  		if (!kvalue)
  			return -ENOMEM;
44c824982   Andrew Morton   fs/xattr.c:setxat...
535
536
537
538
  		if (copy_from_user(kvalue, value, size)) {
  			error = -EFAULT;
  			goto out;
  		}
2f6f0654a   Eric W. Biederman   userns: Convert v...
539
540
  		if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
  		    (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
dc85bc24f   Christian Brauner   fs: fix acl trans...
541
542
  			posix_acl_fix_xattr_from_user(mnt_userns, d_inode(d),
  						      kvalue, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
  	}
c7c7a1a18   Tycho Andersen   xattr: handle idm...
544
  	error = vfs_setxattr(mnt_userns, d, kname, kvalue, size, flags);
44c824982   Andrew Morton   fs/xattr.c:setxat...
545
  out:
0b2a6f231   Richard Weinberger   fs: xattr: Use kv...
546
  	kvfree(kvalue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
549
550
551
  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
552
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
553
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
  	int error;
c7c7a1a18   Tycho Andersen   xattr: handle idm...
555

68f1bb8bb   Jeff Layton   vfs: allow setxat...
556
557
  retry:
  	error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
559
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
560
  	error = mnt_want_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
561
  	if (!error) {
c7c7a1a18   Tycho Andersen   xattr: handle idm...
562
563
  		error = setxattr(mnt_user_ns(path.mnt), path.dentry, name,
  				 value, size, flags);
2d8f30380   Al Viro   [PATCH] sanitize ...
564
  		mnt_drop_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
565
  	}
2d8f30380   Al Viro   [PATCH] sanitize ...
566
  	path_put(&path);
68f1bb8bb   Jeff Layton   vfs: allow setxat...
567
568
569
570
  	if (retry_estale(error, lookup_flags)) {
  		lookup_flags |= LOOKUP_REVAL;
  		goto retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
572
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
573
574
575
576
577
578
  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...
579
580
581
  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
582
  {
8cc431165   Eric Biggers   vfs: Deduplicate ...
583
  	return path_setxattr(pathname, name, value, size, flags, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
585
586
  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
587
  {
2903ff019   Al Viro   switch simple cas...
588
  	struct fd f = fdget(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
  	int error = -EBADF;
2903ff019   Al Viro   switch simple cas...
590
  	if (!f.file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
  		return error;
9f45f5bf3   Al Viro   new helper: audit...
592
  	audit_file(f.file);
6742cee04   Miklos Szeredi   Revert "ovl: don'...
593
  	error = mnt_want_write_file(f.file);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
594
  	if (!error) {
c7c7a1a18   Tycho Andersen   xattr: handle idm...
595
596
597
  		error = setxattr(file_mnt_user_ns(f.file),
  				 f.file->f_path.dentry, name,
  				 value, size, flags);
6742cee04   Miklos Szeredi   Revert "ovl: don'...
598
  		mnt_drop_write_file(f.file);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
599
  	}
2903ff019   Al Viro   switch simple cas...
600
  	fdput(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
602
603
604
605
606
607
  	return error;
  }
  
  /*
   * Extended attribute GET operations
   */
  static ssize_t
c7c7a1a18   Tycho Andersen   xattr: handle idm...
608
609
  getxattr(struct user_namespace *mnt_userns, struct dentry *d,
  	 const char __user *name, void __user *value, size_t size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
611
612
613
614
615
616
617
618
619
620
621
622
623
  {
  	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[...
624
625
626
  		kvalue = kvzalloc(size, GFP_KERNEL);
  		if (!kvalue)
  			return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
  	}
c7c7a1a18   Tycho Andersen   xattr: handle idm...
628
  	error = vfs_getxattr(mnt_userns, d, kname, kvalue, size);
f549d6c18   Stephen Smalley   [PATCH] Generic V...
629
  	if (error > 0) {
2f6f0654a   Eric W. Biederman   userns: Convert v...
630
631
  		if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
  		    (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
dc85bc24f   Christian Brauner   fs: fix acl trans...
632
633
  			posix_acl_fix_xattr_to_user(mnt_userns, d_inode(d),
  						    kvalue, error);
f549d6c18   Stephen Smalley   [PATCH] Generic V...
634
635
636
637
638
639
  		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
640
  	}
0b2a6f231   Richard Weinberger   fs: xattr: Use kv...
641
642
  
  	kvfree(kvalue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
644
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
645
646
647
  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
648
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
649
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
  	ssize_t error;
60e66b48c   Jeff Layton   vfs: make getxatt...
651
652
  retry:
  	error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
654
  	if (error)
  		return error;
c7c7a1a18   Tycho Andersen   xattr: handle idm...
655
  	error = getxattr(mnt_user_ns(path.mnt), path.dentry, name, value, size);
2d8f30380   Al Viro   [PATCH] sanitize ...
656
  	path_put(&path);
60e66b48c   Jeff Layton   vfs: make getxatt...
657
658
659
660
  	if (retry_estale(error, lookup_flags)) {
  		lookup_flags |= LOOKUP_REVAL;
  		goto retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
662
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
663
664
665
666
667
  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...
668
669
  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
670
  {
8cc431165   Eric Biggers   vfs: Deduplicate ...
671
  	return path_getxattr(pathname, name, value, size, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
673
674
  SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
  		void __user *, value, size_t, size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
  {
2903ff019   Al Viro   switch simple cas...
676
  	struct fd f = fdget(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
  	ssize_t error = -EBADF;
2903ff019   Al Viro   switch simple cas...
678
  	if (!f.file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
  		return error;
9f45f5bf3   Al Viro   new helper: audit...
680
  	audit_file(f.file);
c7c7a1a18   Tycho Andersen   xattr: handle idm...
681
682
  	error = getxattr(file_mnt_user_ns(f.file), f.file->f_path.dentry,
  			 name, value, size);
2903ff019   Al Viro   switch simple cas...
683
  	fdput(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
  	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[...
699
700
701
  		klist = kvmalloc(size, GFP_KERNEL);
  		if (!klist)
  			return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
  	}
659564c8a   Bill Nottingham   [PATCH] Introduce...
703
  	error = vfs_listxattr(d, klist, size);
f549d6c18   Stephen Smalley   [PATCH] Generic V...
704
705
706
707
708
709
710
  	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
711
  	}
0b2a6f231   Richard Weinberger   fs: xattr: Use kv...
712
713
  
  	kvfree(klist);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
715
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
716
717
  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
718
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
719
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
  	ssize_t error;
10a90cf36   Jeff Layton   vfs: make listxat...
721
722
  retry:
  	error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723
724
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
725
726
  	error = listxattr(path.dentry, list, size);
  	path_put(&path);
10a90cf36   Jeff Layton   vfs: make listxat...
727
728
729
730
  	if (retry_estale(error, lookup_flags)) {
  		lookup_flags |= LOOKUP_REVAL;
  		goto retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
732
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
733
734
735
736
737
  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...
738
739
  SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list,
  		size_t, size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
  {
8cc431165   Eric Biggers   vfs: Deduplicate ...
741
  	return path_listxattr(pathname, list, size, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
  }
64fd1de3d   Heiko Carstens   [CVE-2009-0029] S...
743
  SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
  {
2903ff019   Al Viro   switch simple cas...
745
  	struct fd f = fdget(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
  	ssize_t error = -EBADF;
2903ff019   Al Viro   switch simple cas...
747
  	if (!f.file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
  		return error;
9f45f5bf3   Al Viro   new helper: audit...
749
  	audit_file(f.file);
2903ff019   Al Viro   switch simple cas...
750
751
  	error = listxattr(f.file->f_path.dentry, list, size);
  	fdput(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
753
754
755
756
757
758
  	return error;
  }
  
  /*
   * Extended attribute REMOVE operations
   */
  static long
c7c7a1a18   Tycho Andersen   xattr: handle idm...
759
760
  removexattr(struct user_namespace *mnt_userns, struct dentry *d,
  	    const char __user *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
761
762
763
764
765
766
767
768
769
  {
  	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;
c7c7a1a18   Tycho Andersen   xattr: handle idm...
770
  	return vfs_removexattr(mnt_userns, d, kname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
772
773
  static int path_removexattr(const char __user *pathname,
  			    const char __user *name, unsigned int lookup_flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
775
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
776
  	int error;
12f062129   Jeff Layton   vfs: make removex...
777
778
  retry:
  	error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
780
  	if (error)
  		return error;
2d8f30380   Al Viro   [PATCH] sanitize ...
781
  	error = mnt_want_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
782
  	if (!error) {
c7c7a1a18   Tycho Andersen   xattr: handle idm...
783
  		error = removexattr(mnt_user_ns(path.mnt), path.dentry, name);
2d8f30380   Al Viro   [PATCH] sanitize ...
784
  		mnt_drop_write(path.mnt);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
785
  	}
2d8f30380   Al Viro   [PATCH] sanitize ...
786
  	path_put(&path);
12f062129   Jeff Layton   vfs: make removex...
787
788
789
790
  	if (retry_estale(error, lookup_flags)) {
  		lookup_flags |= LOOKUP_REVAL;
  		goto retry;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791
792
  	return error;
  }
8cc431165   Eric Biggers   vfs: Deduplicate ...
793
794
795
796
797
  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...
798
799
  SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
  		const char __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
  {
8cc431165   Eric Biggers   vfs: Deduplicate ...
801
  	return path_removexattr(pathname, name, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
  }
6a6160a7b   Heiko Carstens   [CVE-2009-0029] S...
803
  SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
804
  {
2903ff019   Al Viro   switch simple cas...
805
  	struct fd f = fdget(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
  	int error = -EBADF;
2903ff019   Al Viro   switch simple cas...
807
  	if (!f.file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808
  		return error;
9f45f5bf3   Al Viro   new helper: audit...
809
  	audit_file(f.file);
6742cee04   Miklos Szeredi   Revert "ovl: don'...
810
  	error = mnt_want_write_file(f.file);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
811
  	if (!error) {
c7c7a1a18   Tycho Andersen   xattr: handle idm...
812
813
  		error = removexattr(file_mnt_user_ns(f.file),
  				    f.file->f_path.dentry, name);
6742cee04   Miklos Szeredi   Revert "ovl: don'...
814
  		mnt_drop_write_file(f.file);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
815
  	}
2903ff019   Al Viro   switch simple cas...
816
  	fdput(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
818
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
821
822
823
824
825
   * 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...
826
  	const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827
828
829
  	unsigned int size = 0;
  
  	if (!buffer) {
431547b3c   Christoph Hellwig   sanitize xattr ha...
830
  		for_each_xattr_handler(handlers, handler) {
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
831
832
  			if (!handler->name ||
  			    (handler->list && !handler->list(dentry)))
c4803c497   Andreas Gruenbacher   nfs: Move call to...
833
  				continue;
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
834
  			size += strlen(handler->name) + 1;
431547b3c   Christoph Hellwig   sanitize xattr ha...
835
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
836
837
  	} else {
  		char *buf = buffer;
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
838
  		size_t len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
840
  
  		for_each_xattr_handler(handlers, handler) {
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
841
842
  			if (!handler->name ||
  			    (handler->list && !handler->list(dentry)))
c4803c497   Andreas Gruenbacher   nfs: Move call to...
843
  				continue;
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
844
845
  			len = strlen(handler->name);
  			if (len + 1 > buffer_size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
846
  				return -ERANGE;
764a5c6b1   Andreas Gruenbacher   xattr handlers: S...
847
848
849
  			memcpy(buf, handler->name, len + 1);
  			buf += len + 1;
  			buffer_size -= len + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
850
851
852
853
854
  		}
  		size = buf - buffer;
  	}
  	return size;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
  EXPORT_SYMBOL(generic_listxattr);
38f386574   Aristeu Rozanski   xattr: extract si...
856

e409de992   Andreas Gruenbacher   9p: xattr simplif...
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
  /**
   * 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 ...
875
  	size_t prefix_len = strlen(xattr_prefix(handler));
e409de992   Andreas Gruenbacher   9p: xattr simplif...
876
877
878
879
  
  	return name - prefix_len;
  }
  EXPORT_SYMBOL(xattr_full_name);
38f386574   Aristeu Rozanski   xattr: extract si...
880
881
882
883
884
885
886
887
888
889
  /*
   * 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...
890
  	if (len < sizeof(*new_xattr))
38f386574   Aristeu Rozanski   xattr: extract si...
891
  		return NULL;
fdc85222d   Daniel Xu   kernfs: kvmalloc ...
892
  	new_xattr = kvmalloc(len, GFP_KERNEL);
38f386574   Aristeu Rozanski   xattr: extract si...
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
  	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 ...
927
928
929
930
931
932
933
  /**
   * 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}
a46a22955   Daniel Xu   kernfs: Add remov...
934
   * @removed_size: returns size of the removed xattr, -1 if none removed
aa7c5241c   Andreas Gruenbacher   tmpfs: Use xattr ...
935
936
937
938
939
940
941
942
   *
   * %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,
a46a22955   Daniel Xu   kernfs: Add remov...
943
944
  		     const void *value, size_t size, int flags,
  		     ssize_t *removed_size)
38f386574   Aristeu Rozanski   xattr: extract si...
945
946
  {
  	struct simple_xattr *xattr;
433858469   David Rientjes   fs, xattr: fix bu...
947
  	struct simple_xattr *new_xattr = NULL;
38f386574   Aristeu Rozanski   xattr: extract si...
948
  	int err = 0;
772b31406   Daniel Xu   xattr: fix uninit...
949
950
  	if (removed_size)
  		*removed_size = -1;
38f386574   Aristeu Rozanski   xattr: extract si...
951
952
953
954
955
956
957
958
  	/* 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) {
fdc85222d   Daniel Xu   kernfs: kvmalloc ...
959
  			kvfree(new_xattr);
38f386574   Aristeu Rozanski   xattr: extract si...
960
961
962
963
964
965
966
967
968
969
970
971
  			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);
a46a22955   Daniel Xu   kernfs: Add remov...
972
973
  				if (removed_size)
  					*removed_size = xattr->size;
38f386574   Aristeu Rozanski   xattr: extract si...
974
975
  			} else {
  				list_del(&xattr->list);
a46a22955   Daniel Xu   kernfs: Add remov...
976
977
  				if (removed_size)
  					*removed_size = xattr->size;
38f386574   Aristeu Rozanski   xattr: extract si...
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
  			}
  			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);
fdc85222d   Daniel Xu   kernfs: kvmalloc ...
993
  		kvfree(xattr);
38f386574   Aristeu Rozanski   xattr: extract si...
994
995
996
997
  	}
  	return err;
  
  }
38f386574   Aristeu Rozanski   xattr: extract si...
998
999
1000
1001
  static bool xattr_is_trusted(const char *name)
  {
  	return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
  }
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
  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...
1015
1016
1017
  /*
   * xattr LIST operation for in-memory/pseudo filesystems
   */
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
1018
1019
  ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
  			  char *buffer, size_t size)
38f386574   Aristeu Rozanski   xattr: extract si...
1020
1021
1022
  {
  	bool trusted = capable(CAP_SYS_ADMIN);
  	struct simple_xattr *xattr;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
1023
  	ssize_t remaining_size = size;
0e9a7da51   Mateusz Guzik   xattr handlers: p...
1024
  	int err = 0;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
1025
1026
  
  #ifdef CONFIG_FS_POSIX_ACL
ffc4c9222   Andreas Gruenbacher   sysfs: Do not ret...
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
  	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 ...
1040
1041
  	}
  #endif
38f386574   Aristeu Rozanski   xattr: extract si...
1042
1043
1044
  
  	spin_lock(&xattrs->lock);
  	list_for_each_entry(xattr, &xattrs->head, list) {
38f386574   Aristeu Rozanski   xattr: extract si...
1045
1046
1047
  		/* skip "trusted." attributes for unprivileged callers */
  		if (!trusted && xattr_is_trusted(xattr->name))
  			continue;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
1048
1049
  		err = xattr_list_one(&buffer, &remaining_size, xattr->name);
  		if (err)
0e9a7da51   Mateusz Guzik   xattr handlers: p...
1050
  			break;
38f386574   Aristeu Rozanski   xattr: extract si...
1051
1052
  	}
  	spin_unlock(&xattrs->lock);
0e9a7da51   Mateusz Guzik   xattr handlers: p...
1053
  	return err ? err : size - remaining_size;
38f386574   Aristeu Rozanski   xattr: extract si...
1054
  }
4895768b6   Aristeu Rozanski   fs: add missing d...
1055
1056
1057
  /*
   * Adds an extended attribute to the list
   */
38f386574   Aristeu Rozanski   xattr: extract si...
1058
1059
1060
1061
1062
1063
1064
  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);
  }