From a29f1a0e36bde5ca7b8f3762f10b210b5e12a875 Mon Sep 17 00:00:00 2001 From: Venky Shankar Date: Wed, 5 Oct 2011 16:56:30 +0530 Subject: fuse: flip xattr key from user to trusted namespace for certain clients. This is needed for gsyncd/hadoop-plugin running as non-super user to be able to request extended attributes under trusted namespace. Request for a key is made under 'user.' namespace and is flipped by fuse xlator for specific xattr name to the corresponding 'trusted.' extended attribute. Both applications set a identifier (client-pid) while doing a FUSE mount, which is checked by get/set/remove interfaces in FUSE translator. Change-Id: I72f77a5dd1ee1d69c8b0e09209449348dbcf879a BUG: 3701 Reviewed-on: http://review.gluster.com/563 Tested-by: Gluster Build System Reviewed-by: Vijay Bellur --- xlators/mount/fuse/src/fuse-bridge.c | 37 +++++++++++++-- xlators/mount/fuse/src/fuse-bridge.h | 3 ++ xlators/mount/fuse/src/fuse-helpers.c | 84 +++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 4 deletions(-) (limited to 'xlators/mount') diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index 78bed048058..7e0022d3d58 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -2338,6 +2338,7 @@ fuse_setxattr (xlator_t *this, fuse_in_header_t *finh, void *msg) fuse_state_t *state = NULL; char *dict_value = NULL; int32_t ret = -1; + char *newkey = NULL; priv = this->private; @@ -2405,13 +2406,20 @@ fuse_setxattr (xlator_t *this, fuse_in_header_t *finh, void *msg) return; } + ret = fuse_flip_xattr_ns (priv, name, &newkey); + if (ret) { + send_fuse_err (this, finh, ENOMEM); + free_fuse_state (state); + return; + } + dict_value = memdup (value, fsi->size); - dict_set (state->dict, (char *)name, + dict_set (state->dict, newkey, data_from_dynptr ((void *)dict_value, fsi->size)); dict_ref (state->dict); state->flags = fsi->flags; - state->name = gf_strdup (name); + state->name = newkey; uuid_copy (state->resolve.gfid, state->loc.inode->gfid); state->resolve.path = gf_strdup (state->loc.path); @@ -2557,6 +2565,8 @@ fuse_getxattr (xlator_t *this, fuse_in_header_t *finh, void *msg) fuse_state_t *state = NULL; int32_t ret = -1; struct fuse_private *priv = NULL; + int rv = 0; + char *newkey = NULL; priv = this->private; @@ -2611,13 +2621,21 @@ fuse_getxattr (xlator_t *this, fuse_in_header_t *finh, void *msg) return; } + rv = fuse_flip_xattr_ns (priv, name, &newkey); + if (rv) { + send_fuse_err (this, finh, ENOMEM); + free_fuse_state (state); + goto out; + } + state->size = fgxi->size; - state->name = gf_strdup (name); + state->name = newkey; uuid_copy (state->resolve.gfid, state->loc.inode->gfid); state->resolve.path = gf_strdup (state->loc.path); fuse_resolve_and_resume (state, fuse_getxattr_resume); + out: return; } @@ -2681,7 +2699,11 @@ fuse_removexattr (xlator_t *this, fuse_in_header_t *finh, void *msg) char *name = msg; fuse_state_t *state = NULL; + fuse_private_t *priv = NULL; int32_t ret = -1; + char *newkey = NULL; + + priv = this->private; GET_STATE (this, finh, state); ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL); @@ -2696,7 +2718,14 @@ fuse_removexattr (xlator_t *this, fuse_in_header_t *finh, void *msg) return; } - state->name = gf_strdup (name); + ret = fuse_flip_xattr_ns (priv, name, &newkey); + if (ret) { + send_fuse_err (this, finh, ENOMEM); + free_fuse_state (state); + return; + } + + state->name = newkey; uuid_copy (state->resolve.gfid, state->loc.inode->gfid); state->resolve.path = gf_strdup (state->loc.path); diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h index c729c9468fc..2215ad22f54 100644 --- a/xlators/mount/fuse/src/fuse-bridge.h +++ b/xlators/mount/fuse/src/fuse-bridge.h @@ -292,4 +292,7 @@ inode_t *fuse_ino_to_inode (uint64_t ino, xlator_t *fuse); int fuse_resolve_and_resume (fuse_state_t *state, fuse_resume_fn_t fn); int send_fuse_err (xlator_t *this, fuse_in_header_t *finh, int error); int fuse_gfid_set (fuse_state_t *state); +int fuse_flip_xattr_ns (struct fuse_private *priv, char *okey, char **nkey); +int fuse_flip_user_to_trusted (char *okey, char **nkey); +int fuse_xattr_alloc_default (char *okey, char **nkey); #endif /* _GF_FUSE_BRIDGE_H_ */ diff --git a/xlators/mount/fuse/src/fuse-helpers.c b/xlators/mount/fuse/src/fuse-helpers.c index 5fe3dc9f4cc..f40d1d6a50e 100644 --- a/xlators/mount/fuse/src/fuse-helpers.c +++ b/xlators/mount/fuse/src/fuse-helpers.c @@ -360,5 +360,89 @@ gf_fuse_stat2attr (struct iatt *st, struct fuse_attr *fa) #endif } +int +fuse_flip_user_to_trusted (char *okey, char **nkey) +{ + int ret = 0; + char *key = NULL; + + key = GF_CALLOC (1, strlen(okey) + 10, gf_common_mt_char); + if (!key) { + ret = -1; + goto out; + } + + okey += 5; + strncpy(key, "trusted.", 8); + strncat(key+8, okey, strlen(okey)); + + *nkey = key; + + out: + return ret; +} + +int +fuse_xattr_alloc_default (char *okey, char **nkey) +{ + int ret = 0; + *nkey = gf_strdup (okey); + if (!*nkey) + ret = -1; + return ret; +} +int +fuse_flip_xattr_ns (fuse_private_t *priv, char *okey, char **nkey) +{ + int ret = 0; + gf_boolean_t need_flip = _gf_false; + gf_client_pid_t npid = 0; + + npid = priv->client_pid; + if (gf_client_pid_check (npid)) { + ret = fuse_xattr_alloc_default (okey, nkey); + goto out; + } + + switch (npid) { + /* + * These two cases will never execute as we check the + * pid range above, but are kept to keep the compiler + * happy. + */ + case GF_CLIENT_PID_MAX: + case GF_CLIENT_PID_MIN: + goto out; + + case GF_CLIENT_PID_GSYNCD: + /* valid xattr(s): *xtime, volume-mark* */ + gf_log("glusterfs-fuse", GF_LOG_DEBUG, "PID: %d, checking xattr(s): " + "volume-mark*, *xtime", npid); + if ( (strcmp (okey, "user.glusterfs.volume-mark") == 0) + || (fnmatch (okey, "user.glusterfs.volume-mark.*", FNM_PERIOD) == 0) + || (fnmatch ("user.glusterfs.*.xtime", okey, FNM_PERIOD) == 0) ) + need_flip = _gf_true; + break; + + case GF_CLIENT_PID_HADOOP: + /* valid xattr(s): pathinfo */ + gf_log("glusterfs-fuse", GF_LOG_DEBUG, "PID: %d, checking xattr(s): " + "pathinfo", npid); + if (strcmp (okey, "user.glusterfs.pathinfo") == 0) + need_flip = _gf_true; + break; + } + + if (need_flip) { + gf_log ("glusterfs-fuse", GF_LOG_DEBUG, "flipping %s to trusted equivalent", + okey); + ret = fuse_flip_user_to_trusted (okey, nkey); + } else { + /* if we cannot match, continue with what we got */ + ret = fuse_xattr_alloc_default (okey, nkey); + } + out: + return ret; +} -- cgit