diff options
author | Pranith Kumar K <pkarampu@redhat.com> | 2015-01-05 16:21:52 +0530 |
---|---|---|
committer | Pranith Kumar Karampuri <pkarampu@redhat.com> | 2015-01-08 21:55:37 -0800 |
commit | 70dc47389cbe08238d8c216c51d49583154bd08a (patch) | |
tree | f5da9dff6260291a7972e590d12ba785ed0841a1 | |
parent | cf0770c61af2fa49fa435baf62cd5f28569175e4 (diff) |
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 <pkarampu@redhat.com>
Reviewed-on: http://review.gluster.org/9385
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Emmanuel Dreyfus <manu@netbsd.org>
Tested-by: Emmanuel Dreyfus <manu@netbsd.org>
Reviewed-by: Xavier Hernandez <xhernandez@datalab.es>
-rw-r--r-- | tests/basic/ec/ec-internal-xattrs.t | 45 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-helpers.c | 17 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-helpers.h | 5 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-inode-read.c | 50 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-inode-write.c | 97 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec.c | 125 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec.h | 9 |
7 files changed, 233 insertions, 115 deletions
diff --git a/tests/basic/ec/ec-internal-xattrs.t b/tests/basic/ec/ec-internal-xattrs.t new file mode 100644 index 00000000000..5ef0502e016 --- /dev/null +++ b/tests/basic/ec/ec-internal-xattrs.t @@ -0,0 +1,45 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +# This test checks internal xattr handling in ec +TESTS_EXPECTED_IN_LOOP=11 + +cleanup +function get_ec_xattrs +{ + getfattr -d -m. -e hex $1 | grep trusted.ec +} + +function get_xattr_count +{ + getfattr -d -m. -e hex $1 | grep "trusted" | wc -l +} + +declare -a xattrs=("trusted.ec.config" "trusted.ec.size" "trusted.ec.version" "trusted.ec.heal") + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 redundancy 2 $H0:$B0/${V0}{0..5} +TEST $CLI volume start $V0 +TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0; +# Wait until all 6 children have been recognized by the ec xlator +EXPECT_WITHIN $CHILD_UP_TIMEOUT "6" ec_child_up_count $V0 0 +TEST touch $M0/a + +#Check that internal xattrs are not modifiable or readable +for x in "${xattrs[@]}"; do + TEST_IN_LOOP ! setfattr -n $x "abc" $M0/a + TEST_IN_LOOP ! setfattr -x $x "abc" $M0/a + if [ $x != "trusted.ec.heal" ]; + then + TEST_IN_LOOP ! getfattr -n $x $M0/a + fi +done + +TEST ! get_ec_xattrs $M0/a +TEST setfattr -n trusted.abc -v 0x616263 $M0/a +EXPECT "616263" get_hex_xattr trusted.abc $M0/a +EXPECT "1" get_xattr_count $M0/a +cleanup 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; |