xattr.c 14.0 KB
Newer Older
J
Jaegeuk Kim 已提交
1
/*
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 * fs/f2fs/xattr.c
 *
 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
 *             http://www.samsung.com/
 *
 * Portions of this code from linux/fs/ext2/xattr.c
 *
 * Copyright (C) 2001-2003 Andreas Gruenbacher <agruen@suse.de>
 *
 * Fix by Harrison Xing <harrison@mountainviewdata.com>.
 * Extended attributes for symlinks and special files added per
 *  suggestion of Luka Renko <luka.renko@hermes.si>.
 * xattr consolidation Copyright (c) 2004 James Morris <jmorris@redhat.com>,
 *  Red Hat Inc.
 *
 * 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.
 */
#include <linux/rwsem.h>
#include <linux/f2fs_fs.h>
23
#include <linux/security.h>
24
#include <linux/posix_acl_xattr.h>
25 26 27
#include "f2fs.h"
#include "xattr.h"

28 29 30
static int f2fs_xattr_generic_get(const struct xattr_handler *handler,
		struct dentry *dentry, const char *name, void *buffer,
		size_t size)
31 32 33
{
	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);

34
	switch (handler->flags) {
35 36 37 38 39 40 41 42
	case F2FS_XATTR_INDEX_USER:
		if (!test_opt(sbi, XATTR_USER))
			return -EOPNOTSUPP;
		break;
	case F2FS_XATTR_INDEX_TRUSTED:
		if (!capable(CAP_SYS_ADMIN))
			return -EPERM;
		break;
43 44
	case F2FS_XATTR_INDEX_SECURITY:
		break;
45 46 47
	default:
		return -EINVAL;
	}
48 49
	return f2fs_getxattr(d_inode(dentry), handler->flags, name,
			     buffer, size, NULL);
50 51
}

52 53 54
static int f2fs_xattr_generic_set(const struct xattr_handler *handler,
		struct dentry *dentry, const char *name, const void *value,
		size_t size, int flags)
55 56 57
{
	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);

58
	switch (handler->flags) {
59 60 61 62 63 64 65 66
	case F2FS_XATTR_INDEX_USER:
		if (!test_opt(sbi, XATTR_USER))
			return -EOPNOTSUPP;
		break;
	case F2FS_XATTR_INDEX_TRUSTED:
		if (!capable(CAP_SYS_ADMIN))
			return -EPERM;
		break;
67 68
	case F2FS_XATTR_INDEX_SECURITY:
		break;
69 70 71
	default:
		return -EINVAL;
	}
72
	return f2fs_setxattr(d_inode(dentry), handler->flags, name,
73
					value, size, NULL, flags);
74 75
}

76
static bool f2fs_xattr_user_list(struct dentry *dentry)
J
Jaegeuk Kim 已提交
77
{
78 79 80 81
	struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);

	return test_opt(sbi, XATTR_USER);
}
J
Jaegeuk Kim 已提交
82

83 84 85
static bool f2fs_xattr_trusted_list(struct dentry *dentry)
{
	return capable(CAP_SYS_ADMIN);
J
Jaegeuk Kim 已提交
86 87
}

88 89 90
static int f2fs_xattr_advise_get(const struct xattr_handler *handler,
		struct dentry *dentry, const char *name, void *buffer,
		size_t size)
J
Jaegeuk Kim 已提交
91
{
92
	struct inode *inode = d_inode(dentry);
J
Jaegeuk Kim 已提交
93

94 95
	if (buffer)
		*((char *)buffer) = F2FS_I(inode)->i_advise;
J
Jaegeuk Kim 已提交
96 97 98
	return sizeof(char);
}

99 100 101
static int f2fs_xattr_advise_set(const struct xattr_handler *handler,
		struct dentry *dentry, const char *name, const void *value,
		size_t size, int flags)
J
Jaegeuk Kim 已提交
102
{
103
	struct inode *inode = d_inode(dentry);
J
Jaegeuk Kim 已提交
104 105 106 107 108 109 110

	if (!inode_owner_or_capable(inode))
		return -EPERM;
	if (value == NULL)
		return -EINVAL;

	F2FS_I(inode)->i_advise |= *(char *)value;
111
	mark_inode_dirty(inode);
J
Jaegeuk Kim 已提交
112 113 114
	return 0;
}

115 116 117 118 119 120 121 122
#ifdef CONFIG_F2FS_FS_SECURITY
static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
		void *page)
{
	const struct xattr *xattr;
	int err = 0;

	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
123
		err = f2fs_setxattr(inode, F2FS_XATTR_INDEX_SECURITY,
124
				xattr->name, xattr->value,
125
				xattr->value_len, (struct page *)page, 0);
126 127 128 129 130 131 132 133 134 135 136 137 138 139
		if (err < 0)
			break;
	}
	return err;
}

int f2fs_init_security(struct inode *inode, struct inode *dir,
				const struct qstr *qstr, struct page *ipage)
{
	return security_inode_init_security(inode, dir, qstr,
				&f2fs_initxattrs, ipage);
}
#endif

140 141 142
const struct xattr_handler f2fs_xattr_user_handler = {
	.prefix	= XATTR_USER_PREFIX,
	.flags	= F2FS_XATTR_INDEX_USER,
143
	.list	= f2fs_xattr_user_list,
144 145 146 147 148 149 150
	.get	= f2fs_xattr_generic_get,
	.set	= f2fs_xattr_generic_set,
};

const struct xattr_handler f2fs_xattr_trusted_handler = {
	.prefix	= XATTR_TRUSTED_PREFIX,
	.flags	= F2FS_XATTR_INDEX_TRUSTED,
151
	.list	= f2fs_xattr_trusted_list,
152 153 154 155
	.get	= f2fs_xattr_generic_get,
	.set	= f2fs_xattr_generic_set,
};

J
Jaegeuk Kim 已提交
156
const struct xattr_handler f2fs_xattr_advise_handler = {
157
	.name	= F2FS_SYSTEM_ADVISE_NAME,
J
Jaegeuk Kim 已提交
158 159 160 161 162
	.flags	= F2FS_XATTR_INDEX_ADVISE,
	.get    = f2fs_xattr_advise_get,
	.set    = f2fs_xattr_advise_set,
};

163 164 165 166 167 168 169
const struct xattr_handler f2fs_xattr_security_handler = {
	.prefix	= XATTR_SECURITY_PREFIX,
	.flags	= F2FS_XATTR_INDEX_SECURITY,
	.get	= f2fs_xattr_generic_get,
	.set	= f2fs_xattr_generic_set,
};

170 171 172
static const struct xattr_handler *f2fs_xattr_handler_map[] = {
	[F2FS_XATTR_INDEX_USER] = &f2fs_xattr_user_handler,
#ifdef CONFIG_F2FS_FS_POSIX_ACL
173 174
	[F2FS_XATTR_INDEX_POSIX_ACL_ACCESS] = &posix_acl_access_xattr_handler,
	[F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler,
175 176
#endif
	[F2FS_XATTR_INDEX_TRUSTED] = &f2fs_xattr_trusted_handler,
177 178 179
#ifdef CONFIG_F2FS_FS_SECURITY
	[F2FS_XATTR_INDEX_SECURITY] = &f2fs_xattr_security_handler,
#endif
180 181 182 183 184 185
	[F2FS_XATTR_INDEX_ADVISE] = &f2fs_xattr_advise_handler,
};

const struct xattr_handler *f2fs_xattr_handlers[] = {
	&f2fs_xattr_user_handler,
#ifdef CONFIG_F2FS_FS_POSIX_ACL
186 187
	&posix_acl_access_xattr_handler,
	&posix_acl_default_xattr_handler,
188 189
#endif
	&f2fs_xattr_trusted_handler,
190 191 192
#ifdef CONFIG_F2FS_FS_SECURITY
	&f2fs_xattr_security_handler,
#endif
193 194 195 196
	&f2fs_xattr_advise_handler,
	NULL,
};

J
Jaegeuk Kim 已提交
197
static inline const struct xattr_handler *f2fs_xattr_handler(int index)
198 199 200
{
	const struct xattr_handler *handler = NULL;

J
Jaegeuk Kim 已提交
201 202
	if (index > 0 && index < ARRAY_SIZE(f2fs_xattr_handler_map))
		handler = f2fs_xattr_handler_map[index];
203 204 205
	return handler;
}

J
Jaegeuk Kim 已提交
206 207
static struct f2fs_xattr_entry *__find_xattr(void *base_addr, int index,
					size_t len, const char *name)
208 209 210 211
{
	struct f2fs_xattr_entry *entry;

	list_for_each_xattr(entry, base_addr) {
J
Jaegeuk Kim 已提交
212
		if (entry->e_name_index != index)
213
			continue;
J
Jaegeuk Kim 已提交
214
		if (entry->e_name_len != len)
215
			continue;
J
Jaegeuk Kim 已提交
216
		if (!memcmp(entry->e_name, name, len))
217 218 219 220 221
			break;
	}
	return entry;
}

J
Jaegeuk Kim 已提交
222 223
static void *read_all_xattrs(struct inode *inode, struct page *ipage)
{
224
	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
J
Jaegeuk Kim 已提交
225 226 227 228 229 230
	struct f2fs_xattr_header *header;
	size_t size = PAGE_SIZE, inline_size = 0;
	void *txattr_addr;

	inline_size = inline_xattr_size(inode);

231
	txattr_addr = kzalloc(inline_size + size, GFP_F2FS_ZERO);
J
Jaegeuk Kim 已提交
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
	if (!txattr_addr)
		return NULL;

	/* read from inline xattr */
	if (inline_size) {
		struct page *page = NULL;
		void *inline_addr;

		if (ipage) {
			inline_addr = inline_xattr_addr(ipage);
		} else {
			page = get_node_page(sbi, inode->i_ino);
			if (IS_ERR(page))
				goto fail;
			inline_addr = inline_xattr_addr(page);
		}
		memcpy(txattr_addr, inline_addr, inline_size);
		f2fs_put_page(page, 1);
	}

	/* read from xattr node block */
	if (F2FS_I(inode)->i_xattr_nid) {
		struct page *xpage;
		void *xattr_addr;

		/* The inode already has an extended attribute block. */
		xpage = get_node_page(sbi, F2FS_I(inode)->i_xattr_nid);
		if (IS_ERR(xpage))
			goto fail;

		xattr_addr = page_address(xpage);
		memcpy(txattr_addr + inline_size, xattr_addr, PAGE_SIZE);
		f2fs_put_page(xpage, 1);
	}

	header = XATTR_HDR(txattr_addr);

	/* never been allocated xattrs */
	if (le32_to_cpu(header->h_magic) != F2FS_XATTR_MAGIC) {
		header->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC);
		header->h_refcount = cpu_to_le32(1);
	}
	return txattr_addr;
fail:
	kzfree(txattr_addr);
	return NULL;
}

static inline int write_all_xattrs(struct inode *inode, __u32 hsize,
				void *txattr_addr, struct page *ipage)
{
283
	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
J
Jaegeuk Kim 已提交
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
	size_t inline_size = 0;
	void *xattr_addr;
	struct page *xpage;
	nid_t new_nid = 0;
	int err;

	inline_size = inline_xattr_size(inode);

	if (hsize > inline_size && !F2FS_I(inode)->i_xattr_nid)
		if (!alloc_nid(sbi, &new_nid))
			return -ENOSPC;

	/* write to inline xattr */
	if (inline_size) {
		struct page *page = NULL;
		void *inline_addr;

		if (ipage) {
			inline_addr = inline_xattr_addr(ipage);
303
			f2fs_wait_on_page_writeback(ipage, NODE);
J
Jaegeuk Kim 已提交
304 305 306 307 308 309 310
		} else {
			page = get_node_page(sbi, inode->i_ino);
			if (IS_ERR(page)) {
				alloc_nid_failed(sbi, new_nid);
				return PTR_ERR(page);
			}
			inline_addr = inline_xattr_addr(page);
311
			f2fs_wait_on_page_writeback(page, NODE);
J
Jaegeuk Kim 已提交
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
		}
		memcpy(inline_addr, txattr_addr, inline_size);
		f2fs_put_page(page, 1);

		/* no need to use xattr node block */
		if (hsize <= inline_size) {
			err = truncate_xattr_node(inode, ipage);
			alloc_nid_failed(sbi, new_nid);
			return err;
		}
	}

	/* write to xattr node block */
	if (F2FS_I(inode)->i_xattr_nid) {
		xpage = get_node_page(sbi, F2FS_I(inode)->i_xattr_nid);
		if (IS_ERR(xpage)) {
			alloc_nid_failed(sbi, new_nid);
			return PTR_ERR(xpage);
		}
331
		f2fs_bug_on(sbi, new_nid);
332
		f2fs_wait_on_page_writeback(xpage, NODE);
J
Jaegeuk Kim 已提交
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
	} else {
		struct dnode_of_data dn;
		set_new_dnode(&dn, inode, NULL, NULL, new_nid);
		xpage = new_node_page(&dn, XATTR_NODE_OFFSET, ipage);
		if (IS_ERR(xpage)) {
			alloc_nid_failed(sbi, new_nid);
			return PTR_ERR(xpage);
		}
		alloc_nid_done(sbi, new_nid);
	}

	xattr_addr = page_address(xpage);
	memcpy(xattr_addr, txattr_addr + inline_size, PAGE_SIZE -
						sizeof(struct node_footer));
	set_page_dirty(xpage);
	f2fs_put_page(xpage, 1);

	/* need to checkpoint during fsync */
	F2FS_I(inode)->xattr_ver = cur_cp_version(F2FS_CKPT(sbi));
	return 0;
}

J
Jaegeuk Kim 已提交
355
int f2fs_getxattr(struct inode *inode, int index, const char *name,
356
		void *buffer, size_t buffer_size, struct page *ipage)
357 358
{
	struct f2fs_xattr_entry *entry;
J
Jaegeuk Kim 已提交
359
	void *base_addr;
360
	int error = 0;
J
Jaegeuk Kim 已提交
361
	size_t size, len;
362 363 364

	if (name == NULL)
		return -EINVAL;
J
Jaegeuk Kim 已提交
365 366 367

	len = strlen(name);
	if (len > F2FS_NAME_LEN)
368
		return -ERANGE;
369

370
	base_addr = read_all_xattrs(inode, ipage);
J
Jaegeuk Kim 已提交
371 372
	if (!base_addr)
		return -ENOMEM;
373

J
Jaegeuk Kim 已提交
374
	entry = __find_xattr(base_addr, index, len, name);
375
	if (IS_XATTR_LAST_ENTRY(entry)) {
376 377 378 379
		error = -ENODATA;
		goto cleanup;
	}

J
Jaegeuk Kim 已提交
380
	size = le16_to_cpu(entry->e_value_size);
381

J
Jaegeuk Kim 已提交
382
	if (buffer && size > buffer_size) {
383 384 385 386 387 388
		error = -ERANGE;
		goto cleanup;
	}

	if (buffer) {
		char *pval = entry->e_name + entry->e_name_len;
J
Jaegeuk Kim 已提交
389
		memcpy(buffer, pval, size);
390
	}
J
Jaegeuk Kim 已提交
391
	error = size;
392 393

cleanup:
J
Jaegeuk Kim 已提交
394
	kzfree(base_addr);
395 396 397 398 399
	return error;
}

ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
{
400
	struct inode *inode = d_inode(dentry);
401 402 403 404 405
	struct f2fs_xattr_entry *entry;
	void *base_addr;
	int error = 0;
	size_t rest = buffer_size;

J
Jaegeuk Kim 已提交
406 407 408
	base_addr = read_all_xattrs(inode, NULL);
	if (!base_addr)
		return -ENOMEM;
409 410 411 412

	list_for_each_xattr(entry, base_addr) {
		const struct xattr_handler *handler =
			f2fs_xattr_handler(entry->e_name_index);
413 414
		const char *prefix;
		size_t prefix_len;
415 416
		size_t size;

417
		if (!handler || (handler->list && !handler->list(dentry)))
418 419
			continue;

420 421 422 423 424 425 426 427 428 429 430 431 432
		prefix = handler->prefix ?: handler->name;
		prefix_len = strlen(prefix);
		size = prefix_len + entry->e_name_len + 1;
		if (buffer) {
			if (size > rest) {
				error = -ERANGE;
				goto cleanup;
			}
			memcpy(buffer, prefix, prefix_len);
			buffer += prefix_len;
			memcpy(buffer, entry->e_name, entry->e_name_len);
			buffer += entry->e_name_len;
			*buffer++ = 0;
433 434 435 436 437
		}
		rest -= size;
	}
	error = buffer_size - rest;
cleanup:
J
Jaegeuk Kim 已提交
438
	kzfree(base_addr);
439 440 441
	return error;
}

J
Jaegeuk Kim 已提交
442 443
static int __f2fs_setxattr(struct inode *inode, int index,
			const char *name, const void *value, size_t size,
444
			struct page *ipage, int flags)
445 446 447 448
{
	struct f2fs_inode_info *fi = F2FS_I(inode);
	struct f2fs_xattr_entry *here, *last;
	void *base_addr;
J
Jaegeuk Kim 已提交
449
	int found, newsize;
J
Jaegeuk Kim 已提交
450
	size_t len;
J
Jaegeuk Kim 已提交
451 452
	__u32 new_hsize;
	int error = -ENOMEM;
453 454 455 456 457

	if (name == NULL)
		return -EINVAL;

	if (value == NULL)
J
Jaegeuk Kim 已提交
458
		size = 0;
459

J
Jaegeuk Kim 已提交
460
	len = strlen(name);
N
Namjae Jeon 已提交
461

462
	if (len > F2FS_NAME_LEN)
463 464
		return -ERANGE;

465 466 467
	if (size > MAX_VALUE_LEN(inode))
		return -E2BIG;

J
Jaegeuk Kim 已提交
468 469 470
	base_addr = read_all_xattrs(inode, ipage);
	if (!base_addr)
		goto exit;
471 472

	/* find entry with wanted name. */
J
Jaegeuk Kim 已提交
473
	here = __find_xattr(base_addr, index, len, name);
474

475
	found = IS_XATTR_LAST_ENTRY(here) ? 0 : 1;
476

477 478 479 480 481 482 483 484 485
	if ((flags & XATTR_REPLACE) && !found) {
		error = -ENODATA;
		goto exit;
	} else if ((flags & XATTR_CREATE) && found) {
		error = -EEXIST;
		goto exit;
	}

	last = here;
486 487 488
	while (!IS_XATTR_LAST_ENTRY(last))
		last = XATTR_NEXT_ENTRY(last);

J
Jaegeuk Kim 已提交
489
	newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) + len + size);
490 491 492

	/* 1. Check space */
	if (value) {
J
Jaegeuk Kim 已提交
493 494 495
		int free;
		/*
		 * If value is NULL, it is remove operation.
A
arter97 已提交
496
		 * In case of update operation, we calculate free.
497
		 */
J
Jaegeuk Kim 已提交
498
		free = MIN_OFFSET(inode) - ((char *)last - (char *)base_addr);
499
		if (found)
500
			free = free + ENTRY_SIZE(here);
501

502
		if (unlikely(free < newsize)) {
503
			error = -ENOSPC;
J
Jaegeuk Kim 已提交
504
			goto exit;
505 506 507 508 509
		}
	}

	/* 2. Remove old entry */
	if (found) {
J
Jaegeuk Kim 已提交
510 511
		/*
		 * If entry is found, remove old entry.
512 513 514 515 516 517 518 519 520 521
		 * If not found, remove operation is not needed.
		 */
		struct f2fs_xattr_entry *next = XATTR_NEXT_ENTRY(here);
		int oldsize = ENTRY_SIZE(here);

		memmove(here, next, (char *)last - (char *)next);
		last = (struct f2fs_xattr_entry *)((char *)last - oldsize);
		memset(last, 0, oldsize);
	}

J
Jaegeuk Kim 已提交
522 523
	new_hsize = (char *)last - (char *)base_addr;

524 525
	/* 3. Write new entry */
	if (value) {
J
Jaegeuk Kim 已提交
526 527 528 529 530
		char *pval;
		/*
		 * Before we come here, old entry is removed.
		 * We just write new entry.
		 */
531
		memset(last, 0, newsize);
J
Jaegeuk Kim 已提交
532 533 534 535 536 537
		last->e_name_index = index;
		last->e_name_len = len;
		memcpy(last->e_name, name, len);
		pval = last->e_name + len;
		memcpy(pval, value, size);
		last->e_value_size = cpu_to_le16(size);
J
Jaegeuk Kim 已提交
538
		new_hsize += newsize;
539 540
	}

J
Jaegeuk Kim 已提交
541 542 543
	error = write_all_xattrs(inode, new_hsize, base_addr, ipage);
	if (error)
		goto exit;
544 545 546 547 548 549

	if (is_inode_flag_set(fi, FI_ACL_MODE)) {
		inode->i_mode = fi->i_acl_mode;
		inode->i_ctime = CURRENT_TIME;
		clear_inode_flag(fi, FI_ACL_MODE);
	}
550 551 552
	if (index == F2FS_XATTR_INDEX_ENCRYPTION &&
			!strcmp(name, F2FS_XATTR_NAME_ENCRYPTION_CONTEXT))
		f2fs_set_encrypted_inode(inode);
553

554 555 556 557
	if (ipage)
		update_inode(inode, ipage);
	else
		update_inode_page(inode);
N
Namjae Jeon 已提交
558
exit:
J
Jaegeuk Kim 已提交
559
	kzfree(base_addr);
560 561
	return error;
}
562

J
Jaegeuk Kim 已提交
563 564
int f2fs_setxattr(struct inode *inode, int index, const char *name,
				const void *value, size_t size,
565
				struct page *ipage, int flags)
566
{
567
	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
568 569
	int err;

570 571 572 573
	/* this case is only from init_inode_metadata */
	if (ipage)
		return __f2fs_setxattr(inode, index, name, value,
						size, ipage, flags);
J
Jaegeuk Kim 已提交
574
	f2fs_balance_fs(sbi, true);
575

576
	f2fs_lock_op(sbi);
577 578
	/* protect xattr_ver */
	down_write(&F2FS_I(inode)->i_sem);
579
	err = __f2fs_setxattr(inode, index, name, value, size, ipage, flags);
580
	up_write(&F2FS_I(inode)->i_sem);
581
	f2fs_unlock_op(sbi);
582

583
	f2fs_update_time(sbi, REQ_TIME);
584 585
	return err;
}