Blame view

fs/ubifs/xattr.c 16.7 KB
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  /*
   * This file is part of UBIFS.
   *
   * Copyright (C) 2006-2008 Nokia Corporation.
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 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., 51
   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
   *
   * Authors: Artem Bityutskiy (Битюцкий Артём)
   *          Adrian Hunter
   */
  
  /*
   * This file implements UBIFS extended attributes support.
   *
   * Extended attributes are implemented as regular inodes with attached data,
   * which limits extended attribute size to UBIFS block size (4KiB). Names of
   * extended attributes are described by extended attribute entries (xentries),
   * which are almost identical to directory entries, but have different key type.
   *
   * In other words, the situation with extended attributes is very similar to
   * directories. Indeed, any inode (but of course not xattr inodes) may have a
   * number of associated xentries, just like directory inodes have associated
   * directory entries. Extended attribute entries store the name of the extended
   * attribute, the host inode number, and the extended attribute inode number.
   * Similarly, direntries store the name, the parent and the target inode
   * numbers. Thus, most of the common UBIFS mechanisms may be re-used for
   * extended attributes.
   *
   * The number of extended attributes is not limited, but there is Linux
   * limitation on the maximum possible size of the list of all extended
   * attributes associated with an inode (%XATTR_LIST_MAX), so UBIFS makes sure
   * the sum of all extended attribute names of the inode does not exceed that
   * limit.
   *
   * Extended attributes are synchronous, which means they are written to the
   * flash media synchronously and there is no write-back for extended attribute
   * inodes. The extended attribute values are not stored in compressed form on
   * the media.
   *
   * Since extended attributes are represented by regular inodes, they are cached
   * in the VFS inode cache. The xentries are cached in the LNC cache (see
   * tnc.c).
   *
   * ACL support is not implemented.
   */
073aaa1b1   Al Viro   helpers for acl c...
57
  #include "ubifs.h"
7dcda1c96   Jens Axboe   fs: export empty_...
58
  #include <linux/fs.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
59
  #include <linux/slab.h>
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
60
  #include <linux/xattr.h>
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
61
62
63
  
  /*
   * Limit the number of extended attributes per inode so that the total size
c78c7e35a   Artem Bityutskiy   UBIFS: xattr bugf...
64
   * (@xattr_size) is guaranteeded to fit in an 'unsigned int'.
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
   */
  #define MAX_XATTRS_PER_INODE 65535
  
  /*
   * Extended attribute type constants.
   *
   * USER_XATTR: user extended attribute ("user.*")
   * TRUSTED_XATTR: trusted extended attribute ("trusted.*)
   * SECURITY_XATTR: security extended attribute ("security.*")
   */
  enum {
  	USER_XATTR,
  	TRUSTED_XATTR,
  	SECURITY_XATTR,
  };
14ffd5d0b   Sedat Dilek   UBIFS: make xattr...
80
81
  static const struct inode_operations empty_iops;
  static const struct file_operations empty_fops;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  
  /**
   * create_xattr - create an extended attribute.
   * @c: UBIFS file-system description object
   * @host: host inode
   * @nm: extended attribute name
   * @value: extended attribute value
   * @size: size of extended attribute value
   *
   * This is a helper function which creates an extended attribute of name @nm
   * and value @value for inode @host. The host inode is also updated on flash
   * because the ctime and extended attribute accounting data changes. This
   * function returns zero in case of success and a negative error code in case
   * of failure.
   */
  static int create_xattr(struct ubifs_info *c, struct inode *host,
  			const struct qstr *nm, const void *value, int size)
  {
fee1756d8   Subodh Nijsure   UBIFS: add ubifs_...
100
  	int err, names_len;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
101
102
103
  	struct inode *inode;
  	struct ubifs_inode *ui, *host_ui = ubifs_inode(host);
  	struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
5acd6ff8a   Zoltan Sogor   UBIFS: fix budget...
104
105
  				.new_ino_d = ALIGN(size, 8), .dirtied_ino = 1,
  				.dirtied_ino_d = ALIGN(host_ui->data_len, 8) };
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
106

fee1756d8   Subodh Nijsure   UBIFS: add ubifs_...
107
  	if (host_ui->xattr_cnt >= MAX_XATTRS_PER_INODE) {
235c362bd   Sheng Yong   UBIFS: extend deb...
108
  		ubifs_err(c, "inode %lu already has too many xattrs (%d), cannot create more",
fee1756d8   Subodh Nijsure   UBIFS: add ubifs_...
109
  			  host->i_ino, host_ui->xattr_cnt);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
110
  		return -ENOSPC;
fee1756d8   Subodh Nijsure   UBIFS: add ubifs_...
111
  	}
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
112
113
  	/*
  	 * Linux limits the maximum size of the extended attribute names list
c78c7e35a   Artem Bityutskiy   UBIFS: xattr bugf...
114
  	 * to %XATTR_LIST_MAX. This means we should not allow creating more
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
115
116
117
  	 * extended attributes if the name list becomes larger. This limitation
  	 * is artificial for UBIFS, though.
  	 */
fee1756d8   Subodh Nijsure   UBIFS: add ubifs_...
118
119
  	names_len = host_ui->xattr_names + host_ui->xattr_cnt + nm->len + 1;
  	if (names_len > XATTR_LIST_MAX) {
235c362bd   Sheng Yong   UBIFS: extend deb...
120
  		ubifs_err(c, "cannot add one more xattr name to inode %lu, total names length would become %d, max. is %d",
fee1756d8   Subodh Nijsure   UBIFS: add ubifs_...
121
  			  host->i_ino, names_len, XATTR_LIST_MAX);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
122
  		return -ENOSPC;
fee1756d8   Subodh Nijsure   UBIFS: add ubifs_...
123
  	}
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
124
125
126
127
128
129
130
131
132
133
  
  	err = ubifs_budget_space(c, &req);
  	if (err)
  		return err;
  
  	inode = ubifs_new_inode(c, host, S_IFREG | S_IRWXUGO);
  	if (IS_ERR(inode)) {
  		err = PTR_ERR(inode);
  		goto out_budg;
  	}
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
134
  	/* Re-define all operations to be "nothing" */
7dcda1c96   Jens Axboe   fs: export empty_...
135
  	inode->i_mapping->a_ops = &empty_aops;
14ffd5d0b   Sedat Dilek   UBIFS: make xattr...
136
137
  	inode->i_op = &empty_iops;
  	inode->i_fop = &empty_fops;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
138
139
140
141
142
  
  	inode->i_flags |= S_SYNC | S_NOATIME | S_NOCMTIME | S_NOQUOTA;
  	ui = ubifs_inode(inode);
  	ui->xattr = 1;
  	ui->flags |= UBIFS_XATTR_FL;
eaecf43a6   Thomas Meyer   UBIFS: Use kmemdu...
143
  	ui->data = kmemdup(value, size, GFP_NOFS);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
144
145
  	if (!ui->data) {
  		err = -ENOMEM;
c78c7e35a   Artem Bityutskiy   UBIFS: xattr bugf...
146
  		goto out_free;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
147
  	}
c78c7e35a   Artem Bityutskiy   UBIFS: xattr bugf...
148
149
150
151
  	inode->i_size = ui->ui_size = size;
  	ui->data_len = size;
  
  	mutex_lock(&host_ui->ui_mutex);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
152
153
154
155
156
  	host->i_ctime = ubifs_current_time(host);
  	host_ui->xattr_cnt += 1;
  	host_ui->xattr_size += CALC_DENT_SIZE(nm->len);
  	host_ui->xattr_size += CALC_XATTR_BYTES(size);
  	host_ui->xattr_names += nm->len;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
157
158
159
160
161
162
163
164
165
166
167
168
169
170
  	err = ubifs_jnl_update(c, host, nm, inode, 0, 1);
  	if (err)
  		goto out_cancel;
  	mutex_unlock(&host_ui->ui_mutex);
  
  	ubifs_release_budget(c, &req);
  	insert_inode_hash(inode);
  	iput(inode);
  	return 0;
  
  out_cancel:
  	host_ui->xattr_cnt -= 1;
  	host_ui->xattr_size -= CALC_DENT_SIZE(nm->len);
  	host_ui->xattr_size -= CALC_XATTR_BYTES(size);
843741c57   Richard Weinberger   ubifs: Fix xattr_...
171
  	host_ui->xattr_names -= nm->len;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
172
  	mutex_unlock(&host_ui->ui_mutex);
c78c7e35a   Artem Bityutskiy   UBIFS: xattr bugf...
173
  out_free:
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
  	make_bad_inode(inode);
  	iput(inode);
  out_budg:
  	ubifs_release_budget(c, &req);
  	return err;
  }
  
  /**
   * change_xattr - change an extended attribute.
   * @c: UBIFS file-system description object
   * @host: host inode
   * @inode: extended attribute inode
   * @value: extended attribute value
   * @size: size of extended attribute value
   *
   * This helper function changes the value of extended attribute @inode with new
   * data from @value. Returns zero in case of success and a negative error code
   * in case of failure.
   */
  static int change_xattr(struct ubifs_info *c, struct inode *host,
  			struct inode *inode, const void *value, int size)
  {
  	int err;
  	struct ubifs_inode *host_ui = ubifs_inode(host);
  	struct ubifs_inode *ui = ubifs_inode(inode);
ab92a20bc   Dongsheng Yang   ubifs: make ubifs...
199
  	void *buf = NULL;
74e9c700b   Pascal Eberhard   ubifs: fix host x...
200
  	int old_size;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
201
  	struct ubifs_budget_req req = { .dirtied_ino = 2,
5acd6ff8a   Zoltan Sogor   UBIFS: fix budget...
202
  		.dirtied_ino_d = ALIGN(size, 8) + ALIGN(host_ui->data_len, 8) };
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
203
204
205
206
207
  
  	ubifs_assert(ui->data_len == inode->i_size);
  	err = ubifs_budget_space(c, &req);
  	if (err)
  		return err;
ab92a20bc   Dongsheng Yang   ubifs: make ubifs...
208
209
  	buf = kmemdup(value, size, GFP_NOFS);
  	if (!buf) {
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
210
  		err = -ENOMEM;
c78c7e35a   Artem Bityutskiy   UBIFS: xattr bugf...
211
  		goto out_free;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
212
  	}
ab92a20bc   Dongsheng Yang   ubifs: make ubifs...
213
214
215
  	mutex_lock(&ui->ui_mutex);
  	kfree(ui->data);
  	ui->data = buf;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
216
  	inode->i_size = ui->ui_size = size;
74e9c700b   Pascal Eberhard   ubifs: fix host x...
217
  	old_size = ui->data_len;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
218
  	ui->data_len = size;
ab92a20bc   Dongsheng Yang   ubifs: make ubifs...
219
  	mutex_unlock(&ui->ui_mutex);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
220

c78c7e35a   Artem Bityutskiy   UBIFS: xattr bugf...
221
222
  	mutex_lock(&host_ui->ui_mutex);
  	host->i_ctime = ubifs_current_time(host);
74e9c700b   Pascal Eberhard   ubifs: fix host x...
223
  	host_ui->xattr_size -= CALC_XATTR_BYTES(old_size);
c78c7e35a   Artem Bityutskiy   UBIFS: xattr bugf...
224
  	host_ui->xattr_size += CALC_XATTR_BYTES(size);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
  	/*
  	 * It is important to write the host inode after the xattr inode
  	 * because if the host inode gets synchronized (via 'fsync()'), then
  	 * the extended attribute inode gets synchronized, because it goes
  	 * before the host inode in the write-buffer.
  	 */
  	err = ubifs_jnl_change_xattr(c, inode, host);
  	if (err)
  		goto out_cancel;
  	mutex_unlock(&host_ui->ui_mutex);
  
  	ubifs_release_budget(c, &req);
  	return 0;
  
  out_cancel:
  	host_ui->xattr_size -= CALC_XATTR_BYTES(size);
74e9c700b   Pascal Eberhard   ubifs: fix host x...
241
  	host_ui->xattr_size += CALC_XATTR_BYTES(old_size);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
242
  	mutex_unlock(&host_ui->ui_mutex);
c78c7e35a   Artem Bityutskiy   UBIFS: xattr bugf...
243
244
  	make_bad_inode(inode);
  out_free:
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
245
246
247
  	ubifs_release_budget(c, &req);
  	return err;
  }
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
248
249
250
251
252
253
  static struct inode *iget_xattr(struct ubifs_info *c, ino_t inum)
  {
  	struct inode *inode;
  
  	inode = ubifs_iget(c->vfs_sb, inum);
  	if (IS_ERR(inode)) {
235c362bd   Sheng Yong   UBIFS: extend deb...
254
  		ubifs_err(c, "dead extended attribute entry, error %d",
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
255
256
257
258
259
  			  (int)PTR_ERR(inode));
  		return inode;
  	}
  	if (ubifs_inode(inode)->xattr)
  		return inode;
235c362bd   Sheng Yong   UBIFS: extend deb...
260
  	ubifs_err(c, "corrupt extended attribute entry");
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
261
262
263
  	iput(inode);
  	return ERR_PTR(-EINVAL);
  }
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
264
  static int __ubifs_setxattr(struct inode *host, const char *name,
298dc6c66   Xiaolei Li   ubifs: Massage as...
265
266
  			    const void *value, size_t size, int flags,
  			    bool check_lock)
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
267
  {
895d9db25   Subodh Nijsure   UBIFS: Add xattr ...
268
  	struct inode *inode;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
269
  	struct ubifs_info *c = host->i_sb->s_fs_info;
26fe57502   Linus Torvalds   vfs: make it poss...
270
  	struct qstr nm = QSTR_INIT(name, strlen(name));
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
271
272
  	struct ubifs_dent_node *xent;
  	union ubifs_key key;
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
273
  	int err;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
274

298dc6c66   Xiaolei Li   ubifs: Massage as...
275
276
  	if (check_lock)
  		ubifs_assert(inode_is_locked(host));
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
277
278
279
  
  	if (size > UBIFS_MAX_INO_DATA)
  		return -ERANGE;
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
280
281
  	if (nm.len > UBIFS_MAX_NLEN)
  		return -ENAMETOOLONG;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
  
  	xent = kmalloc(UBIFS_MAX_XENT_NODE_SZ, GFP_NOFS);
  	if (!xent)
  		return -ENOMEM;
  
  	/*
  	 * The extended attribute entries are stored in LNC, so multiple
  	 * look-ups do not involve reading the flash.
  	 */
  	xent_key_init(c, &key, host->i_ino, &nm);
  	err = ubifs_tnc_lookup_nm(c, &key, xent, &nm);
  	if (err) {
  		if (err != -ENOENT)
  			goto out_free;
  
  		if (flags & XATTR_REPLACE)
  			/* We are asked not to create the xattr */
  			err = -ENODATA;
  		else
  			err = create_xattr(c, host, &nm, value, size);
  		goto out_free;
  	}
  
  	if (flags & XATTR_CREATE) {
  		/* We are asked not to replace the xattr */
  		err = -EEXIST;
  		goto out_free;
  	}
  
  	inode = iget_xattr(c, le64_to_cpu(xent->inum));
  	if (IS_ERR(inode)) {
  		err = PTR_ERR(inode);
  		goto out_free;
  	}
  
  	err = change_xattr(c, host, inode, value, size);
  	iput(inode);
  
  out_free:
  	kfree(xent);
  	return err;
  }
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
324
325
  static ssize_t __ubifs_getxattr(struct inode *host, const char *name,
  				void *buf, size_t size)
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
326
  {
ce23e6401   Al Viro   ->getxattr(): pas...
327
  	struct inode *inode;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
328
  	struct ubifs_info *c = host->i_sb->s_fs_info;
26fe57502   Linus Torvalds   vfs: make it poss...
329
  	struct qstr nm = QSTR_INIT(name, strlen(name));
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
330
331
332
333
  	struct ubifs_inode *ui;
  	struct ubifs_dent_node *xent;
  	union ubifs_key key;
  	int err;
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
334
335
  	if (nm.len > UBIFS_MAX_NLEN)
  		return -ENAMETOOLONG;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
336
337
338
339
  
  	xent = kmalloc(UBIFS_MAX_XENT_NODE_SZ, GFP_NOFS);
  	if (!xent)
  		return -ENOMEM;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
  	xent_key_init(c, &key, host->i_ino, &nm);
  	err = ubifs_tnc_lookup_nm(c, &key, xent, &nm);
  	if (err) {
  		if (err == -ENOENT)
  			err = -ENODATA;
  		goto out_unlock;
  	}
  
  	inode = iget_xattr(c, le64_to_cpu(xent->inum));
  	if (IS_ERR(inode)) {
  		err = PTR_ERR(inode);
  		goto out_unlock;
  	}
  
  	ui = ubifs_inode(inode);
  	ubifs_assert(inode->i_size == ui->data_len);
  	ubifs_assert(ubifs_inode(host)->xattr_size > ui->data_len);
ab92a20bc   Dongsheng Yang   ubifs: make ubifs...
357
  	mutex_lock(&ui->ui_mutex);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
358
359
360
  	if (buf) {
  		/* If @buf is %NULL we are supposed to return the length */
  		if (ui->data_len > size) {
235c362bd   Sheng Yong   UBIFS: extend deb...
361
  			ubifs_err(c, "buffer size %zd, xattr len %d",
a6aae4dd0   Artem Bityutskiy   UBIFS: get rid of...
362
  				  size, ui->data_len);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
363
364
365
366
367
368
369
370
371
  			err = -ERANGE;
  			goto out_iput;
  		}
  
  		memcpy(buf, ui->data, ui->data_len);
  	}
  	err = ui->data_len;
  
  out_iput:
ab92a20bc   Dongsheng Yang   ubifs: make ubifs...
372
  	mutex_unlock(&ui->ui_mutex);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
373
374
  	iput(inode);
  out_unlock:
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
375
376
377
378
379
380
381
  	kfree(xent);
  	return err;
  }
  
  ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size)
  {
  	union ubifs_key key;
2b0143b5c   David Howells   VFS: normal files...
382
  	struct inode *host = d_inode(dentry);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
383
384
385
386
387
  	struct ubifs_info *c = host->i_sb->s_fs_info;
  	struct ubifs_inode *host_ui = ubifs_inode(host);
  	struct ubifs_dent_node *xent, *pxent = NULL;
  	int err, len, written = 0;
  	struct qstr nm = { .name = NULL };
4cb2a01d8   Al Viro   ubifs: switch to %pd
388
389
  	dbg_gen("ino %lu ('%pd'), buffer size %zd", host->i_ino,
  		dentry, size);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
390
391
392
393
394
395
396
397
398
399
400
401
402
  
  	len = host_ui->xattr_names + host_ui->xattr_cnt;
  	if (!buffer)
  		/*
  		 * We should return the minimum buffer size which will fit a
  		 * null-terminated list of all the extended attribute names.
  		 */
  		return len;
  
  	if (len > size)
  		return -ERANGE;
  
  	lowest_xent_key(c, &key, host->i_ino);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
403
  	while (1) {
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
404
  		xent = ubifs_tnc_next_ent(c, &key, &nm);
8d47aef43   Hirofumi Nakagawa   UBIFS: remove unn...
405
  		if (IS_ERR(xent)) {
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
406
407
408
409
410
411
  			err = PTR_ERR(xent);
  			break;
  		}
  
  		nm.name = xent->name;
  		nm.len = le16_to_cpu(xent->nlen);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
412
  		/* Show trusted namespace only for "power" users */
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
413
414
415
  		if (strncmp(xent->name, XATTR_TRUSTED_PREFIX,
  			    XATTR_TRUSTED_PREFIX_LEN) ||
  		    capable(CAP_SYS_ADMIN)) {
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
416
417
418
419
420
421
422
423
  			memcpy(buffer + written, nm.name, nm.len + 1);
  			written += nm.len + 1;
  		}
  
  		kfree(pxent);
  		pxent = xent;
  		key_read(c, &xent->key, &key);
  	}
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
424
425
426
  
  	kfree(pxent);
  	if (err != -ENOENT) {
235c362bd   Sheng Yong   UBIFS: extend deb...
427
  		ubifs_err(c, "cannot find next direntry, error %d", err);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
428
429
430
431
432
433
434
435
436
437
438
439
440
  		return err;
  	}
  
  	ubifs_assert(written <= size);
  	return written;
  }
  
  static int remove_xattr(struct ubifs_info *c, struct inode *host,
  			struct inode *inode, const struct qstr *nm)
  {
  	int err;
  	struct ubifs_inode *host_ui = ubifs_inode(host);
  	struct ubifs_inode *ui = ubifs_inode(inode);
5acd6ff8a   Zoltan Sogor   UBIFS: fix budget...
441
442
  	struct ubifs_budget_req req = { .dirtied_ino = 2, .mod_dent = 1,
  				.dirtied_ino_d = ALIGN(host_ui->data_len, 8) };
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
  
  	ubifs_assert(ui->data_len == inode->i_size);
  
  	err = ubifs_budget_space(c, &req);
  	if (err)
  		return err;
  
  	mutex_lock(&host_ui->ui_mutex);
  	host->i_ctime = ubifs_current_time(host);
  	host_ui->xattr_cnt -= 1;
  	host_ui->xattr_size -= CALC_DENT_SIZE(nm->len);
  	host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len);
  	host_ui->xattr_names -= nm->len;
  
  	err = ubifs_jnl_delete_xattr(c, host, inode, nm);
  	if (err)
  		goto out_cancel;
  	mutex_unlock(&host_ui->ui_mutex);
  
  	ubifs_release_budget(c, &req);
  	return 0;
  
  out_cancel:
  	host_ui->xattr_cnt += 1;
  	host_ui->xattr_size += CALC_DENT_SIZE(nm->len);
  	host_ui->xattr_size += CALC_XATTR_BYTES(ui->data_len);
843741c57   Richard Weinberger   ubifs: Fix xattr_...
469
  	host_ui->xattr_names += nm->len;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
470
471
472
473
474
  	mutex_unlock(&host_ui->ui_mutex);
  	ubifs_release_budget(c, &req);
  	make_bad_inode(inode);
  	return err;
  }
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
475
  static int __ubifs_removexattr(struct inode *host, const char *name)
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
476
  {
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
477
  	struct inode *inode;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
478
  	struct ubifs_info *c = host->i_sb->s_fs_info;
26fe57502   Linus Torvalds   vfs: make it poss...
479
  	struct qstr nm = QSTR_INIT(name, strlen(name));
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
480
481
482
  	struct ubifs_dent_node *xent;
  	union ubifs_key key;
  	int err;
5955102c9   Al Viro   wrappers for ->i_...
483
  	ubifs_assert(inode_is_locked(host));
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
484

2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
485
486
  	if (nm.len > UBIFS_MAX_NLEN)
  		return -ENAMETOOLONG;
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
  
  	xent = kmalloc(UBIFS_MAX_XENT_NODE_SZ, GFP_NOFS);
  	if (!xent)
  		return -ENOMEM;
  
  	xent_key_init(c, &key, host->i_ino, &nm);
  	err = ubifs_tnc_lookup_nm(c, &key, xent, &nm);
  	if (err) {
  		if (err == -ENOENT)
  			err = -ENODATA;
  		goto out_free;
  	}
  
  	inode = iget_xattr(c, le64_to_cpu(xent->inum));
  	if (IS_ERR(inode)) {
  		err = PTR_ERR(inode);
  		goto out_free;
  	}
  
  	ubifs_assert(inode->i_nlink == 1);
6d6b77f16   Miklos Szeredi   filesystems: add ...
507
  	clear_nlink(inode);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
508
509
  	err = remove_xattr(c, host, inode, &nm);
  	if (err)
bfe868486   Miklos Szeredi   filesystems: add ...
510
  		set_nlink(inode, 1);
1e51764a3   Artem Bityutskiy   UBIFS: add new fl...
511
512
513
514
515
516
517
518
  
  	/* If @i_nlink is 0, 'iput()' will delete the inode */
  	iput(inode);
  
  out_free:
  	kfree(xent);
  	return err;
  }
d7f0b70d3   Subodh Nijsure   UBIFS: Add securi...
519

d7f0b70d3   Subodh Nijsure   UBIFS: Add securi...
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
  static int init_xattrs(struct inode *inode, const struct xattr *xattr_array,
  		      void *fs_info)
  {
  	const struct xattr *xattr;
  	char *name;
  	int err = 0;
  
  	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
  		name = kmalloc(XATTR_SECURITY_PREFIX_LEN +
  			       strlen(xattr->name) + 1, GFP_NOFS);
  		if (!name) {
  			err = -ENOMEM;
  			break;
  		}
  		strcpy(name, XATTR_SECURITY_PREFIX);
  		strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
298dc6c66   Xiaolei Li   ubifs: Massage as...
536
537
  		err = __ubifs_setxattr(inode, name, xattr->value,
  				       xattr->value_len, 0, false);
d7f0b70d3   Subodh Nijsure   UBIFS: Add securi...
538
539
540
541
542
543
544
545
546
547
548
549
  		kfree(name);
  		if (err < 0)
  			break;
  	}
  
  	return err;
  }
  
  int ubifs_init_security(struct inode *dentry, struct inode *inode,
  			const struct qstr *qstr)
  {
  	int err;
d7f0b70d3   Subodh Nijsure   UBIFS: Add securi...
550
551
  	err = security_inode_init_security(inode, dentry, qstr,
  					   &init_xattrs, 0);
235c362bd   Sheng Yong   UBIFS: extend deb...
552
553
554
  	if (err) {
  		struct ubifs_info *c = dentry->i_sb->s_fs_info;
  		ubifs_err(c, "cannot initialize security for inode %lu, error %d",
fee1756d8   Subodh Nijsure   UBIFS: add ubifs_...
555
  			  inode->i_ino, err);
235c362bd   Sheng Yong   UBIFS: extend deb...
556
  	}
d7f0b70d3   Subodh Nijsure   UBIFS: Add securi...
557
558
  	return err;
  }
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
559
560
561
562
563
564
565
  
  static int ubifs_xattr_get(const struct xattr_handler *handler,
  			   struct dentry *dentry, struct inode *inode,
  			   const char *name, void *buffer, size_t size)
  {
  	dbg_gen("xattr '%s', ino %lu ('%pd'), buf size %zd", name,
  		inode->i_ino, dentry, size);
17ce1eb0b   Richard Weinberger   ubifs: Fix xattr ...
566
567
  	name = xattr_full_name(handler, name);
  	return __ubifs_getxattr(inode, name, buffer, size);
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
568
569
570
  }
  
  static int ubifs_xattr_set(const struct xattr_handler *handler,
593012268   Al Viro   switch xattr_hand...
571
572
573
  			   struct dentry *dentry, struct inode *inode,
  			   const char *name, const void *value,
  			   size_t size, int flags)
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
574
  {
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
575
576
  	dbg_gen("xattr '%s', host ino %lu ('%pd'), size %zd",
  		name, inode->i_ino, dentry, size);
17ce1eb0b   Richard Weinberger   ubifs: Fix xattr ...
577
  	name = xattr_full_name(handler, name);
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
578
  	if (value)
298dc6c66   Xiaolei Li   ubifs: Massage as...
579
580
  		return __ubifs_setxattr(inode, name, value, size, flags,
  					true);
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
581
582
583
  	else
  		return __ubifs_removexattr(inode, name);
  }
dfaf8d2ae   Ben Dooks   ubifs: Make xattr...
584
  static const struct xattr_handler ubifs_user_xattr_handler = {
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
585
586
587
588
  	.prefix = XATTR_USER_PREFIX,
  	.get = ubifs_xattr_get,
  	.set = ubifs_xattr_set,
  };
dfaf8d2ae   Ben Dooks   ubifs: Make xattr...
589
  static const struct xattr_handler ubifs_trusted_xattr_handler = {
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
590
591
592
593
  	.prefix = XATTR_TRUSTED_PREFIX,
  	.get = ubifs_xattr_get,
  	.set = ubifs_xattr_set,
  };
dfaf8d2ae   Ben Dooks   ubifs: Make xattr...
594
  static const struct xattr_handler ubifs_security_xattr_handler = {
2b88fc21c   Andreas Gruenbacher   ubifs: Switch to ...
595
596
597
598
599
600
601
602
603
604
605
  	.prefix = XATTR_SECURITY_PREFIX,
  	.get = ubifs_xattr_get,
  	.set = ubifs_xattr_set,
  };
  
  const struct xattr_handler *ubifs_xattr_handlers[] = {
  	&ubifs_user_xattr_handler,
  	&ubifs_trusted_xattr_handler,
  	&ubifs_security_xattr_handler,
  	NULL
  };