diff options
| author | Poornima G <pgurusid@redhat.com> | 2016-02-26 06:42:14 -0500 | 
|---|---|---|
| committer | Vijay Bellur <vbellur@redhat.com> | 2016-03-09 19:09:43 -0800 | 
| commit | a8a8feb25216db2fa426b09d778f61c0f89d514c (patch) | |
| tree | b8f2ef368c065194f236bb3042b9b269cc5d2584 | |
| parent | 73f415353b0d70a4e6e4a4cedc05cd9b8418625f (diff) | |
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 <pgurusid@redhat.com>
Reviewed-on: http://review.gluster.org/13626
Tested-by: Vijay Bellur <vbellur@redhat.com>
Smoke: Gluster Build System <jenkins@build.gluster.com>
CentOS-regression: Gluster Build System <jenkins@build.gluster.com>
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
| -rw-r--r-- | doc/mount.glusterfs.8 | 3 | ||||
| -rw-r--r-- | glusterfsd/src/glusterfsd.c | 17 | ||||
| -rw-r--r-- | glusterfsd/src/glusterfsd.h | 1 | ||||
| -rw-r--r-- | libglusterfs/src/glusterfs.h | 1 | ||||
| -rw-r--r-- | tests/bugs/fuse/bug-1309462.t | 49 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 27 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.h | 4 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-helpers.c | 26 | ||||
| -rwxr-xr-x | xlators/mount/fuse/utils/mount_glusterfs.in | 7 | 
9 files changed, 123 insertions, 12 deletions
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  | 
