diff options
author | David Sterba <dsterba@suse.cz> | 2015-03-25 14:26:41 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2015-03-26 21:10:24 -0400 |
commit | 3c3b04d10ff1811a27f86684ccd2f5ba6983211d (patch) | |
tree | 3ad3d87edc735b1f2445fe92e9d5610ea367af32 /fs/btrfs/xattr.c | |
parent | dcc82f4783ad91d4ab654f89f37ae9291cdc846a (diff) |
btrfs: don't accept bare namespace as a valid xattr
Due to insufficient check in btrfs_is_valid_xattr, this unexpectedly
works:
$ touch file
$ setfattr -n user. -v 1 file
$ getfattr -d file
user.="1"
ie. the missing attribute name after the namespace.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=94291
Reported-by: William Douglas <william.douglas@intel.com>
CC: <stable@vger.kernel.org> # 2.6.29+
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/xattr.c')
-rw-r--r-- | fs/btrfs/xattr.c | 53 |
1 files changed, 39 insertions, 14 deletions
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 883b93623bc5..45ea704be030 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c | |||
@@ -364,22 +364,42 @@ const struct xattr_handler *btrfs_xattr_handlers[] = { | |||
364 | /* | 364 | /* |
365 | * Check if the attribute is in a supported namespace. | 365 | * Check if the attribute is in a supported namespace. |
366 | * | 366 | * |
367 | * This applied after the check for the synthetic attributes in the system | 367 | * This is applied after the check for the synthetic attributes in the system |
368 | * namespace. | 368 | * namespace. |
369 | */ | 369 | */ |
370 | static bool btrfs_is_valid_xattr(const char *name) | 370 | static int btrfs_is_valid_xattr(const char *name) |
371 | { | 371 | { |
372 | return !strncmp(name, XATTR_SECURITY_PREFIX, | 372 | int len = strlen(name); |
373 | XATTR_SECURITY_PREFIX_LEN) || | 373 | int prefixlen = 0; |
374 | !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) || | 374 | |
375 | !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) || | 375 | if (!strncmp(name, XATTR_SECURITY_PREFIX, |
376 | !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) || | 376 | XATTR_SECURITY_PREFIX_LEN)) |
377 | !strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN); | 377 | prefixlen = XATTR_SECURITY_PREFIX_LEN; |
378 | else if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) | ||
379 | prefixlen = XATTR_SYSTEM_PREFIX_LEN; | ||
380 | else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) | ||
381 | prefixlen = XATTR_TRUSTED_PREFIX_LEN; | ||
382 | else if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) | ||
383 | prefixlen = XATTR_USER_PREFIX_LEN; | ||
384 | else if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN)) | ||
385 | prefixlen = XATTR_BTRFS_PREFIX_LEN; | ||
386 | else | ||
387 | return -EOPNOTSUPP; | ||
388 | |||
389 | /* | ||
390 | * The name cannot consist of just prefix | ||
391 | */ | ||
392 | if (len <= prefixlen) | ||
393 | return -EINVAL; | ||
394 | |||
395 | return 0; | ||
378 | } | 396 | } |
379 | 397 | ||
380 | ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, | 398 | ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, |
381 | void *buffer, size_t size) | 399 | void *buffer, size_t size) |
382 | { | 400 | { |
401 | int ret; | ||
402 | |||
383 | /* | 403 | /* |
384 | * If this is a request for a synthetic attribute in the system.* | 404 | * If this is a request for a synthetic attribute in the system.* |
385 | * namespace use the generic infrastructure to resolve a handler | 405 | * namespace use the generic infrastructure to resolve a handler |
@@ -388,8 +408,9 @@ ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, | |||
388 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) | 408 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) |
389 | return generic_getxattr(dentry, name, buffer, size); | 409 | return generic_getxattr(dentry, name, buffer, size); |
390 | 410 | ||
391 | if (!btrfs_is_valid_xattr(name)) | 411 | ret = btrfs_is_valid_xattr(name); |
392 | return -EOPNOTSUPP; | 412 | if (ret) |
413 | return ret; | ||
393 | return __btrfs_getxattr(dentry->d_inode, name, buffer, size); | 414 | return __btrfs_getxattr(dentry->d_inode, name, buffer, size); |
394 | } | 415 | } |
395 | 416 | ||
@@ -397,6 +418,7 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, | |||
397 | size_t size, int flags) | 418 | size_t size, int flags) |
398 | { | 419 | { |
399 | struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root; | 420 | struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root; |
421 | int ret; | ||
400 | 422 | ||
401 | /* | 423 | /* |
402 | * The permission on security.* and system.* is not checked | 424 | * The permission on security.* and system.* is not checked |
@@ -413,8 +435,9 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, | |||
413 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) | 435 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) |
414 | return generic_setxattr(dentry, name, value, size, flags); | 436 | return generic_setxattr(dentry, name, value, size, flags); |
415 | 437 | ||
416 | if (!btrfs_is_valid_xattr(name)) | 438 | ret = btrfs_is_valid_xattr(name); |
417 | return -EOPNOTSUPP; | 439 | if (ret) |
440 | return ret; | ||
418 | 441 | ||
419 | if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN)) | 442 | if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN)) |
420 | return btrfs_set_prop(dentry->d_inode, name, | 443 | return btrfs_set_prop(dentry->d_inode, name, |
@@ -430,6 +453,7 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, | |||
430 | int btrfs_removexattr(struct dentry *dentry, const char *name) | 453 | int btrfs_removexattr(struct dentry *dentry, const char *name) |
431 | { | 454 | { |
432 | struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root; | 455 | struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root; |
456 | int ret; | ||
433 | 457 | ||
434 | /* | 458 | /* |
435 | * The permission on security.* and system.* is not checked | 459 | * The permission on security.* and system.* is not checked |
@@ -446,8 +470,9 @@ int btrfs_removexattr(struct dentry *dentry, const char *name) | |||
446 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) | 470 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) |
447 | return generic_removexattr(dentry, name); | 471 | return generic_removexattr(dentry, name); |
448 | 472 | ||
449 | if (!btrfs_is_valid_xattr(name)) | 473 | ret = btrfs_is_valid_xattr(name); |
450 | return -EOPNOTSUPP; | 474 | if (ret) |
475 | return ret; | ||
451 | 476 | ||
452 | if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN)) | 477 | if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN)) |
453 | return btrfs_set_prop(dentry->d_inode, name, | 478 | return btrfs_set_prop(dentry->d_inode, name, |