diff options
| -rw-r--r-- | rpc/rpc-lib/src/auth-glusterfs.c | 6 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpcsvc-auth.c | 16 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpcsvc-common.h | 1 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpcsvc.h | 23 | ||||
| -rwxr-xr-x | tests/bugs/bug-887145.t | 85 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-set.c | 1 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server.c | 9 | 
7 files changed, 139 insertions, 2 deletions
diff --git a/rpc/rpc-lib/src/auth-glusterfs.c b/rpc/rpc-lib/src/auth-glusterfs.c index c08871466cc..9c6f8385b2c 100644 --- a/rpc/rpc-lib/src/auth-glusterfs.c +++ b/rpc/rpc-lib/src/auth-glusterfs.c @@ -64,9 +64,9 @@ int auth_glusterfs_authenticate (rpcsvc_request_t *req, void *priv)          struct auth_glusterfs_parms  au = {0,};          int ret      = RPCSVC_AUTH_REJECT; -        int gidcount = 0;          int j        = 0;          int i        = 0; +        int gidcount = 0;          if (!req)                  return ret; @@ -99,6 +99,8 @@ int auth_glusterfs_authenticate (rpcsvc_request_t *req, void *priv)          for (gidcount = 0; gidcount < au.ngrps; ++gidcount)                  req->auxgids[gidcount] = au.groups[gidcount]; +        RPC_AUTH_ROOT_SQUASH(req); +          gf_log (GF_RPCSVC, GF_LOG_TRACE, "Auth Info: pid: %u, uid: %d"                  ", gid: %d, owner: %s",                  req->pid, req->uid, req->gid, lkowner_utoa (&req->lk_owner)); @@ -207,6 +209,8 @@ int auth_glusterfs_v2_authenticate (rpcsvc_request_t *req, void *priv)          for (i = 0; i < au.lk_owner.lk_owner_len; ++i)                  req->lk_owner.data[i] = au.lk_owner.lk_owner_val[i]; +        RPC_AUTH_ROOT_SQUASH(req); +          gf_log (GF_RPCSVC, GF_LOG_TRACE, "Auth Info: pid: %u, uid: %d"                  ", gid: %d, owner: %s",                  req->pid, req->uid, req->gid, lkowner_utoa (&req->lk_owner)); diff --git a/rpc/rpc-lib/src/rpcsvc-auth.c b/rpc/rpc-lib/src/rpcsvc-auth.c index 3a46cc498e5..907ae1ec9af 100644 --- a/rpc/rpc-lib/src/rpcsvc-auth.c +++ b/rpc/rpc-lib/src/rpcsvc-auth.c @@ -204,6 +204,21 @@ rpcsvc_set_allow_insecure (rpcsvc_t *svc, dict_t *options)  }  int +rpcsvc_set_root_squash (rpcsvc_t *svc, dict_t *options) +{ +        GF_ASSERT (svc); +        GF_ASSERT (options); + +        if (dict_get_str_boolean (options, "root-squash", 0)) +                svc->root_squash = _gf_true; + +        if (svc->root_squash) +                gf_log (GF_RPCSVC, GF_LOG_DEBUG, "root squashing enabled "); + +        return 0; +} + +int  rpcsvc_auth_init (rpcsvc_t *svc, dict_t *options)  {          int             ret = -1; @@ -212,6 +227,7 @@ rpcsvc_auth_init (rpcsvc_t *svc, dict_t *options)                  return -1;          (void) rpcsvc_set_allow_insecure (svc, options); +        (void) rpcsvc_set_root_squash (svc, options);          ret = rpcsvc_auth_add_initers (svc);          if (ret == -1) {                  gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to add initers"); diff --git a/rpc/rpc-lib/src/rpcsvc-common.h b/rpc/rpc-lib/src/rpcsvc-common.h index 81f79811612..2c6f074886d 100644 --- a/rpc/rpc-lib/src/rpcsvc-common.h +++ b/rpc/rpc-lib/src/rpcsvc-common.h @@ -52,6 +52,7 @@ typedef struct rpcsvc_state {          /* Allow insecure ports. */          int                     allow_insecure;          gf_boolean_t            register_portmap; +        gf_boolean_t            root_squash;          glusterfs_ctx_t         *ctx;          /* list of connections which will listen for incoming connections */ diff --git a/rpc/rpc-lib/src/rpcsvc.h b/rpc/rpc-lib/src/rpcsvc.h index 7fdeaeb0458..1323c8b7aee 100644 --- a/rpc/rpc-lib/src/rpcsvc.h +++ b/rpc/rpc-lib/src/rpcsvc.h @@ -48,6 +48,10 @@  #define RPCSVC_POOLCOUNT_MULT           64  #define RPCSVC_CONN_READ        (128 * GF_UNIT_KB)  #define RPCSVC_PAGE_SIZE        (128 * GF_UNIT_KB) +#define RPC_ROOT_UID             0 +#define RPC_ROOT_GID             0 +#define RPC_NOBODY_UID           65534 +#define RPC_NOBODY_GID           65534  /* RPC Record States */  #define RPCSVC_READ_FRAGHDR     1 @@ -261,7 +265,22 @@ struct rpcsvc_request {  #define rpcsvc_request_vecstate(req) ((req)->vecstate)  #define rpcsvc_request_transport(req) ((req)->trans)  #define rpcsvc_request_transport_ref(req) (rpc_transport_ref((req)->trans)) - +#define RPC_AUTH_ROOT_SQUASH(req)                                       \ +        do {                                                            \ +                int gidcount = 0;                                       \ +                if (req->svc->root_squash) {                            \ +                        if (req->uid == RPC_ROOT_UID)                   \ +                                req->uid = RPC_NOBODY_UID;              \ +                        if (req->gid == RPC_ROOT_GID)                   \ +                                req->gid = RPC_NOBODY_GID;              \ +                        for (gidcount = 0; gidcount < req->auxgidcount; \ +                             ++gidcount) {                              \ +                                if (!req->auxgids[gidcount])            \ +                                        req->auxgids[gidcount] =        \ +                                                RPC_NOBODY_GID;         \ +                        }                                               \ +                }                                                       \ +        } while (0);  #define RPCSVC_ACTOR_SUCCESS    0  #define RPCSVC_ACTOR_ERROR      (-1) @@ -546,6 +565,8 @@ rpcsvc_transport_unix_options_build (dict_t **options, char *filepath);  int  rpcsvc_set_allow_insecure (rpcsvc_t *svc, dict_t *options);  int +rpcsvc_set_root_squash (rpcsvc_t *svc, dict_t *options); +int  rpcsvc_auth_array (rpcsvc_t *svc, char *volname, int *autharr, int arrlen);  char *  rpcsvc_volume_allowed (dict_t *options, char *volname); diff --git a/tests/bugs/bug-887145.t b/tests/bugs/bug-887145.t new file mode 100755 index 00000000000..8e5f039006c --- /dev/null +++ b/tests/bugs/bug-887145.t @@ -0,0 +1,85 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{1,2}; +TEST $CLI volume set $V0 performance.open-behind off; +TEST $CLI volume start $V0 + +sleep 2; +## Mount FUSE with caching disabled +TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0; + +sleep 2; + +TEST mount -t nfs -o vers=3,nolock $H0:/$V0 $N0; + +useradd tmp_user 2>/dev/null 1>/dev/null; +mkdir $M0/dir; +mkdir $M0/other; +cp /etc/passwd $M0/; +cp $M0/passwd $M0/file; +chmod 600 $M0/file; + +chown -R nfsnobody:nfsnobody $M0/dir; +chown -R tmp_user:tmp_user $M0/other; + +TEST $CLI volume set $V0 server.root-squash on; + +sleep 2; + +# create files and directories in the root of the glusterfs and nfs mount +# which is owned by root and hence the right behavior is getting EACCESS +# as the fops are executed as nfsnobody. +touch $M0/foo 2>/dev/null; +TEST [ $? -ne 0 ] +touch $N0/foo 2>/dev/null; +TEST [ $? -ne 0 ] +mkdir $M0/new 2>/dev/null; +TEST [ $? -ne 0 ] +mkdir $N0/new 2>/dev/null; +TEST [ $? -ne 0 ] +cp $M0/file $M0/tmp_file 2>/dev/null; +TEST [ $? -ne 0 ] +cp $N0/file $N0/tmp_file 2>/dev/null; +TEST [ $? -ne 0 ] +cat $M0/file 2>/dev/null; +TEST [ $? -ne 0 ] +# here read should be allowed because eventhough file "passwd" is owned +# by root, the permissions if the file allow other users to read it. +cat $M0/passwd 1>/dev/null; +TEST [ $? -eq 0 ] +cat $N0/passwd 1>/dev/null; +TEST [ $? -eq 0 ] + +# create files and directories should succeed as the fops are being executed +# inside the directory owned by nfsnobody +TEST touch $M0/dir/file; +TEST touch $N0/dir/foo; +TEST mkdir $M0/dir/new; +TEST mkdir $N0/dir/other; +TEST rm -f $M0/dir/file $M0/dir/foo; +TEST rmdir $N0/dir/*; + +# create files and directories here should fail as other directory is owned +# by tmp_user. +touch $M0/other/foo 2>/dev/null; +TEST [ $? -ne 0 ] +touch $N0/other/foo 2>/dev/null; +TEST [ $? -ne 0 ] +mkdir $M0/other/new 2>/dev/null; +TEST [ $? -ne 0 ] +mkdir $N0/other/new 2>/dev/null; +TEST [ $? -ne 0 ] + +userdel tmp_user; +rm -rf /home/tmp_user; + +TEST $CLI volume stop $V0; +TEST $CLI volume delete $V0; + +cleanup; diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c index 9681f44428e..fc2c64a5fe2 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c @@ -163,6 +163,7 @@ struct volopt_map_entry glusterd_volopt_map[] = {          {"transport.keepalive",                  "protocol/server",           "transport.socket.keepalive", NULL, NO_DOC, 0, 1},          {"server.allow-insecure",                "protocol/server",           "rpc-auth-allow-insecure", NULL, NO_DOC, 0, 1}, +        {"server.root-squash",                   "protocol/server",           "root-squash", NULL, DOC, 0, 2},          {"server.statedump-path",                "protocol/server",           "statedump-path", NULL, DOC, 0, 1},          {"features.lock-heal",                   "protocol/server",           "lk-heal", NULL, NO_DOC, 0, 1},          {"features.grace-timeout",               "protocol/server",           "grace-timeout", NULL, NO_DOC, 0, 1}, diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c index 9e60febfb53..3a5f84b1dd8 100644 --- a/xlators/protocol/server/src/server.c +++ b/xlators/protocol/server/src/server.c @@ -993,6 +993,7 @@ reconfigure (xlator_t *this, dict_t *options)          }          (void) rpcsvc_set_allow_insecure (rpc_conf, options); +        (void) rpcsvc_set_root_squash (rpc_conf, options);          list_for_each_entry (listeners, &(rpc_conf->listeners), list) {                  if (listeners->trans != NULL) {                          if (listeners->trans->reconfigure ) @@ -1274,6 +1275,14 @@ struct volume_options options[] = {          { .key   = {"rpc-auth-allow-insecure"},            .type  = GF_OPTION_TYPE_BOOL,          }, +        { .key   = {"root-squash"}, +          .type  = GF_OPTION_TYPE_BOOL, +          .default_value = "off", +          .description = "Map  requests  from  uid/gid 0 to the anonymous " +                         "uid/gid. Note that this does not apply to any other" +                         "uids or gids that might be equally sensitive, such as" +                         "user bin or group staff." +        },          { .key           = {"statedump-path"},            .type          = GF_OPTION_TYPE_PATH,            .default_value = DEFAULT_VAR_RUN_DIRECTORY,  | 
