From a8a8feb25216db2fa426b09d778f61c0f89d514c Mon Sep 17 00:00:00 2001 From: Poornima G Date: Fri, 26 Feb 2016 06:42:14 -0500 Subject: fuse: Add a new mount option capability Originally all security.* xattrs were forbidden if selinux is disabled, which was causing Samba's acl_xattr module to not work, as it would store the NTACL in security.NTACL. To fix this http://review.gluster.org/#/c/12826/ was sent, which forbid only security.selinux. This opened up a getxattr call on security.capability before every write fop and others. Capabilities can be used without selinux, hence if selinux is disabled, security.capability cannot be forbidden. Hence adding a new mount option called capability. Only when "--capability" or "--selinux" mount option is used, security.capability is sent to the brick, else it is forbidden. Backport of : http://review.gluster.org/#/c/13540/ & http://review.gluster.org/#/c/13653/ BUG: 1309462 Change-Id: Ib8d4f32d9f1458f4d71a05785f92b526aa7033ff Signed-off-by: Poornima G Reviewed-on: http://review.gluster.org/13626 Tested-by: Vijay Bellur Smoke: Gluster Build System CentOS-regression: Gluster Build System NetBSD-regression: NetBSD Build System Reviewed-by: Vijay Bellur --- doc/mount.glusterfs.8 | 3 ++ glusterfsd/src/glusterfsd.c | 17 +++++++++- glusterfsd/src/glusterfsd.h | 1 + libglusterfs/src/glusterfs.h | 1 + tests/bugs/fuse/bug-1309462.t | 49 +++++++++++++++++++++++++++++ xlators/mount/fuse/src/fuse-bridge.c | 27 +++++++++------- xlators/mount/fuse/src/fuse-bridge.h | 4 +++ xlators/mount/fuse/src/fuse-helpers.c | 26 +++++++++++++++ xlators/mount/fuse/utils/mount_glusterfs.in | 7 +++++ 9 files changed, 123 insertions(+), 12 deletions(-) create mode 100644 tests/bugs/fuse/bug-1309462.t diff --git a/doc/mount.glusterfs.8 b/doc/mount.glusterfs.8 index 8884b483a48..4cb7772971d 100644 --- a/doc/mount.glusterfs.8 +++ b/doc/mount.glusterfs.8 @@ -62,6 +62,9 @@ support 64-bit inodes .TP \fBmem\-accounting Enable internal memory accounting +.TP +\fBcapability +Enable file capability setting and retrival .PP .SS "Advanced options" diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c index e41064a1372..45dbc26801a 100644 --- a/glusterfsd/src/glusterfsd.c +++ b/glusterfsd/src/glusterfsd.c @@ -155,7 +155,9 @@ static struct argp_option gf_options[] = { {"acl", ARGP_ACL_KEY, 0, 0, "Mount the filesystem with POSIX ACL support"}, {"selinux", ARGP_SELINUX_KEY, 0, 0, - "Enable SELinux label (extened attributes) support on inodes"}, + "Enable SELinux label (extended attributes) support on inodes"}, + {"capability", ARGP_CAPABILITY_KEY, 0, 0, + "Enable file capability setting and retrival"}, {"print-netgroups", ARGP_PRINT_NETGROUPS, "NETGROUP-FILE", 0, "Validate the netgroups file and print it out"}, @@ -371,6 +373,15 @@ set_fuse_mount_options (glusterfs_ctx_t *ctx, dict_t *options) } } + if (cmd_args->capability) { + ret = dict_set_static_ptr (options, "capability", "on"); + if (ret < 0) { + gf_msg ("glusterfsd", GF_LOG_ERROR, 0, glusterfsd_msg_4, + "capability"); + goto err; + } + } + if (cmd_args->aux_gfid_mount) { ret = dict_set_static_ptr (options, "virtual-gfid-access", "on"); @@ -799,6 +810,10 @@ parse_opts (int key, char *arg, struct argp_state *state) gf_remember_xlator_option ("*-md-cache.cache-selinux=true"); break; + case ARGP_CAPABILITY_KEY: + cmd_args->capability = 1; + break; + case ARGP_AUX_GFID_MOUNT_KEY: cmd_args->aux_gfid_mount = 1; break; diff --git a/glusterfsd/src/glusterfsd.h b/glusterfsd/src/glusterfsd.h index f5f0e62c51f..bb7966ebd58 100644 --- a/glusterfsd/src/glusterfsd.h +++ b/glusterfsd/src/glusterfsd.h @@ -96,6 +96,7 @@ enum argp_option_keys { ARGP_SECURE_MGMT_KEY = 172, ARGP_GLOBAL_TIMER_WHEEL = 173, ARGP_RESOLVE_GIDS_KEY = 174, + ARGP_CAPABILITY_KEY = 175, }; struct _gfd_vol_top_priv_t { diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index ef00038ef77..81caf12e62b 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -448,6 +448,7 @@ struct _cmd_args { int read_only; int acl; int selinux; + int capability; int enable_ino32; int worm; int mac_compat; diff --git a/tests/bugs/fuse/bug-1309462.t b/tests/bugs/fuse/bug-1309462.t new file mode 100644 index 00000000000..f3b74bd2935 --- /dev/null +++ b/tests/bugs/fuse/bug-1309462.t @@ -0,0 +1,49 @@ +#!/bin/bash +# +# https://bugzilla.redhat.com/show_bug.cgi?id=1309462 +# Test the new fuse mount option --capability. +# Set/get xattr on security.capability should be sent +# down from fuse, only if --selinux or --capability option +# is used for mounting. + +. $(dirname $0)/../../include.rc + +cleanup; + +#Basic checks +TEST glusterd +TEST pidof glusterd + +#Create a distributed volume +TEST $CLI volume create $V0 $H0:$B0/${V0}{1..2}; +TEST $CLI volume start $V0 + +# Mount FUSE without selinux: +TEST glusterfs -s $H0 --volfile-id $V0 $M0 + +TESTFILE="$M0/testfile" +TEST touch ${TESTFILE} + +TEST ! setfattr -n security.capability -v value ${TESTFILE} +TEST ! getfattr -n security.capability ${TESTFILE} + +TEST umount $M0 + +# Mount FUSE with selinux: +TEST glusterfs -s $H0 --volfile-id $V0 --selinux $M0 + +TEST setfattr -n security.capability -v value ${TESTFILE} +TEST getfattr -n security.capability ${TESTFILE} +TEST setfattr -x security.capability ${TESTFILE} + +TEST umount $M0 + +# Mount FUSE with capability: +TEST glusterfs -s $H0 --volfile-id $V0 --capability $M0 + +TEST setfattr -n security.capability -v value ${TESTFILE} +TEST getfattr -n security.capability ${TESTFILE} +TEST setfattr -x security.capability ${TESTFILE} + +TEST umount $M0 + diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index a6aa96e456c..85b212af951 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -3175,12 +3175,11 @@ fuse_setxattr (xlator_t *this, fuse_in_header_t *finh, void *msg) } } - if (!priv->selinux) { - if (strcmp (name, "security.selinux") == 0) { - send_fuse_err (this, finh, EOPNOTSUPP); - GF_FREE (finh); - return; - } + ret = fuse_check_selinux_cap_xattr (priv, name); + if (ret) { + send_fuse_err (this, finh, EOPNOTSUPP); + GF_FREE (finh); + return; } /* Check if the command is for changing the log @@ -3474,6 +3473,7 @@ fuse_getxattr (xlator_t *this, fuse_in_header_t *finh, void *msg) int rv = 0; int op_errno = EINVAL; char *newkey = NULL; + int ret = 0; priv = this->private; GET_STATE (this, finh, state); @@ -3505,11 +3505,10 @@ fuse_getxattr (xlator_t *this, fuse_in_header_t *finh, void *msg) } } - if (!priv->selinux) { - if (strcmp (name, "security.selinux") == 0) { - op_errno = ENODATA; - goto err; - } + ret = fuse_check_selinux_cap_xattr (priv, name); + if (ret) { + op_errno = ENODATA; + goto err; } fuse_resolve_inode_init (state, &state->resolve, finh->nodeid); @@ -5484,6 +5483,8 @@ init (xlator_t *this_xl) GF_OPTION_INIT ("selinux", priv->selinux, bool, cleanup_exit); + GF_OPTION_INIT ("capability", priv->capability, bool, cleanup_exit); + GF_OPTION_INIT ("read-only", priv->read_only, bool, cleanup_exit); GF_OPTION_INIT ("enable-ino32", priv->enable_ino32, bool, cleanup_exit); @@ -5818,5 +5819,9 @@ struct volume_options options[] = { "does not have any affect and the volume option for root-squash is " "honoured.", }, + { .key = {"capability"}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "false" + }, { .key = {NULL} }, }; diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h index 807bc302a59..ee09b252bde 100644 --- a/xlators/mount/fuse/src/fuse-bridge.h +++ b/xlators/mount/fuse/src/fuse-bridge.h @@ -136,6 +136,9 @@ struct fuse_private { /* resolve gid with getgrouplist() instead of /proc/%d/status */ gf_boolean_t resolve_gids; + + /* Enable or disable capability support */ + gf_boolean_t capability; }; typedef struct fuse_private fuse_private_t; @@ -424,4 +427,5 @@ int fuse_resolve_fd_init (fuse_state_t *state, fuse_resolve_t *resolve, int fuse_ignore_xattr_set (fuse_private_t *priv, char *key); void fuse_fop_resume (fuse_state_t *state); int dump_history_fuse (circular_buffer_t *cb, void *data); +int fuse_check_selinux_cap_xattr (fuse_private_t *priv, char *name); #endif /* _GF_FUSE_BRIDGE_H_ */ diff --git a/xlators/mount/fuse/src/fuse-helpers.c b/xlators/mount/fuse/src/fuse-helpers.c index 0f8abf03d32..3ccd46efaeb 100644 --- a/xlators/mount/fuse/src/fuse-helpers.c +++ b/xlators/mount/fuse/src/fuse-helpers.c @@ -652,3 +652,29 @@ fuse_ignore_xattr_set (fuse_private_t *priv, char *key) return ret; } + +int +fuse_check_selinux_cap_xattr (fuse_private_t *priv, char *name) +{ + int ret = -1; + + if (strcmp (name, "security.selinux") && + strcmp (name, "security.capability")) { + /* if xattr name is not of interest, no validations needed */ + ret = 0; + goto out; + } + + if ((strcmp (name, "security.selinux") == 0) && + (priv->selinux)) { + ret = 0; + } + + if ((strcmp (name, "security.capability") == 0) && + ((priv->capability) || (priv->selinux))) { + ret = 0; + } + +out: + return ret; +} diff --git a/xlators/mount/fuse/utils/mount_glusterfs.in b/xlators/mount/fuse/utils/mount_glusterfs.in index 50a301c26a8..3d58c29e0cf 100755 --- a/xlators/mount/fuse/utils/mount_glusterfs.in +++ b/xlators/mount/fuse/utils/mount_glusterfs.in @@ -173,6 +173,10 @@ start_glusterfs () cmd_line=$(echo "$cmd_line --no-root-squash"); fi + if [ -n "$capability" ]; then + cmd_line=$(echo "$cmd_line --capability"); + fi + #options with values start here if [ -n "$log_level" ]; then cmd_line=$(echo "$cmd_line --log-level=$log_level"); @@ -440,6 +444,9 @@ without_options() ;; "_netdev") ;; + "capability") + capability=1 + ;; *) warn "Invalid option $option"; exit 1 -- cgit