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, |