diff options
author | Niels de Vos <ndevos@redhat.com> | 2014-04-17 18:32:07 +0200 |
---|---|---|
committer | Anand Avati <avati@redhat.com> | 2014-05-09 12:22:39 -0700 |
commit | 2fd499d148fc8865c77de8b2c73fe0b7e1737882 (patch) | |
tree | 368fe211b31d82cd14c6efc773fd91693855f3de /xlators/protocol/server/src/server-helpers.c | |
parent | 47c33dd27150039a6e5e3295eacd8d2d5a7e0ce0 (diff) |
rpc: implement server.manage-gids for group resolving on the bricks
The new volume option 'server.manage-gids' can be enabled in
environments where a user belongs to more than the current absolute
maximum of 93 groups. This option triggers the following behavior:
1. The AUTH_GLUSTERFS structure sent by GlusterFS clients (fuse, nfs or
libgfapi) will contain only one (1) auxiliary group, instead of
a full list. This reduces network usage and prevents problems in
encoding the AUTH_GLUSTERFS structure which should fit in 400 bytes.
2. The single group in the RPC Calls received by the server is replaced
by resolving the groups server-side. Permission checks and similar in
lower xlators are applied against the full list of groups where the
user belongs to, and not the single auxiliary group that the client
sent.
Change-Id: I9e540de13e3022f8b63ff893ecba511129a47b91
BUG: 1053579
Signed-off-by: Niels de Vos <ndevos@redhat.com>
Reviewed-on: http://review.gluster.org/7501
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Santosh Pradhan <spradhan@redhat.com>
Reviewed-by: Harshavardhana <harsha@harshavardhana.net>
Reviewed-by: Anand Avati <avati@redhat.com>
Diffstat (limited to 'xlators/protocol/server/src/server-helpers.c')
-rw-r--r-- | xlators/protocol/server/src/server-helpers.c | 114 |
1 files changed, 113 insertions, 1 deletions
diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c index b349d7de1eb..9dcb55ce3aa 100644 --- a/xlators/protocol/server/src/server-helpers.c +++ b/xlators/protocol/server/src/server-helpers.c @@ -15,8 +15,117 @@ #include "server.h" #include "server-helpers.h" +#include "gidcache.h" #include <fnmatch.h> +#include <pwd.h> +#include <grp.h> + +/* based on nfs_fix_aux_groups() */ +int +gid_resolve (server_conf_t *conf, call_stack_t *root) +{ + int ret = 0; + struct passwd mypw; + char mystrs[1024]; + struct passwd *result; + gid_t mygroups[GF_MAX_AUX_GROUPS]; + gid_list_t gl; + const gid_list_t *agl; + int ngroups, i; + + agl = gid_cache_lookup (&conf->gid_cache, root->uid, 0, 0); + if (agl) { + root->ngrps = agl->gl_count; + goto fill_groups; + } + + ret = getpwuid_r (root->uid, &mypw, mystrs, sizeof(mystrs), &result); + if (ret != 0) { + gf_log("gid-cache", GF_LOG_ERROR, "getpwuid_r(%u) failed", + root->uid); + return -1; + } + + if (!result) { + gf_log ("gid-cache", GF_LOG_ERROR, "getpwuid_r(%u) found " + "nothing", root->uid); + return -1; + } + + gf_log ("gid-cache", GF_LOG_TRACE, "mapped %u => %s", root->uid, + result->pw_name); + + ngroups = GF_MAX_AUX_GROUPS; + ret = getgrouplist (result->pw_name, root->gid, mygroups, &ngroups); + if (ret == -1) { + gf_log ("gid-cache", GF_LOG_ERROR, "could not map %s to group " + "list (%d gids)", result->pw_name, root->ngrps); + return -1; + } + root->ngrps = (uint16_t) ngroups; + +fill_groups: + if (agl) { + /* the gl is not complete, we only use gl.gl_list later on */ + gl.gl_list = agl->gl_list; + } else { + /* setup a full gid_list_t to add it to the gid_cache */ + gl.gl_id = root->uid; + gl.gl_uid = root->uid; + gl.gl_gid = root->gid; + gl.gl_count = root->ngrps; + + gl.gl_list = GF_MALLOC (root->ngrps * sizeof(gid_t), + gf_common_mt_groups_t); + if (gl.gl_list) + memcpy (gl.gl_list, mygroups, + sizeof(gid_t) * root->ngrps); + else + return -1; + } + + if (root->ngrps == 0) { + ret = 0; + goto out; + } + + if (call_stack_alloc_groups (root, root->ngrps) != 0) { + ret = -1; + goto out; + } + + /* finally fill the groups from the */ + for (i = 0; i < root->ngrps; ++i) + root->groups[i] = gl.gl_list[i]; + +out: + if (agl) { + gid_cache_release (&conf->gid_cache, agl); + } else { + if (gid_cache_add (&conf->gid_cache, &gl) != 1) + GF_FREE (gl.gl_list); + } + + return ret; +} + +int +server_resolve_groups (call_frame_t *frame, rpcsvc_request_t *req) +{ + xlator_t *this = NULL; + server_conf_t *conf = NULL; + + GF_VALIDATE_OR_GOTO ("server", frame, out); + GF_VALIDATE_OR_GOTO ("server", req, out); + + this = req->trans->xl; + conf = this->private; + + return gid_resolve (conf, frame->root); +out: + return -1; +} int server_decode_groups (call_frame_t *frame, rpcsvc_request_t *req) @@ -379,7 +488,10 @@ get_frame_from_request (rpcsvc_request_t *req) frame->root->client = client; frame->root->lk_owner = req->lk_owner; - server_decode_groups (frame, req); + if (priv->server_manage_gids) + server_resolve_groups (frame, req); + else + server_decode_groups (frame, req); frame->local = req; out: |