From b1de5fd8f480bb6cd034242c49a1f85ff6c21e51 Mon Sep 17 00:00:00 2001 From: Raghavendra Bhat Date: Wed, 24 Jun 2015 20:06:01 +0530 Subject: [PATCH 186/190] features/bit-rot-stub: do not allow setxattr and removexattr on bit-rot xattrs Backport of http://review.gluster.org/11389 * setxattr and {f}removexattr of versioning, signature and bad-file xattrs are returned with error. Change-Id: I21b25e06b6b78309c0ddd155345fec8765e03352 BUG: 1224227 Reviewed-on: https://code.engineering.redhat.com/gerrit/51758 Reviewed-by: Venky Shankar Tested-by: Venky Shankar --- .../bit-rot/src/stub/bit-rot-stub-messages.h | 10 ++- xlators/features/bit-rot/src/stub/bit-rot-stub.c | 103 ++++++++++++++++++- 2 files changed, 106 insertions(+), 7 deletions(-) diff --git a/xlators/features/bit-rot/src/stub/bit-rot-stub-messages.h b/xlators/features/bit-rot/src/stub/bit-rot-stub-messages.h index db5736a..532c2be 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-stub-messages.h +++ b/xlators/features/bit-rot/src/stub/bit-rot-stub-messages.h @@ -167,7 +167,14 @@ * @recommendedaction * */ -#define BRS_MSG_REMOVE_BAD_OBJECT_XATTR (GLFS_BITROT_STUB_BASE + 18) +#define BRS_MSG_REMOVE_INTERNAL_XATTR (GLFS_BITROT_STUB_BASE + 18) +/*! + * @messageid + * @diagnosis + * @recommendedaction + * + */ +#define BRS_MSG_SET_INTERNAL_XATTR (GLFS_BITROT_STUB_BASE + 19) /*! * @messageid * @diagnosis @@ -182,5 +189,6 @@ * */ /*------------*/ + #define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages" #endif /* !_BITROT_STUB_MESSAGES_H_ */ diff --git a/xlators/features/bit-rot/src/stub/bit-rot-stub.c b/xlators/features/bit-rot/src/stub/bit-rot-stub.c index de81510..41c8359 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-stub.c +++ b/xlators/features/bit-rot/src/stub/bit-rot-stub.c @@ -993,6 +993,37 @@ unwind: return 0; } + +/** + * As of now, versioning is done by the stub (though as a setxattr + * operation) as part of inode modification operations such as writev, + * truncate, ftruncate. And signing is done by BitD by a fsetxattr call. + * So any kind of setxattr coming on the versioning and the signing xattr is + * not allowed (i.e. BITROT_CURRENT_VERSION_KEY and BITROT_SIGNING_VERSION_KEY). + * In future if BitD/scrubber are allowed to change the versioning + * xattrs (though I cannot see a reason for it as of now), then the below + * function can be modified to block setxattr on version for only applications. + * + * NOTE: BitD sends sign request on GLUSTERFS_SET_OBJECT_SIGNATURE key. + * BITROT_SIGNING_VERSION_KEY is the xattr used to save the signature. + * + */ +static int32_t +br_stub_handle_internal_xattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + char *key) +{ + int32_t op_ret = -1; + int32_t op_errno = EINVAL; + + gf_msg (this->name, GF_LOG_ERROR, 0, + BRS_MSG_SET_INTERNAL_XATTR, "setxattr called" + " on the internal xattr %s for inode %s", key, + uuid_utoa (fd->inode->gfid)); + + STACK_UNWIND_STRICT (fsetxattr, frame, op_ret, op_errno, NULL); + return 0; +} + int br_stub_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, int flags, dict_t *xdata) @@ -1013,6 +1044,20 @@ br_stub_fsetxattr (call_frame_t *frame, xlator_t *this, goto done; } + /* signing xattr */ + if (dict_get(dict, BITROT_SIGNING_VERSION_KEY)) { + br_stub_handle_internal_xattr (frame, this, fd, + BITROT_SIGNING_VERSION_KEY); + goto done; + } + + /* version xattr */ + if (dict_get(dict, BITROT_CURRENT_VERSION_KEY)) { + br_stub_handle_internal_xattr (frame, this, fd, + BITROT_CURRENT_VERSION_KEY); + goto done; + } + /* object reopen request */ ret = dict_get_uint32 (dict, BR_REOPEN_SIGN_HINT_KEY, &val); if (!ret) { @@ -1035,6 +1080,45 @@ done: return 0; } + +/** + * Currently BitD and scrubber are doing fsetxattr to either sign the object + * or to mark it as bad. Hence setxattr on any of those keys is denied directly + * without checking from where the fop is coming. + * Later, if BitD or Scrubber does setxattr of those keys, then appropriate + * check has to be added below. + */ +int +br_stub_setxattr (call_frame_t *frame, xlator_t *this, + loc_t *loc, dict_t *dict, int flags, dict_t *xdata) +{ + int32_t op_ret = -1; + int32_t op_errno = EINVAL; + char dump[64*1024] = {0,}; + char *format = "(%s:%s)"; + + if (dict_get (dict, GLUSTERFS_SET_OBJECT_SIGNATURE) || + dict_get (dict, BR_REOPEN_SIGN_HINT_KEY) || + dict_get (dict, BITROT_OBJECT_BAD_KEY) || + dict_get (dict, BITROT_SIGNING_VERSION_KEY) || + dict_get (dict, BITROT_CURRENT_VERSION_KEY)) { + dict_dump_to_str (dict, dump, sizeof(dump), format); + gf_msg (this->name, GF_LOG_ERROR, 0, + BRS_MSG_SET_INTERNAL_XATTR, "setxattr called on " + "internal xattr %s", dump); + goto unwind; + } + + + STACK_WIND_TAIL (frame, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->setxattr, loc, dict, flags, + xdata); + return 0; +unwind: + STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno, NULL); + return 0; +} + /** }}} */ @@ -1049,13 +1133,16 @@ br_stub_removexattr (call_frame_t *frame, xlator_t *this, int32_t op_ret = -1; int32_t op_errno = EINVAL; - if (!strcmp (BITROT_OBJECT_BAD_KEY, name)) { + if (!strcmp (BITROT_OBJECT_BAD_KEY, name) || + !strcmp (BITROT_SIGNING_VERSION_KEY, name) || + !strcmp (BITROT_CURRENT_VERSION_KEY, name)) { gf_msg (this->name, GF_LOG_WARNING, 0, - BRS_MSG_REMOVE_BAD_OBJECT_XATTR, "Remove xattr called" - " on bad object xattr for file %s", loc->path); + BRS_MSG_REMOVE_INTERNAL_XATTR, "removexattr called" + " on internal xattr %s for file %s", name, loc->path); goto unwind; } + STACK_WIND_TAIL (frame, FIRST_CHILD(this), FIRST_CHILD(this)->fops->removexattr, loc, name, xdata); @@ -1072,14 +1159,17 @@ br_stub_fremovexattr (call_frame_t *frame, xlator_t *this, int32_t op_ret = -1; int32_t op_errno = EINVAL; - if (!strcmp (BITROT_OBJECT_BAD_KEY, name)) { + if (!strcmp (BITROT_OBJECT_BAD_KEY, name) || + !strcmp (BITROT_SIGNING_VERSION_KEY, name) || + !strcmp (BITROT_CURRENT_VERSION_KEY, name)) { gf_msg (this->name, GF_LOG_WARNING, 0, - BRS_MSG_REMOVE_BAD_OBJECT_XATTR, "Remove xattr called" - " on bad object xattr for inode %s", + BRS_MSG_REMOVE_INTERNAL_XATTR, "removexattr called" + " on internal xattr %s for inode %s", name, uuid_utoa (fd->inode->gfid)); goto unwind; } + STACK_WIND_TAIL (frame, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fremovexattr, fd, name, xdata); @@ -2593,6 +2683,7 @@ struct xlator_fops fops = { .readv = br_stub_readv, .removexattr = br_stub_removexattr, .fremovexattr = br_stub_fremovexattr, + .setxattr = br_stub_setxattr, }; struct xlator_cbks cbks = { -- 1.7.1