Blame view

fs/btrfs/xattr.c 9.91 KB
5103e947b   Josef Bacik   xattr support for...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  /*
   * Copyright (C) 2007 Red Hat.  All rights reserved.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public
   * License v2 as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public
   * License along with this program; if not, write to the
   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   * Boston, MA 021110-1307, USA.
   */
  
  #include <linux/init.h>
  #include <linux/fs.h>
  #include <linux/slab.h>
  #include <linux/rwsem.h>
  #include <linux/xattr.h>
0279b4cd8   Jim Owens   Btrfs: selinux su...
24
  #include <linux/security.h>
5103e947b   Josef Bacik   xattr support for...
25
26
27
28
29
  #include "ctree.h"
  #include "btrfs_inode.h"
  #include "transaction.h"
  #include "xattr.h"
  #include "disk-io.h"
33268eaf0   Josef Bacik   Btrfs: Add ACL su...
30

5103e947b   Josef Bacik   xattr support for...
31

95819c057   Christoph Hellwig   Btrfs: optimize b...
32
33
  ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
  				void *buffer, size_t size)
5103e947b   Josef Bacik   xattr support for...
34
35
36
37
38
  {
  	struct btrfs_dir_item *di;
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_path *path;
  	struct extent_buffer *leaf;
5103e947b   Josef Bacik   xattr support for...
39
40
  	int ret = 0;
  	unsigned long data_ptr;
5103e947b   Josef Bacik   xattr support for...
41
42
  
  	path = btrfs_alloc_path();
95819c057   Christoph Hellwig   Btrfs: optimize b...
43
  	if (!path)
5103e947b   Josef Bacik   xattr support for...
44
  		return -ENOMEM;
5103e947b   Josef Bacik   xattr support for...
45

5103e947b   Josef Bacik   xattr support for...
46
47
48
  	/* lookup the xattr by name */
  	di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name,
  				strlen(name), 0);
070604040   Josef Bacik   Btrfs: cleanup xa...
49
  	if (!di) {
5103e947b   Josef Bacik   xattr support for...
50
51
  		ret = -ENODATA;
  		goto out;
070604040   Josef Bacik   Btrfs: cleanup xa...
52
53
54
  	} else if (IS_ERR(di)) {
  		ret = PTR_ERR(di);
  		goto out;
5103e947b   Josef Bacik   xattr support for...
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  	}
  
  	leaf = path->nodes[0];
  	/* if size is 0, that means we want the size of the attr */
  	if (!size) {
  		ret = btrfs_dir_data_len(leaf, di);
  		goto out;
  	}
  
  	/* now get the data out of our dir_item */
  	if (btrfs_dir_data_len(leaf, di) > size) {
  		ret = -ERANGE;
  		goto out;
  	}
070604040   Josef Bacik   Btrfs: cleanup xa...
69
70
71
72
73
74
75
76
  
  	/*
  	 * The way things are packed into the leaf is like this
  	 * |struct btrfs_dir_item|name|data|
  	 * where name is the xattr name, so security.foo, and data is the
  	 * content of the xattr.  data_ptr points to the location in memory
  	 * where the data starts in the in memory leaf
  	 */
5103e947b   Josef Bacik   xattr support for...
77
78
79
  	data_ptr = (unsigned long)((char *)(di + 1) +
  				   btrfs_dir_name_len(leaf, di));
  	read_extent_buffer(leaf, buffer, data_ptr,
3acd7ee87   Josef Bacik   Btrfs: xattr fixes
80
  			   btrfs_dir_data_len(leaf, di));
5103e947b   Josef Bacik   xattr support for...
81
82
83
  	ret = btrfs_dir_data_len(leaf, di);
  
  out:
5103e947b   Josef Bacik   xattr support for...
84
85
86
  	btrfs_free_path(path);
  	return ret;
  }
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
87
88
89
  static int do_setxattr(struct btrfs_trans_handle *trans,
  		       struct inode *inode, const char *name,
  		       const void *value, size_t size, int flags)
5103e947b   Josef Bacik   xattr support for...
90
91
92
  {
  	struct btrfs_dir_item *di;
  	struct btrfs_root *root = BTRFS_I(inode)->root;
5103e947b   Josef Bacik   xattr support for...
93
  	struct btrfs_path *path;
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
94
95
96
97
98
  	size_t name_len = strlen(name);
  	int ret = 0;
  
  	if (name_len + size > BTRFS_MAX_XATTR_SIZE(root))
  		return -ENOSPC;
5103e947b   Josef Bacik   xattr support for...
99
100
  
  	path = btrfs_alloc_path();
95819c057   Christoph Hellwig   Btrfs: optimize b...
101
  	if (!path)
5103e947b   Josef Bacik   xattr support for...
102
  		return -ENOMEM;
5103e947b   Josef Bacik   xattr support for...
103

5103e947b   Josef Bacik   xattr support for...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
  	/* first lets see if we already have this xattr */
  	di = btrfs_lookup_xattr(trans, root, path, inode->i_ino, name,
  				strlen(name), -1);
  	if (IS_ERR(di)) {
  		ret = PTR_ERR(di);
  		goto out;
  	}
  
  	/* ok we already have this xattr, lets remove it */
  	if (di) {
  		/* if we want create only exit */
  		if (flags & XATTR_CREATE) {
  			ret = -EEXIST;
  			goto out;
  		}
  
  		ret = btrfs_delete_one_dir_name(trans, root, path, di);
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
121
  		BUG_ON(ret);
5103e947b   Josef Bacik   xattr support for...
122
123
124
  		btrfs_release_path(root, path);
  
  		/* if we don't have a value then we are removing the xattr */
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
125
  		if (!value)
5103e947b   Josef Bacik   xattr support for...
126
  			goto out;
33268eaf0   Josef Bacik   Btrfs: Add ACL su...
127
128
129
130
131
132
133
134
  	} else {
  		btrfs_release_path(root, path);
  
  		if (flags & XATTR_REPLACE) {
  			/* we couldn't find the attr to replace */
  			ret = -ENODATA;
  			goto out;
  		}
5103e947b   Josef Bacik   xattr support for...
135
136
137
  	}
  
  	/* ok we have to create a completely new xattr */
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  	ret = btrfs_insert_xattr_item(trans, root, path, inode->i_ino,
  				      name, name_len, value, size);
  	BUG_ON(ret);
  out:
  	btrfs_free_path(path);
  	return ret;
  }
  
  int __btrfs_setxattr(struct btrfs_trans_handle *trans,
  		     struct inode *inode, const char *name,
  		     const void *value, size_t size, int flags)
  {
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	int ret;
  
  	if (trans)
  		return do_setxattr(trans, inode, name, value, size, flags);
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
155
156
157
  	trans = btrfs_start_transaction(root, 2);
  	if (IS_ERR(trans))
  		return PTR_ERR(trans);
5103e947b   Josef Bacik   xattr support for...
158

f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
159
  	btrfs_set_trans_block_group(trans, inode);
5103e947b   Josef Bacik   xattr support for...
160

f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
161
162
163
164
165
166
167
168
169
  	ret = do_setxattr(trans, inode, name, value, size, flags);
  	if (ret)
  		goto out;
  
  	inode->i_ctime = CURRENT_TIME;
  	ret = btrfs_update_inode(trans, root, inode);
  	BUG_ON(ret);
  out:
  	btrfs_end_transaction_throttle(trans, root);
5103e947b   Josef Bacik   xattr support for...
170
171
172
173
174
175
176
177
178
  	return ret;
  }
  
  ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
  {
  	struct btrfs_key key, found_key;
  	struct inode *inode = dentry->d_inode;
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_path *path;
5103e947b   Josef Bacik   xattr support for...
179
180
  	struct extent_buffer *leaf;
  	struct btrfs_dir_item *di;
5103e947b   Josef Bacik   xattr support for...
181
  	int ret = 0, slot, advance;
eaa47d861   Christoph Hellwig   btrfs: optmize li...
182
  	size_t total_size = 0, size_left = size;
5103e947b   Josef Bacik   xattr support for...
183
  	unsigned long name_ptr;
eaa47d861   Christoph Hellwig   btrfs: optmize li...
184
  	size_t name_len;
5103e947b   Josef Bacik   xattr support for...
185
186
187
188
189
190
191
192
193
194
195
196
  	u32 nritems;
  
  	/*
  	 * ok we want all objects associated with this id.
  	 * NOTE: we set key.offset = 0; because we want to start with the
  	 * first xattr that we find and walk forward
  	 */
  	key.objectid = inode->i_ino;
  	btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
  	key.offset = 0;
  
  	path = btrfs_alloc_path();
5103e947b   Josef Bacik   xattr support for...
197
198
  	if (!path)
  		return -ENOMEM;
1caf9342f   Josef Bacik   Btrfs: Make ACLs ...
199
  	path->reada = 2;
5103e947b   Josef Bacik   xattr support for...
200

5103e947b   Josef Bacik   xattr support for...
201
202
203
204
  	/* search for our xattrs */
  	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
  	if (ret < 0)
  		goto err;
5103e947b   Josef Bacik   xattr support for...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  	advance = 0;
  	while (1) {
  		leaf = path->nodes[0];
  		nritems = btrfs_header_nritems(leaf);
  		slot = path->slots[0];
  
  		/* this is where we start walking through the path */
  		if (advance || slot >= nritems) {
  			/*
  			 * if we've reached the last slot in this leaf we need
  			 * to go to the next leaf and reset everything
  			 */
  			if (slot >= nritems-1) {
  				ret = btrfs_next_leaf(root, path);
  				if (ret)
  					break;
  				leaf = path->nodes[0];
  				nritems = btrfs_header_nritems(leaf);
  				slot = path->slots[0];
  			} else {
  				/*
  				 * just walking through the slots on this leaf
  				 */
  				slot++;
  				path->slots[0]++;
  			}
  		}
  		advance = 1;
5103e947b   Josef Bacik   xattr support for...
233
234
235
236
237
238
239
240
241
  		btrfs_item_key_to_cpu(leaf, &found_key, slot);
  
  		/* check to make sure this item is what we want */
  		if (found_key.objectid != key.objectid)
  			break;
  		if (btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY)
  			break;
  
  		di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
eaa47d861   Christoph Hellwig   btrfs: optmize li...
242
243
  		name_len = btrfs_dir_name_len(leaf, di);
  		total_size += name_len + 1;
5103e947b   Josef Bacik   xattr support for...
244
245
246
247
  
  		/* we are just looking for how big our buffer needs to be */
  		if (!size)
  			continue;
eaa47d861   Christoph Hellwig   btrfs: optmize li...
248
  		if (!buffer || (name_len + 1) > size_left) {
5103e947b   Josef Bacik   xattr support for...
249
  			ret = -ERANGE;
b16281c30   Yehuda Sadeh Weinraub   Btrfs: fix return...
250
  			goto err;
5103e947b   Josef Bacik   xattr support for...
251
  		}
eaa47d861   Christoph Hellwig   btrfs: optmize li...
252
253
254
255
256
257
  		name_ptr = (unsigned long)(di + 1);
  		read_extent_buffer(leaf, buffer, name_ptr, name_len);
  		buffer[name_len] = '\0';
  
  		size_left -= name_len + 1;
  		buffer += name_len + 1;
5103e947b   Josef Bacik   xattr support for...
258
259
260
261
  	}
  	ret = total_size;
  
  err:
5103e947b   Josef Bacik   xattr support for...
262
263
264
265
266
267
  	btrfs_free_path(path);
  
  	return ret;
  }
  
  /*
95819c057   Christoph Hellwig   Btrfs: optimize b...
268
269
270
   * List of handlers for synthetic system.* attributes.  All real ondisk
   * attributes are handled directly.
   */
f01cbd3f8   Stephen Hemminger   btrfs: constify x...
271
  const struct xattr_handler *btrfs_xattr_handlers[] = {
0eda294df   Chris Mason   Btrfs: fix btrfs ...
272
  #ifdef CONFIG_BTRFS_FS_POSIX_ACL
95819c057   Christoph Hellwig   Btrfs: optimize b...
273
274
275
276
277
278
279
280
281
282
283
  	&btrfs_xattr_acl_access_handler,
  	&btrfs_xattr_acl_default_handler,
  #endif
  	NULL,
  };
  
  /*
   * Check if the attribute is in a supported namespace.
   *
   * This applied after the check for the synthetic attributes in the system
   * namespace.
5103e947b   Josef Bacik   xattr support for...
284
   */
95819c057   Christoph Hellwig   Btrfs: optimize b...
285
286
  static bool btrfs_is_valid_xattr(const char *name)
  {
d397712bc   Chris Mason   Btrfs: Fix checkp...
287
288
  	return !strncmp(name, XATTR_SECURITY_PREFIX,
  			XATTR_SECURITY_PREFIX_LEN) ||
95819c057   Christoph Hellwig   Btrfs: optimize b...
289
290
291
  	       !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
  	       !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
  	       !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
69a32ac51   Chris Mason   Btrfs: Change mag...
292
  }
95819c057   Christoph Hellwig   Btrfs: optimize b...
293
294
295
296
297
298
299
300
301
302
  ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
  		       void *buffer, size_t size)
  {
  	/*
  	 * If this is a request for a synthetic attribute in the system.*
  	 * namespace use the generic infrastructure to resolve a handler
  	 * for it via sb->s_xattr.
  	 */
  	if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
  		return generic_getxattr(dentry, name, buffer, size);
5103e947b   Josef Bacik   xattr support for...
303

95819c057   Christoph Hellwig   Btrfs: optimize b...
304
305
306
307
  	if (!btrfs_is_valid_xattr(name))
  		return -EOPNOTSUPP;
  	return __btrfs_getxattr(dentry->d_inode, name, buffer, size);
  }
5103e947b   Josef Bacik   xattr support for...
308

95819c057   Christoph Hellwig   Btrfs: optimize b...
309
310
311
  int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
  		   size_t size, int flags)
  {
b83cc9693   Li Zefan   Btrfs: Add readon...
312
313
314
315
316
317
318
319
  	struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
  
  	/*
  	 * The permission on security.* and system.* is not checked
  	 * in permission().
  	 */
  	if (btrfs_root_readonly(root))
  		return -EROFS;
95819c057   Christoph Hellwig   Btrfs: optimize b...
320
321
322
323
324
325
326
  	/*
  	 * If this is a request for a synthetic attribute in the system.*
  	 * namespace use the generic infrastructure to resolve a handler
  	 * for it via sb->s_xattr.
  	 */
  	if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
  		return generic_setxattr(dentry, name, value, size, flags);
5103e947b   Josef Bacik   xattr support for...
327

95819c057   Christoph Hellwig   Btrfs: optimize b...
328
329
  	if (!btrfs_is_valid_xattr(name))
  		return -EOPNOTSUPP;
5103e947b   Josef Bacik   xattr support for...
330

95819c057   Christoph Hellwig   Btrfs: optimize b...
331
332
  	if (size == 0)
  		value = "";  /* empty EA, do not remove */
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
333
334
335
  
  	return __btrfs_setxattr(NULL, dentry->d_inode, name, value, size,
  				flags);
95819c057   Christoph Hellwig   Btrfs: optimize b...
336
337
338
339
  }
  
  int btrfs_removexattr(struct dentry *dentry, const char *name)
  {
b83cc9693   Li Zefan   Btrfs: Add readon...
340
341
342
343
344
345
346
347
  	struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
  
  	/*
  	 * The permission on security.* and system.* is not checked
  	 * in permission().
  	 */
  	if (btrfs_root_readonly(root))
  		return -EROFS;
95819c057   Christoph Hellwig   Btrfs: optimize b...
348
349
350
351
352
353
354
355
356
357
  	/*
  	 * If this is a request for a synthetic attribute in the system.*
  	 * namespace use the generic infrastructure to resolve a handler
  	 * for it via sb->s_xattr.
  	 */
  	if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
  		return generic_removexattr(dentry, name);
  
  	if (!btrfs_is_valid_xattr(name))
  		return -EOPNOTSUPP;
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
358
359
360
  
  	return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0,
  				XATTR_REPLACE);
95819c057   Christoph Hellwig   Btrfs: optimize b...
361
  }
0279b4cd8   Jim Owens   Btrfs: selinux su...
362

f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
363
364
  int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
  			      struct inode *inode, struct inode *dir)
0279b4cd8   Jim Owens   Btrfs: selinux su...
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
  {
  	int err;
  	size_t len;
  	void *value;
  	char *suffix;
  	char *name;
  
  	err = security_inode_init_security(inode, dir, &suffix, &value, &len);
  	if (err) {
  		if (err == -EOPNOTSUPP)
  			return 0;
  		return err;
  	}
  
  	name = kmalloc(XATTR_SECURITY_PREFIX_LEN + strlen(suffix) + 1,
  		       GFP_NOFS);
  	if (!name) {
  		err = -ENOMEM;
  	} else {
  		strcpy(name, XATTR_SECURITY_PREFIX);
  		strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix);
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
386
  		err = __btrfs_setxattr(trans, inode, name, value, len, 0);
0279b4cd8   Jim Owens   Btrfs: selinux su...
387
388
389
390
391
392
393
  		kfree(name);
  	}
  
  	kfree(suffix);
  	kfree(value);
  	return err;
  }