Blame view

fs/btrfs/xattr.c 12.3 KB
c1d7c514f   David Sterba   btrfs: replace GP...
1
  // SPDX-License-Identifier: GPL-2.0
5103e947b   Josef Bacik   xattr support for...
2
3
  /*
   * Copyright (C) 2007 Red Hat.  All rights reserved.
5103e947b   Josef Bacik   xattr support for...
4
5
6
7
8
9
10
   */
  
  #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...
11
  #include <linux/security.h>
996a710d4   Christoph Hellwig   btrfs: use generi...
12
  #include <linux/posix_acl_xattr.h>
ae5e165d8   Jeff Layton   fs: new API for h...
13
  #include <linux/iversion.h>
827aa18e7   Filipe Manana   Btrfs: use nofs c...
14
  #include <linux/sched/mm.h>
5103e947b   Josef Bacik   xattr support for...
15
16
17
18
19
  #include "ctree.h"
  #include "btrfs_inode.h"
  #include "transaction.h"
  #include "xattr.h"
  #include "disk-io.h"
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
20
  #include "props.h"
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
21
  #include "locking.h"
33268eaf0   Josef Bacik   Btrfs: Add ACL su...
22

bcadd7050   David Sterba   btrfs: adjust ret...
23
  int btrfs_getxattr(struct inode *inode, const char *name,
95819c057   Christoph Hellwig   Btrfs: optimize b...
24
  				void *buffer, size_t size)
5103e947b   Josef Bacik   xattr support for...
25
26
27
28
29
  {
  	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...
30
31
  	int ret = 0;
  	unsigned long data_ptr;
5103e947b   Josef Bacik   xattr support for...
32
33
  
  	path = btrfs_alloc_path();
95819c057   Christoph Hellwig   Btrfs: optimize b...
34
  	if (!path)
5103e947b   Josef Bacik   xattr support for...
35
  		return -ENOMEM;
5103e947b   Josef Bacik   xattr support for...
36

5103e947b   Josef Bacik   xattr support for...
37
  	/* lookup the xattr by name */
f85b7379c   David Sterba   btrfs: fix over-8...
38
39
  	di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(BTRFS_I(inode)),
  			name, strlen(name), 0);
070604040   Josef Bacik   Btrfs: cleanup xa...
40
  	if (!di) {
5103e947b   Josef Bacik   xattr support for...
41
42
  		ret = -ENODATA;
  		goto out;
070604040   Josef Bacik   Btrfs: cleanup xa...
43
44
45
  	} else if (IS_ERR(di)) {
  		ret = PTR_ERR(di);
  		goto out;
5103e947b   Josef Bacik   xattr support for...
46
47
48
49
50
51
52
53
54
55
56
57
58
59
  	}
  
  	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...
60
61
62
63
64
65
66
67
  
  	/*
  	 * 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...
68
69
70
  	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
71
  			   btrfs_dir_data_len(leaf, di));
5103e947b   Josef Bacik   xattr support for...
72
73
74
  	ret = btrfs_dir_data_len(leaf, di);
  
  out:
5103e947b   Josef Bacik   xattr support for...
75
76
77
  	btrfs_free_path(path);
  	return ret;
  }
3e125a74f   Anand Jain   btrfs: export btr...
78
79
  int btrfs_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...
80
  {
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
81
  	struct btrfs_dir_item *di = NULL;
5103e947b   Josef Bacik   xattr support for...
82
  	struct btrfs_root *root = BTRFS_I(inode)->root;
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
83
  	struct btrfs_fs_info *fs_info = root->fs_info;
5103e947b   Josef Bacik   xattr support for...
84
  	struct btrfs_path *path;
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
85
86
  	size_t name_len = strlen(name);
  	int ret = 0;
04e6863b1   Anand Jain   btrfs: split btrf...
87
  	ASSERT(trans);
da17066c4   Jeff Mahoney   btrfs: pull node/...
88
  	if (name_len + size > BTRFS_MAX_XATTR_SIZE(root->fs_info))
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
89
  		return -ENOSPC;
5103e947b   Josef Bacik   xattr support for...
90
91
  
  	path = btrfs_alloc_path();
95819c057   Christoph Hellwig   Btrfs: optimize b...
92
  	if (!path)
5103e947b   Josef Bacik   xattr support for...
93
  		return -ENOMEM;
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
94
95
96
  	path->skip_release_on_error = 1;
  
  	if (!value) {
f85b7379c   David Sterba   btrfs: fix over-8...
97
98
  		di = btrfs_lookup_xattr(trans, root, path,
  				btrfs_ino(BTRFS_I(inode)), name, name_len, -1);
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
99
100
  		if (!di && (flags & XATTR_REPLACE))
  			ret = -ENODATA;
5cdf83edb   Filipe Manana   Btrfs: do not ign...
101
102
  		else if (IS_ERR(di))
  			ret = PTR_ERR(di);
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
103
104
105
106
  		else if (di)
  			ret = btrfs_delete_one_dir_name(trans, root, path, di);
  		goto out;
  	}
5103e947b   Josef Bacik   xattr support for...
107

5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
108
109
110
111
112
113
114
  	/*
  	 * For a replace we can't just do the insert blindly.
  	 * Do a lookup first (read-only btrfs_search_slot), and return if xattr
  	 * doesn't exist. If it exists, fall down below to the insert/replace
  	 * path - we can't race with a concurrent xattr delete, because the VFS
  	 * locks the inode's i_mutex before calling setxattr or removexattr.
  	 */
fa09200b8   Josef Bacik   Btrfs: try to onl...
115
  	if (flags & XATTR_REPLACE) {
5955102c9   Al Viro   wrappers for ->i_...
116
  		ASSERT(inode_is_locked(inode));
f85b7379c   David Sterba   btrfs: fix over-8...
117
118
  		di = btrfs_lookup_xattr(NULL, root, path,
  				btrfs_ino(BTRFS_I(inode)), name, name_len, 0);
5cdf83edb   Filipe Manana   Btrfs: do not ign...
119
  		if (!di)
fa09200b8   Josef Bacik   Btrfs: try to onl...
120
  			ret = -ENODATA;
5cdf83edb   Filipe Manana   Btrfs: do not ign...
121
122
123
  		else if (IS_ERR(di))
  			ret = PTR_ERR(di);
  		if (ret)
5103e947b   Josef Bacik   xattr support for...
124
  			goto out;
b3b4aa74b   David Sterba   btrfs: drop unuse...
125
  		btrfs_release_path(path);
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
126
127
  		di = NULL;
  	}
4815053ab   David Sterba   btrfs: xattr: fix...
128

4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
129
  	ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(BTRFS_I(inode)),
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
130
131
  				      name, name_len, value, size);
  	if (ret == -EOVERFLOW) {
4815053ab   David Sterba   btrfs: xattr: fix...
132
  		/*
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
133
134
135
  		 * We have an existing item in a leaf, split_leaf couldn't
  		 * expand it. That item might have or not a dir_item that
  		 * matches our target xattr, so lets check.
4815053ab   David Sterba   btrfs: xattr: fix...
136
  		 */
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
137
138
  		ret = 0;
  		btrfs_assert_tree_locked(path->nodes[0]);
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
139
  		di = btrfs_match_dir_item_name(fs_info, path, name, name_len);
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
140
141
  		if (!di && !(flags & XATTR_REPLACE)) {
  			ret = -ENOSPC;
01e6deb25   Liu Bo   Btrfs: don't add ...
142
143
  			goto out;
  		}
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
144
145
  	} else if (ret == -EEXIST) {
  		ret = 0;
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
146
  		di = btrfs_match_dir_item_name(fs_info, path, name, name_len);
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
147
148
149
  		ASSERT(di); /* logic error */
  	} else if (ret) {
  		goto out;
fa09200b8   Josef Bacik   Btrfs: try to onl...
150
  	}
5103e947b   Josef Bacik   xattr support for...
151

5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
152
  	if (di && (flags & XATTR_CREATE)) {
ed3ee9f44   Josef Bacik   Btrfs: fix regres...
153
  		ret = -EEXIST;
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
154
155
  		goto out;
  	}
ed3ee9f44   Josef Bacik   Btrfs: fix regres...
156

5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
157
  	if (di) {
fa09200b8   Josef Bacik   Btrfs: try to onl...
158
  		/*
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
159
160
161
162
163
  		 * We're doing a replace, and it must be atomic, that is, at
  		 * any point in time we have either the old or the new xattr
  		 * value in the tree. We don't want readers (getxattr and
  		 * listxattrs) to miss a value, this is specially important
  		 * for ACLs.
fa09200b8   Josef Bacik   Btrfs: try to onl...
164
  		 */
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
165
166
167
168
169
170
171
172
173
174
  		const int slot = path->slots[0];
  		struct extent_buffer *leaf = path->nodes[0];
  		const u16 old_data_len = btrfs_dir_data_len(leaf, di);
  		const u32 item_size = btrfs_item_size_nr(leaf, slot);
  		const u32 data_size = sizeof(*di) + name_len + size;
  		struct btrfs_item *item;
  		unsigned long data_ptr;
  		char *ptr;
  
  		if (size > old_data_len) {
e902baac6   David Sterba   btrfs: get fs_inf...
175
  			if (btrfs_leaf_free_space(leaf) <
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
176
177
178
179
  			    (size - old_data_len)) {
  				ret = -ENOSPC;
  				goto out;
  			}
fa09200b8   Josef Bacik   Btrfs: try to onl...
180
  		}
33268eaf0   Josef Bacik   Btrfs: Add ACL su...
181

5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
182
183
184
  		if (old_data_len + name_len + sizeof(*di) == item_size) {
  			/* No other xattrs packed in the same leaf item. */
  			if (size > old_data_len)
c71dd8800   David Sterba   btrfs: remove unu...
185
  				btrfs_extend_item(path, size - old_data_len);
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
186
  			else if (size < old_data_len)
78ac4f9e5   David Sterba   btrfs: remove unu...
187
  				btrfs_truncate_item(path, data_size, 1);
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
188
189
190
191
192
  		} else {
  			/* There are other xattrs packed in the same item. */
  			ret = btrfs_delete_one_dir_name(trans, root, path, di);
  			if (ret)
  				goto out;
c71dd8800   David Sterba   btrfs: remove unu...
193
  			btrfs_extend_item(path, data_size);
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
194
  		}
fa09200b8   Josef Bacik   Btrfs: try to onl...
195

5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
196
197
198
199
200
201
202
203
204
  		item = btrfs_item_nr(slot);
  		ptr = btrfs_item_ptr(leaf, slot, char);
  		ptr += btrfs_item_size(leaf, item) - data_size;
  		di = (struct btrfs_dir_item *)ptr;
  		btrfs_set_dir_data_len(leaf, di, size);
  		data_ptr = ((unsigned long)(di + 1)) + name_len;
  		write_extent_buffer(leaf, value, data_ptr, size);
  		btrfs_mark_buffer_dirty(leaf);
  	} else {
fa09200b8   Josef Bacik   Btrfs: try to onl...
205
  		/*
5f5bc6b1e   Filipe Manana   Btrfs: make xattr...
206
207
208
  		 * Insert, and we had space for the xattr, so path->slots[0] is
  		 * where our xattr dir_item is and btrfs_insert_xattr_item()
  		 * filled it.
fa09200b8   Josef Bacik   Btrfs: try to onl...
209
  		 */
5103e947b   Josef Bacik   xattr support for...
210
  	}
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
211
212
  out:
  	btrfs_free_path(path);
877381645   Filipe Manana   btrfs: skip unnec...
213
  	if (!ret) {
3763771cf   Filipe Manana   Btrfs: fix failur...
214
215
  		set_bit(BTRFS_INODE_COPY_EVERYTHING,
  			&BTRFS_I(inode)->runtime_flags);
877381645   Filipe Manana   btrfs: skip unnec...
216
217
  		clear_bit(BTRFS_INODE_NO_XATTRS, &BTRFS_I(inode)->runtime_flags);
  	}
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
218
219
  	return ret;
  }
4815053ab   David Sterba   btrfs: xattr: fix...
220
221
222
  /*
   * @value: "" makes the attribute to empty, NULL removes it
   */
e3de9b159   Anand Jain   btrfs: cleanup bt...
223
  int btrfs_setxattr_trans(struct inode *inode, const char *name,
cac237ae0   Anand Jain   btrfs: rename btr...
224
  			 const void *value, size_t size, int flags)
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
225
226
  {
  	struct btrfs_root *root = BTRFS_I(inode)->root;
e3de9b159   Anand Jain   btrfs: cleanup bt...
227
  	struct btrfs_trans_handle *trans;
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
228
  	int ret;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
229
230
231
  	trans = btrfs_start_transaction(root, 2);
  	if (IS_ERR(trans))
  		return PTR_ERR(trans);
5103e947b   Josef Bacik   xattr support for...
232

2d74fa3ef   Anand Jain   btrfs: rename do_...
233
  	ret = btrfs_setxattr(trans, inode, name, value, size, flags);
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
234
235
  	if (ret)
  		goto out;
0c4d2d95d   Josef Bacik   Btrfs: use i_vers...
236
  	inode_inc_iversion(inode);
c2050a454   Deepa Dinamani   fs: Replace curre...
237
  	inode->i_ctime = current_time(inode);
f34f57a3a   Yan, Zheng   Btrfs: Pass trans...
238
239
240
  	ret = btrfs_update_inode(trans, root, inode);
  	BUG_ON(ret);
  out:
3a45bb207   Jeff Mahoney   btrfs: remove roo...
241
  	btrfs_end_transaction(trans);
5103e947b   Josef Bacik   xattr support for...
242
243
244
245
246
  	return ret;
  }
  
  ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
  {
daac7ba61   Filipe Manana   Btrfs: fix listxa...
247
  	struct btrfs_key key;
2b0143b5c   David Howells   VFS: normal files...
248
  	struct inode *inode = d_inode(dentry);
5103e947b   Josef Bacik   xattr support for...
249
250
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_path *path;
daac7ba61   Filipe Manana   Btrfs: fix listxa...
251
  	int ret = 0;
eaa47d861   Christoph Hellwig   btrfs: optmize li...
252
  	size_t total_size = 0, size_left = size;
5103e947b   Josef Bacik   xattr support for...
253
254
255
256
257
258
  
  	/*
  	 * 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
  	 */
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
259
  	key.objectid = btrfs_ino(BTRFS_I(inode));
962a298f3   David Sterba   btrfs: kill the k...
260
  	key.type = BTRFS_XATTR_ITEM_KEY;
5103e947b   Josef Bacik   xattr support for...
261
262
263
  	key.offset = 0;
  
  	path = btrfs_alloc_path();
5103e947b   Josef Bacik   xattr support for...
264
265
  	if (!path)
  		return -ENOMEM;
e4058b54d   David Sterba   btrfs: cleanup, u...
266
  	path->reada = READA_FORWARD;
5103e947b   Josef Bacik   xattr support for...
267

5103e947b   Josef Bacik   xattr support for...
268
269
270
271
  	/* search for our xattrs */
  	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
  	if (ret < 0)
  		goto err;
2e6a00356   Li Zefan   Btrfs: Check if b...
272

5103e947b   Josef Bacik   xattr support for...
273
  	while (1) {
daac7ba61   Filipe Manana   Btrfs: fix listxa...
274
275
276
277
278
279
  		struct extent_buffer *leaf;
  		int slot;
  		struct btrfs_dir_item *di;
  		struct btrfs_key found_key;
  		u32 item_size;
  		u32 cur;
5103e947b   Josef Bacik   xattr support for...
280
  		leaf = path->nodes[0];
5103e947b   Josef Bacik   xattr support for...
281
282
283
  		slot = path->slots[0];
  
  		/* this is where we start walking through the path */
2e6a00356   Li Zefan   Btrfs: Check if b...
284
  		if (slot >= btrfs_header_nritems(leaf)) {
5103e947b   Josef Bacik   xattr support for...
285
286
287
288
  			/*
  			 * if we've reached the last slot in this leaf we need
  			 * to go to the next leaf and reset everything
  			 */
2e6a00356   Li Zefan   Btrfs: Check if b...
289
290
291
292
293
294
  			ret = btrfs_next_leaf(root, path);
  			if (ret < 0)
  				goto err;
  			else if (ret > 0)
  				break;
  			continue;
5103e947b   Josef Bacik   xattr support for...
295
  		}
5103e947b   Josef Bacik   xattr support for...
296

5103e947b   Josef Bacik   xattr support for...
297
298
299
300
301
  		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;
f1cd1f0b7   Filipe Manana   Btrfs: fix race w...
302
  		if (found_key.type > BTRFS_XATTR_ITEM_KEY)
5103e947b   Josef Bacik   xattr support for...
303
  			break;
f1cd1f0b7   Filipe Manana   Btrfs: fix race w...
304
  		if (found_key.type < BTRFS_XATTR_ITEM_KEY)
daac7ba61   Filipe Manana   Btrfs: fix listxa...
305
  			goto next_item;
5103e947b   Josef Bacik   xattr support for...
306
307
  
  		di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
daac7ba61   Filipe Manana   Btrfs: fix listxa...
308
309
310
311
312
313
314
  		item_size = btrfs_item_size_nr(leaf, slot);
  		cur = 0;
  		while (cur < item_size) {
  			u16 name_len = btrfs_dir_name_len(leaf, di);
  			u16 data_len = btrfs_dir_data_len(leaf, di);
  			u32 this_len = sizeof(*di) + name_len + data_len;
  			unsigned long name_ptr = (unsigned long)(di + 1);
daac7ba61   Filipe Manana   Btrfs: fix listxa...
315
316
317
318
319
320
321
  			total_size += name_len + 1;
  			/*
  			 * We are just looking for how big our buffer needs to
  			 * be.
  			 */
  			if (!size)
  				goto next;
5103e947b   Josef Bacik   xattr support for...
322

daac7ba61   Filipe Manana   Btrfs: fix listxa...
323
324
325
326
  			if (!buffer || (name_len + 1) > size_left) {
  				ret = -ERANGE;
  				goto err;
  			}
5103e947b   Josef Bacik   xattr support for...
327

daac7ba61   Filipe Manana   Btrfs: fix listxa...
328
329
  			read_extent_buffer(leaf, buffer, name_ptr, name_len);
  			buffer[name_len] = '\0';
eaa47d861   Christoph Hellwig   btrfs: optmize li...
330

daac7ba61   Filipe Manana   Btrfs: fix listxa...
331
332
  			size_left -= name_len + 1;
  			buffer += name_len + 1;
2e6a00356   Li Zefan   Btrfs: Check if b...
333
  next:
daac7ba61   Filipe Manana   Btrfs: fix listxa...
334
335
336
337
  			cur += this_len;
  			di = (struct btrfs_dir_item *)((char *)di + this_len);
  		}
  next_item:
2e6a00356   Li Zefan   Btrfs: Check if b...
338
  		path->slots[0]++;
5103e947b   Josef Bacik   xattr support for...
339
340
341
342
  	}
  	ret = total_size;
  
  err:
5103e947b   Josef Bacik   xattr support for...
343
344
345
346
  	btrfs_free_path(path);
  
  	return ret;
  }
9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
347
  static int btrfs_xattr_handler_get(const struct xattr_handler *handler,
b296821a7   Al Viro   xattr_handler: pa...
348
  				   struct dentry *unused, struct inode *inode,
3484eba91   Mark Salyzyn   FROMLIST: Add fla...
349
350
  				   const char *name, void *buffer, size_t size,
  				   int flags)
95819c057   Christoph Hellwig   Btrfs: optimize b...
351
  {
9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
352
  	name = xattr_full_name(handler, name);
7852781d9   David Sterba   btrfs: drop under...
353
  	return btrfs_getxattr(inode, name, buffer, size);
69a32ac51   Chris Mason   Btrfs: Change mag...
354
  }
9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
355
  static int btrfs_xattr_handler_set(const struct xattr_handler *handler,
593012268   Al Viro   switch xattr_hand...
356
357
358
  				   struct dentry *unused, struct inode *inode,
  				   const char *name, const void *buffer,
  				   size_t size, int flags)
95819c057   Christoph Hellwig   Btrfs: optimize b...
359
  {
9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
360
  	name = xattr_full_name(handler, name);
e3de9b159   Anand Jain   btrfs: cleanup bt...
361
  	return btrfs_setxattr_trans(inode, name, buffer, size, flags);
9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
362
  }
5103e947b   Josef Bacik   xattr support for...
363

9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
364
  static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
593012268   Al Viro   switch xattr_hand...
365
  					struct dentry *unused, struct inode *inode,
9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
366
367
368
  					const char *name, const void *value,
  					size_t size, int flags)
  {
f22125e5d   Anand Jain   btrfs: refactor b...
369
  	int ret;
b3f6a4be1   Anand Jain   btrfs: start tran...
370
371
  	struct btrfs_trans_handle *trans;
  	struct btrfs_root *root = BTRFS_I(inode)->root;
f22125e5d   Anand Jain   btrfs: refactor b...
372

9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
373
  	name = xattr_full_name(handler, name);
f22125e5d   Anand Jain   btrfs: refactor b...
374
375
376
  	ret = btrfs_validate_prop(name, value, size);
  	if (ret)
  		return ret;
b3f6a4be1   Anand Jain   btrfs: start tran...
377
378
379
380
381
382
383
384
385
  
  	trans = btrfs_start_transaction(root, 2);
  	if (IS_ERR(trans))
  		return PTR_ERR(trans);
  
  	ret = btrfs_set_prop(trans, inode, name, value, size, flags);
  	if (!ret) {
  		inode_inc_iversion(inode);
  		inode->i_ctime = current_time(inode);
b3f6a4be1   Anand Jain   btrfs: start tran...
386
387
388
389
390
391
392
  		ret = btrfs_update_inode(trans, root, inode);
  		BUG_ON(ret);
  	}
  
  	btrfs_end_transaction(trans);
  
  	return ret;
95819c057   Christoph Hellwig   Btrfs: optimize b...
393
  }
5103e947b   Josef Bacik   xattr support for...
394

9172abbcd   Andreas Gruenbacher   btrfs: Use xattr ...
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
  static const struct xattr_handler btrfs_security_xattr_handler = {
  	.prefix = XATTR_SECURITY_PREFIX,
  	.get = btrfs_xattr_handler_get,
  	.set = btrfs_xattr_handler_set,
  };
  
  static const struct xattr_handler btrfs_trusted_xattr_handler = {
  	.prefix = XATTR_TRUSTED_PREFIX,
  	.get = btrfs_xattr_handler_get,
  	.set = btrfs_xattr_handler_set,
  };
  
  static const struct xattr_handler btrfs_user_xattr_handler = {
  	.prefix = XATTR_USER_PREFIX,
  	.get = btrfs_xattr_handler_get,
  	.set = btrfs_xattr_handler_set,
  };
  
  static const struct xattr_handler btrfs_btrfs_xattr_handler = {
  	.prefix = XATTR_BTRFS_PREFIX,
  	.get = btrfs_xattr_handler_get,
  	.set = btrfs_xattr_handler_set_prop,
  };
  
  const struct xattr_handler *btrfs_xattr_handlers[] = {
  	&btrfs_security_xattr_handler,
  #ifdef CONFIG_BTRFS_FS_POSIX_ACL
  	&posix_acl_access_xattr_handler,
  	&posix_acl_default_xattr_handler,
  #endif
  	&btrfs_trusted_xattr_handler,
  	&btrfs_user_xattr_handler,
  	&btrfs_btrfs_xattr_handler,
  	NULL,
  };
48a3b6366   Eric Sandeen   btrfs: make stati...
430
  static int btrfs_initxattrs(struct inode *inode,
419a6f30f   Anand Jain   btrfs: rename fs_...
431
  			    const struct xattr *xattr_array, void *fs_private)
0279b4cd8   Jim Owens   Btrfs: selinux su...
432
  {
419a6f30f   Anand Jain   btrfs: rename fs_...
433
  	struct btrfs_trans_handle *trans = fs_private;
9d8f13ba3   Mimi Zohar   security: new sec...
434
  	const struct xattr *xattr;
827aa18e7   Filipe Manana   Btrfs: use nofs c...
435
  	unsigned int nofs_flag;
0279b4cd8   Jim Owens   Btrfs: selinux su...
436
  	char *name;
9d8f13ba3   Mimi Zohar   security: new sec...
437
  	int err = 0;
0279b4cd8   Jim Owens   Btrfs: selinux su...
438

827aa18e7   Filipe Manana   Btrfs: use nofs c...
439
440
441
442
443
  	/*
  	 * We're holding a transaction handle, so use a NOFS memory allocation
  	 * context to avoid deadlock if reclaim happens.
  	 */
  	nofs_flag = memalloc_nofs_save();
9d8f13ba3   Mimi Zohar   security: new sec...
444
445
  	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
  		name = kmalloc(XATTR_SECURITY_PREFIX_LEN +
39a27ec10   David Sterba   btrfs: use GFP_KE...
446
  			       strlen(xattr->name) + 1, GFP_KERNEL);
9d8f13ba3   Mimi Zohar   security: new sec...
447
448
449
450
  		if (!name) {
  			err = -ENOMEM;
  			break;
  		}
0279b4cd8   Jim Owens   Btrfs: selinux su...
451
  		strcpy(name, XATTR_SECURITY_PREFIX);
9d8f13ba3   Mimi Zohar   security: new sec...
452
  		strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
04e6863b1   Anand Jain   btrfs: split btrf...
453
454
  		err = btrfs_setxattr(trans, inode, name, xattr->value,
  				     xattr->value_len, 0);
0279b4cd8   Jim Owens   Btrfs: selinux su...
455
  		kfree(name);
9d8f13ba3   Mimi Zohar   security: new sec...
456
457
  		if (err < 0)
  			break;
0279b4cd8   Jim Owens   Btrfs: selinux su...
458
  	}
827aa18e7   Filipe Manana   Btrfs: use nofs c...
459
  	memalloc_nofs_restore(nofs_flag);
0279b4cd8   Jim Owens   Btrfs: selinux su...
460
461
  	return err;
  }
9d8f13ba3   Mimi Zohar   security: new sec...
462
463
464
465
466
467
468
469
  
  int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
  			      struct inode *inode, struct inode *dir,
  			      const struct qstr *qstr)
  {
  	return security_inode_init_security(inode, dir, qstr,
  					    &btrfs_initxattrs, trans);
  }