From 70dc47389cbe08238d8c216c51d49583154bd08a Mon Sep 17 00:00:00 2001 From: Pranith Kumar K Date: Mon, 5 Jan 2015 16:21:52 +0530 Subject: cluster/ec: Handle internal xattr get/set Problem: Internal xattrs of EC like trusted.ec.size/config/version can be modified by users and that can lead to misbehavior in EC. Fix: Don't let the user modify the xattrs. Hide these xattrs in getfattr outputs. Change-Id: I39cec96ae12826b506b496fda7da74201015fd75 BUG: 1178688 Signed-off-by: Pranith Kumar K Reviewed-on: http://review.gluster.org/9385 Tested-by: Gluster Build System Reviewed-by: Emmanuel Dreyfus Tested-by: Emmanuel Dreyfus Reviewed-by: Xavier Hernandez --- xlators/cluster/ec/src/ec-helpers.c | 17 +++++ xlators/cluster/ec/src/ec-helpers.h | 5 ++ xlators/cluster/ec/src/ec-inode-read.c | 50 ++++++------- xlators/cluster/ec/src/ec-inode-write.c | 97 ++++++++++++------------- xlators/cluster/ec/src/ec.c | 125 ++++++++++++++++++++++++-------- xlators/cluster/ec/src/ec.h | 9 ++- 6 files changed, 188 insertions(+), 115 deletions(-) (limited to 'xlators') diff --git a/xlators/cluster/ec/src/ec-helpers.c b/xlators/cluster/ec/src/ec-helpers.c index 3c3e2302e53..05ecab51ab6 100644 --- a/xlators/cluster/ec/src/ec-helpers.c +++ b/xlators/cluster/ec/src/ec-helpers.c @@ -694,3 +694,20 @@ uint64_t ec_adjust_size(ec_t * ec, uint64_t size, int32_t scale) return size; } + +inline gf_boolean_t +ec_is_internal_xattr (dict_t *dict, char *key, data_t *value, void *data) +{ + if (key && + (strncmp (key, EC_XATTR_PREFIX, strlen (EC_XATTR_PREFIX)) == 0)) + return _gf_true; + + return _gf_false; +} + +void +ec_filter_internal_xattrs (dict_t *xattr) +{ + dict_foreach_match (xattr, ec_is_internal_xattr, NULL, + dict_remove_foreach_fn, NULL); +} diff --git a/xlators/cluster/ec/src/ec-helpers.h b/xlators/cluster/ec/src/ec-helpers.h index 46791041a3f..ff61839756c 100644 --- a/xlators/cluster/ec/src/ec-helpers.h +++ b/xlators/cluster/ec/src/ec-helpers.h @@ -52,4 +52,9 @@ static inline int32_t ec_is_power_of_2(uint32_t value) return (value != 0) && ((value & (value - 1)) == 0); } +inline gf_boolean_t +ec_is_internal_xattr (dict_t *dict, char *key, data_t *value, void *data); + +void +ec_filter_internal_xattrs (dict_t *xattr); #endif /* __EC_HELPERS_H__ */ diff --git a/xlators/cluster/ec/src/ec-inode-read.c b/xlators/cluster/ec/src/ec-inode-read.c index 3b5315b187a..64b1b719eea 100644 --- a/xlators/cluster/ec/src/ec-inode-read.c +++ b/xlators/cluster/ec/src/ec-inode-read.c @@ -280,15 +280,10 @@ int32_t ec_manager_getxattr(ec_fop_data_t * fop, int32_t state) else { if (cbk->xdata != NULL) - { - dict_del(cbk->xdata, EC_XATTR_SIZE); - dict_del(cbk->xdata, EC_XATTR_VERSION); - } + ec_filter_internal_xattrs (cbk->xdata); + if (cbk->dict != NULL) - { - dict_del(cbk->dict, EC_XATTR_SIZE); - dict_del(cbk->dict, EC_XATTR_VERSION); - } + ec_filter_internal_xattrs (cbk->dict); } } else @@ -399,9 +394,10 @@ out: return 0; } -void ec_getxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, - int32_t minimum, fop_getxattr_cbk_t func, void * data, - loc_t * loc, const char * name, dict_t * xdata) +void +ec_getxattr (call_frame_t *frame, xlator_t *this, uintptr_t target, + int32_t minimum, fop_getxattr_cbk_t func, void *data, + loc_t *loc, const char *name, dict_t *xdata) { ec_cbk_t callback = { .getxattr = func }; ec_fop_data_t * fop = NULL; @@ -464,13 +460,10 @@ void ec_getxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, error = 0; out: - if (fop != NULL) - { - ec_manager(fop, error); - } - else - { - func(frame, NULL, this, -1, EIO, NULL, NULL); + if (fop != NULL) { + ec_manager (fop, error); + } else { + func (frame, NULL, this, -1, error, NULL, NULL); } } @@ -536,7 +529,8 @@ out: return 0; } -void ec_wind_fgetxattr(ec_t * ec, ec_fop_data_t * fop, int32_t idx) +void +ec_wind_fgetxattr (ec_t *ec, ec_fop_data_t *fop, int32_t idx) { ec_trace("WIND", fop, "idx=%d", idx); @@ -545,9 +539,10 @@ void ec_wind_fgetxattr(ec_t * ec, ec_fop_data_t * fop, int32_t idx) fop->fd, fop->str[0], fop->xdata); } -void ec_fgetxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, - int32_t minimum, fop_fgetxattr_cbk_t func, void * data, - fd_t * fd, const char * name, dict_t * xdata) +void +ec_fgetxattr (call_frame_t *frame, xlator_t *this, uintptr_t target, + int32_t minimum, fop_fgetxattr_cbk_t func, void *data, + fd_t *fd, const char *name, dict_t *xdata) { ec_cbk_t callback = { .fgetxattr = func }; ec_fop_data_t * fop = NULL; @@ -606,13 +601,10 @@ void ec_fgetxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, error = 0; out: - if (fop != NULL) - { - ec_manager(fop, error); - } - else - { - func(frame, NULL, this, -1, EIO, NULL, NULL); + if (fop != NULL) { + ec_manager (fop, error); + } else { + func (frame, NULL, this, -1, error, NULL, NULL); } } diff --git a/xlators/cluster/ec/src/ec-inode-write.c b/xlators/cluster/ec/src/ec-inode-write.c index c120f067b6a..9c3f6fcd115 100644 --- a/xlators/cluster/ec/src/ec-inode-write.c +++ b/xlators/cluster/ec/src/ec-inode-write.c @@ -195,9 +195,10 @@ int32_t ec_manager_removexattr(ec_fop_data_t * fop, int32_t state) } } -void ec_removexattr(call_frame_t * frame, xlator_t * this, uintptr_t target, - int32_t minimum, fop_removexattr_cbk_t func, void * data, - loc_t * loc, const char * name, dict_t * xdata) +void +ec_removexattr (call_frame_t *frame, xlator_t *this, uintptr_t target, + int32_t minimum, fop_removexattr_cbk_t func, void *data, + loc_t *loc, const char *name, dict_t *xdata) { ec_cbk_t callback = { .removexattr = func }; ec_fop_data_t * fop = NULL; @@ -205,9 +206,9 @@ void ec_removexattr(call_frame_t * frame, xlator_t * this, uintptr_t target, gf_log("ec", GF_LOG_TRACE, "EC(REMOVEXATTR) %p", frame); - VALIDATE_OR_GOTO(this, out); - GF_VALIDATE_OR_GOTO(this->name, frame, out); - GF_VALIDATE_OR_GOTO(this->name, this->private, out); + VALIDATE_OR_GOTO (this, out); + GF_VALIDATE_OR_GOTO (this->name, frame, out); + GF_VALIDATE_OR_GOTO (this->name, this->private, out); fop = ec_fop_data_allocate(frame, this, GF_FOP_REMOVEXATTR, EC_FLAG_UPDATE_LOC_INODE, target, minimum, @@ -252,13 +253,10 @@ void ec_removexattr(call_frame_t * frame, xlator_t * this, uintptr_t target, error = 0; out: - if (fop != NULL) - { - ec_manager(fop, error); - } - else - { - func(frame, NULL, this, -1, EIO, NULL); + if (fop != NULL) { + ec_manager (fop, error); + } else { + func (frame, NULL, this, -1, error, NULL); } } @@ -319,9 +317,10 @@ void ec_wind_fremovexattr(ec_t * ec, ec_fop_data_t * fop, int32_t idx) fop->fd, fop->str[0], fop->xdata); } -void ec_fremovexattr(call_frame_t * frame, xlator_t * this, uintptr_t target, - int32_t minimum, fop_fremovexattr_cbk_t func, void * data, - fd_t * fd, const char * name, dict_t * xdata) +void +ec_fremovexattr (call_frame_t *frame, xlator_t *this, uintptr_t target, + int32_t minimum, fop_fremovexattr_cbk_t func, void *data, + fd_t *fd, const char *name, dict_t *xdata) { ec_cbk_t callback = { .fremovexattr = func }; ec_fop_data_t * fop = NULL; @@ -329,9 +328,9 @@ void ec_fremovexattr(call_frame_t * frame, xlator_t * this, uintptr_t target, gf_log("ec", GF_LOG_TRACE, "EC(FREMOVEXATTR) %p", frame); - VALIDATE_OR_GOTO(this, out); - GF_VALIDATE_OR_GOTO(this->name, frame, out); - GF_VALIDATE_OR_GOTO(this->name, this->private, out); + VALIDATE_OR_GOTO (this, out); + GF_VALIDATE_OR_GOTO (this->name, frame, out); + GF_VALIDATE_OR_GOTO (this->name, this->private, out); fop = ec_fop_data_allocate(frame, this, GF_FOP_FREMOVEXATTR, EC_FLAG_UPDATE_FD_INODE, target, minimum, @@ -380,13 +379,10 @@ void ec_fremovexattr(call_frame_t * frame, xlator_t * this, uintptr_t target, error = 0; out: - if (fop != NULL) - { - ec_manager(fop, error); - } - else - { - func(frame, NULL, this, -1, EIO, NULL); + if (fop != NULL) { + ec_manager (fop, error); + } else { + func (frame, NULL, this, -1, error, NULL); } } @@ -986,9 +982,10 @@ int32_t ec_manager_setxattr(ec_fop_data_t * fop, int32_t state) } } -void ec_setxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, - int32_t minimum, fop_setxattr_cbk_t func, void * data, - loc_t * loc, dict_t * dict, int32_t flags, dict_t * xdata) +void +ec_setxattr (call_frame_t *frame, xlator_t *this, uintptr_t target, + int32_t minimum, fop_setxattr_cbk_t func, void *data, + loc_t *loc, dict_t *dict, int32_t flags, dict_t *xdata) { ec_cbk_t callback = { .setxattr = func }; ec_fop_data_t * fop = NULL; @@ -1046,29 +1043,27 @@ void ec_setxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, error = 0; out: - if (fop != NULL) - { - ec_manager(fop, error); - } - else - { - func(frame, NULL, this, -1, EIO, NULL); + if (fop != NULL) { + ec_manager (fop, error); + } else { + func (frame, NULL, this, -1, error, NULL); } } /* FOP: fsetxattr */ -int32_t ec_fsetxattr_cbk(call_frame_t * frame, void * cookie, xlator_t * this, - int32_t op_ret, int32_t op_errno, dict_t * xdata) +int32_t +ec_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { ec_fop_data_t * fop = NULL; ec_cbk_data_t * cbk = NULL; int32_t idx = (int32_t)(uintptr_t)cookie; - VALIDATE_OR_GOTO(this, out); - GF_VALIDATE_OR_GOTO(this->name, frame, out); - GF_VALIDATE_OR_GOTO(this->name, frame->local, out); - GF_VALIDATE_OR_GOTO(this->name, this->private, out); + VALIDATE_OR_GOTO (this, out); + GF_VALIDATE_OR_GOTO (this->name, frame, out); + GF_VALIDATE_OR_GOTO (this->name, frame->local, out); + GF_VALIDATE_OR_GOTO (this->name, this->private, out); fop = frame->local; @@ -1112,9 +1107,10 @@ void ec_wind_fsetxattr(ec_t * ec, ec_fop_data_t * fop, int32_t idx) fop->fd, fop->dict, fop->int32, fop->xdata); } -void ec_fsetxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, - int32_t minimum, fop_fsetxattr_cbk_t func, void * data, - fd_t * fd, dict_t * dict, int32_t flags, dict_t * xdata) +void +ec_fsetxattr (call_frame_t *frame, xlator_t *this, uintptr_t target, + int32_t minimum, fop_fsetxattr_cbk_t func, void *data, + fd_t *fd, dict_t *dict, int32_t flags, dict_t *xdata) { ec_cbk_t callback = { .fsetxattr = func }; ec_fop_data_t * fop = NULL; @@ -1176,13 +1172,10 @@ void ec_fsetxattr(call_frame_t * frame, xlator_t * this, uintptr_t target, error = 0; out: - if (fop != NULL) - { - ec_manager(fop, error); - } - else - { - func(frame, NULL, this, -1, EIO, NULL); + if (fop != NULL) { + ec_manager (fop, error); + } else { + func (frame, NULL, this, -1, error, NULL); } } diff --git a/xlators/cluster/ec/src/ec.c b/xlators/cluster/ec/src/ec.c index c6d3b9fe718..bd3fbc717e5 100644 --- a/xlators/cluster/ec/src/ec.c +++ b/xlators/cluster/ec/src/ec.c @@ -10,6 +10,7 @@ #include "defaults.h" #include "statedump.h" +#include "compat-errno.h" #include "ec-mem-types.h" #include "ec-helpers.h" @@ -25,6 +26,19 @@ */ #define EC_MAX_NODES min(EC_MAX_FRAGMENTS * 2 - 1, EC_METHOD_MAX_NODES) +#define EC_INTERNAL_XATTR_OR_GOTO(name, xattr, op_errno, label) \ + do { \ + if (ec_is_internal_xattr (NULL, (char *)name, NULL, NULL)) { \ + op_errno = EPERM; \ + goto label; \ + } \ + if (name && (strlen (name) == 0) && xattr) { \ + /* Bulk [f]removexattr/[f]setxattr */ \ + GF_IF_INTERNAL_XATTR_GOTO (EC_XATTR_PREFIX"*", xattr, \ + op_errno, label); \ + } \ + } while (0) + int32_t ec_parse_options(xlator_t * this) { ec_t * ec = this->private; @@ -470,22 +484,41 @@ int32_t ec_gf_fsyncdir(call_frame_t * frame, xlator_t * this, fd_t * fd, return 0; } -int32_t ec_gf_getxattr(call_frame_t * frame, xlator_t * this, loc_t * loc, - const char * name, dict_t * xdata) +int32_t +ec_gf_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata) { - ec_getxattr(frame, this, -1, EC_MINIMUM_MIN, default_getxattr_cbk, NULL, - loc, name, xdata); + int error = 0; - return 0; + if (name && strcmp (name, EC_XATTR_HEAL) != 0) { + EC_INTERNAL_XATTR_OR_GOTO(name, NULL, error, out); + } + + ec_getxattr (frame, this, -1, EC_MINIMUM_MIN, default_getxattr_cbk, + NULL, loc, name, xdata); + + return 0; +out: + error = ENODATA; + STACK_UNWIND_STRICT (getxattr, frame, -1, error, NULL, NULL); + return 0; } -int32_t ec_gf_fgetxattr(call_frame_t * frame, xlator_t * this, fd_t * fd, - const char * name, dict_t * xdata) +int32_t +ec_gf_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata) { - ec_fgetxattr(frame, this, -1, EC_MINIMUM_MIN, default_fgetxattr_cbk, NULL, - fd, name, xdata); + int error = 0; - return 0; + EC_INTERNAL_XATTR_OR_GOTO(name, NULL, error, out); + + ec_fgetxattr (frame, this, -1, EC_MINIMUM_MIN, default_fgetxattr_cbk, + NULL, fd, name, xdata); + return 0; +out: + error = ENODATA; + STACK_UNWIND_STRICT (fgetxattr, frame, -1, error, NULL, NULL); + return 0; } int32_t ec_gf_inodelk(call_frame_t * frame, xlator_t * this, @@ -607,22 +640,38 @@ int32_t ec_gf_readv(call_frame_t * frame, xlator_t * this, fd_t * fd, return 0; } -int32_t ec_gf_removexattr(call_frame_t * frame, xlator_t * this, loc_t * loc, - const char * name, dict_t * xdata) +int32_t +ec_gf_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata) { - ec_removexattr(frame, this, -1, EC_MINIMUM_MIN, default_removexattr_cbk, - NULL, loc, name, xdata); + int error = 0; - return 0; + EC_INTERNAL_XATTR_OR_GOTO (name, xdata, error, out); + + ec_removexattr (frame, this, -1, EC_MINIMUM_MIN, + default_removexattr_cbk, NULL, loc, name, xdata); + + return 0; +out: + STACK_UNWIND_STRICT (removexattr, frame, -1, error, NULL); + return 0; } -int32_t ec_gf_fremovexattr(call_frame_t * frame, xlator_t * this, fd_t * fd, - const char * name, dict_t * xdata) +int32_t +ec_gf_fremovexattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata) { - ec_fremovexattr(frame, this, -1, EC_MINIMUM_MIN, default_fremovexattr_cbk, - NULL, fd, name, xdata); + int error = 0; - return 0; + EC_INTERNAL_XATTR_OR_GOTO (name, xdata, error, out); + + ec_fremovexattr (frame, this, -1, EC_MINIMUM_MIN, + default_fremovexattr_cbk, NULL, fd, name, xdata); + + return 0; +out: + STACK_UNWIND_STRICT (fremovexattr, frame, -1, error, NULL); + return 0; } int32_t ec_gf_rename(call_frame_t * frame, xlator_t * this, loc_t * oldloc, @@ -661,22 +710,38 @@ int32_t ec_gf_fsetattr(call_frame_t * frame, xlator_t * this, fd_t * fd, return 0; } -int32_t ec_gf_setxattr(call_frame_t * frame, xlator_t * this, loc_t * loc, - dict_t * dict, int32_t flags, dict_t * xdata) +int32_t +ec_gf_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *dict, int32_t flags, dict_t *xdata) { - ec_setxattr(frame, this, -1, EC_MINIMUM_MIN, default_setxattr_cbk, NULL, - loc, dict, flags, xdata); + int error = 0; - return 0; + EC_INTERNAL_XATTR_OR_GOTO ("", dict, error, out); + + ec_setxattr (frame, this, -1, EC_MINIMUM_MIN, default_setxattr_cbk, + NULL, loc, dict, flags, xdata); + + return 0; +out: + STACK_UNWIND_STRICT (setxattr, frame, -1, error, NULL); + return 0; } -int32_t ec_gf_fsetxattr(call_frame_t * frame, xlator_t * this, fd_t * fd, - dict_t * dict, int32_t flags, dict_t * xdata) +int32_t +ec_gf_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + dict_t *dict, int32_t flags, dict_t *xdata) { - ec_fsetxattr(frame, this, -1, EC_MINIMUM_MIN, default_fsetxattr_cbk, NULL, - fd, dict, flags, xdata); + int error = 0; - return 0; + EC_INTERNAL_XATTR_OR_GOTO ("", dict, error, out); + + ec_fsetxattr (frame, this, -1, EC_MINIMUM_MIN, default_fsetxattr_cbk, + NULL, fd, dict, flags, xdata); + + return 0; +out: + STACK_UNWIND_STRICT (fsetxattr, frame, -1, error, NULL); + return 0; } int32_t ec_gf_stat(call_frame_t * frame, xlator_t * this, loc_t * loc, diff --git a/xlators/cluster/ec/src/ec.h b/xlators/cluster/ec/src/ec.h index c7db6226e25..2a042ae577f 100644 --- a/xlators/cluster/ec/src/ec.h +++ b/xlators/cluster/ec/src/ec.h @@ -14,10 +14,11 @@ #include "xlator.h" #include "timer.h" -#define EC_XATTR_CONFIG "trusted.ec.config" -#define EC_XATTR_SIZE "trusted.ec.size" -#define EC_XATTR_VERSION "trusted.ec.version" -#define EC_XATTR_HEAL "trusted.ec.heal" +#define EC_XATTR_PREFIX "trusted.ec." +#define EC_XATTR_CONFIG EC_XATTR_PREFIX"config" +#define EC_XATTR_SIZE EC_XATTR_PREFIX"size" +#define EC_XATTR_VERSION EC_XATTR_PREFIX"version" +#define EC_XATTR_HEAL EC_XATTR_PREFIX"heal" struct _ec; typedef struct _ec ec_t; -- cgit