From 5144d3d5a4982a86f46ef023d0dc836d0fdead58 Mon Sep 17 00:00:00 2001 From: Raghavendra Bhat Date: Tue, 26 May 2015 19:22:14 +0530 Subject: features/bit-rot-stub: deny access to bad objects Backport of http://review.gluster.org/11126 * Access to bad objects (especially operations such as open, readv, writev) should be denied to prevent applications from getting wrong data. * Do not allow anyone apart from scrubber to set bad object xattr. * Do not allow bad object xattr to be removed. Change-Id: I6903184ab64a9d1ea595330b603935979c33bc26 BUG: 1241529 Reviewed-on: http://review.gluster.org/11603 Tested-by: NetBSD Build System Tested-by: Gluster Build System Reviewed-by: Venky Shankar --- xlators/features/bit-rot/src/stub/bit-rot-stub.h | 94 ++++++++++++++++++++++++ 1 file changed, 94 insertions(+) (limited to 'xlators/features/bit-rot/src/stub/bit-rot-stub.h') diff --git a/xlators/features/bit-rot/src/stub/bit-rot-stub.h b/xlators/features/bit-rot/src/stub/bit-rot-stub.h index 48c7a371e43..e5649fc2142 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-stub.h +++ b/xlators/features/bit-rot/src/stub/bit-rot-stub.h @@ -37,6 +37,7 @@ typedef struct br_stub_inode_ctx { int info_sign; struct list_head fd_list; /* list of open fds or fds participating in write operations */ + gf_boolean_t bad_object; } br_stub_inode_ctx_t; typedef struct br_stub_fd { @@ -85,6 +86,18 @@ typedef struct br_stub_private { struct mem_pool *local_pool; } br_stub_private_t; +static inline gf_boolean_t +__br_stub_is_bad_object (br_stub_inode_ctx_t *ctx) +{ + return ctx->bad_object; +} + +static inline void +__br_stub_mark_object_bad (br_stub_inode_ctx_t *ctx) +{ + ctx->bad_object = _gf_true; +} + /* inode writeback helpers */ static inline void __br_stub_mark_inode_dirty (br_stub_inode_ctx_t *ctx) @@ -370,12 +383,93 @@ static inline void br_stub_remove_vxattrs (dict_t *xattr) { if (xattr) { + dict_del (xattr, BITROT_OBJECT_BAD_KEY); dict_del (xattr, BITROT_CURRENT_VERSION_KEY); dict_del (xattr, BITROT_SIGNING_VERSION_KEY); dict_del (xattr, BITROT_SIGNING_XATTR_SIZE_KEY); } } +#define BR_STUB_HANDLE_BAD_OBJECT(this, inode, op_ret, op_errno, label) \ + do { \ + if (br_stub_is_bad_object (this, inode)) { \ + gf_msg (this->name, GF_LOG_ERROR, 0, \ + BRS_MSG_BAD_OBJECT_ACCESS, \ + "%s is a bad object. Returning", \ + uuid_utoa (inode->gfid)); \ + op_ret = -1; \ + op_errno = EIO; \ + goto label; \ + } \ + } while (0) + +static inline gf_boolean_t +br_stub_is_bad_object (xlator_t *this, inode_t *inode) +{ + gf_boolean_t bad_object = _gf_false; + uint64_t ctx_addr = 0; + br_stub_inode_ctx_t *ctx = NULL; + int32_t ret = -1; + + ret = br_stub_get_inode_ctx (this, inode, &ctx_addr); + if (ret) { + gf_msg (this->name, GF_LOG_ERROR, 0, BRS_MSG_SET_CONTEXT_FAILED, + "failed to get the inode context for the inode %s", + uuid_utoa (inode->gfid)); + goto out; + } + + ctx = (br_stub_inode_ctx_t *)(long)ctx_addr; + + LOCK (&inode->lock); + { + bad_object = __br_stub_is_bad_object (ctx); + } + UNLOCK (&inode->lock); + +out: + return bad_object; +} + +static inline int32_t +br_stub_mark_object_bad (xlator_t *this, inode_t *inode) +{ + int32_t ret = -1; + uint64_t ctx_addr = 0; + br_stub_inode_ctx_t *ctx = NULL; + + ret = br_stub_get_inode_ctx (this, inode, &ctx_addr); + if (ret) { + gf_msg (this->name, GF_LOG_ERROR, 0, + BRS_MSG_GET_INODE_CONTEXT_FAILED, "failed to get the " + "inode context for the inode %s", + uuid_utoa (inode->gfid)); + goto out; + } + + ctx = (br_stub_inode_ctx_t *)(long)ctx_addr; + + LOCK (&inode->lock); + { + __br_stub_mark_object_bad (ctx); + } + UNLOCK (&inode->lock); + +out: + return ret; +} + +static inline int32_t +br_stub_mark_xdata_bad_object (xlator_t *this, inode_t *inode, dict_t *xdata) +{ + int32_t ret = 0; + + if (br_stub_is_bad_object (this, inode)) + ret = dict_set_int32 (xdata, GLUSTERFS_BAD_INODE, 1); + + return ret; +} + int32_t br_stub_add_fd_to_inode (xlator_t *this, fd_t *fd, br_stub_inode_ctx_t *ctx); -- cgit