summaryrefslogtreecommitdiffstats
path: root/xlators
diff options
context:
space:
mode:
authorRaghavendra Bhat <raghavendra@redhat.com>2013-04-19 12:27:03 +0530
committerVijay Bellur <vbellur@redhat.com>2014-02-10 23:32:05 -0800
commit28209283a67f13802cc0c1d3df07c676926810a2 (patch)
tree5cf62085fa1a4bbc6d76eb1763f343c6116ea195 /xlators
parent97ce783de326b51fcba65737f07db2c314d1e218 (diff)
protocol/server: do not do root-squashing for trusted clients
* As of now clients mounting within the storage pool using that machine's ip/hostname are trusted clients (i.e clients local to the glusterd). * Be careful when the request itself comes in as nfsnobody (ex: posix tests). So move the squashing part to protocol/server when it creates a new frame for the request, instead of auth part of rpc layer. * For nfs servers do root-squashing without checking if it is trusted client, as all the nfs servers would be running within the storage pool, hence will be trusted clients for the bricks. * Provide one more option for mounting which actually says root-squash should/should not happen. This value is given priority only for the trusted clients. For non trusted clients, the volume option takes the priority. But for trusted clients if root-squash should not happen, then they have to be mounted with root-squash=no option. (This is done because by default blocking root-squashing for the trusted clients will cause problems for smb and UFO clients for which the requests have to be squashed if the option is enabled). * For geo-replication and defrag clients do not do root-squashing. * Introduce a new option in open-behind for doing read after successful open. Change-Id: I8a8359840313dffc34824f3ea80a9c48375067f0 BUG: 954057 Signed-off-by: Raghavendra Bhat <raghavendra@redhat.com> Reviewed-on: http://review.gluster.org/4863 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'xlators')
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volgen.c91
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volume-set.c6
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.c22
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.h8
-rwxr-xr-xxlators/mount/fuse/utils/mount.glusterfs.in13
-rw-r--r--xlators/performance/open-behind/src/open-behind.c23
-rw-r--r--xlators/protocol/server/src/server-handshake.c2
-rw-r--r--xlators/protocol/server/src/server-helpers.c157
-rw-r--r--xlators/protocol/server/src/server-helpers.h2
9 files changed, 320 insertions, 4 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c
index b26a7ef3d..3bb2f9a63 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volgen.c
+++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c
@@ -2517,6 +2517,9 @@ client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
xlator_t *xl = NULL;
char *volname = NULL;
glusterd_conf_t *conf = THIS->private;
+ char *tmp = NULL;
+ gf_boolean_t var = _gf_false;
+ gf_boolean_t ob = _gf_false;
GF_ASSERT (conf);
@@ -2582,7 +2585,93 @@ client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
}
}
- ret = client_graph_set_perf_options(graph, volinfo, set_dict);
+ /* Do not allow changing read-after-open option if root-squash is
+ enabled.
+ */
+ ret = dict_get_str (set_dict, "performance.read-after-open", &tmp);
+ if (!ret) {
+ ret = dict_get_str (volinfo->dict, "server.root-squash", &tmp);
+ if (!ret) {
+ ob = _gf_false;
+ ret = gf_string2boolean (tmp, &ob);
+ if (!ret && ob) {
+ gf_log (THIS->name, GF_LOG_WARNING,
+ "root-squash is enabled. Please turn it"
+ " off to change read-after-open "
+ "option");
+ ret = -1;
+ goto out;
+ }
+ }
+ }
+
+ /* open behind causes problems when root-squash is enabled
+ (by allowing reads to happen even though the squashed user
+ does not have permissions to do so) as it fakes open to be
+ successful and later sends reads on anonymous fds. So when
+ root-squash is enabled, open-behind's option to read after
+ open is done is also enabled.
+ */
+ ret = dict_get_str (set_dict, "server.root-squash", &tmp);
+ if (!ret) {
+ ret = gf_string2boolean (tmp, &var);
+ if (ret)
+ goto out;
+
+ if (var) {
+ ret = dict_get_str (volinfo->dict,
+ "performance.read-after-open",
+ &tmp);
+ if (!ret) {
+ ret = gf_string2boolean (tmp, &ob);
+ /* go ahead with turning read-after-open on
+ even if string2boolean conversion fails,
+ OR if read-after-open option is turned off
+ */
+ if (ret || !ob)
+ ret = dict_set_str (set_dict,
+ "performance.read-after-open",
+ "yes");
+ } else {
+ ret = dict_set_str (set_dict,
+ "performance.read-after-open",
+ "yes");
+ }
+ } else {
+ /* When root-squash has to be turned off, open-behind's
+ read-after-open option should be reset to what was
+ there before root-squash was turned on. If the option
+ cannot be found in volinfo's dict, it means that
+ option was not set before turning on root-squash.
+ */
+ ob = _gf_false;
+ ret = dict_get_str (volinfo->dict,
+ "performance.read-after-open",
+ &tmp);
+ if (!ret) {
+ ret = gf_string2boolean (tmp, &ob);
+
+ if (!ret && ob) {
+ ret = dict_set_str (set_dict,
+ "performance.read-after-open",
+ "yes");
+ }
+ }
+ /* consider operation is failure only if read-after-open
+ option is enabled and could not set into set_dict
+ */
+ if (!ob)
+ ret = 0;
+ }
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_WARNING, "setting "
+ "open behind option as part of root "
+ "squash failed");
+ goto out;
+ }
+ }
+
+ ret = client_graph_set_perf_options(graph, volinfo, set_dict);
if (ret)
goto out;
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
index db0a6374a..ab8cefedd 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
@@ -711,6 +711,12 @@ struct volopt_map_entry glusterd_volopt_map[] = {
.op_version = 3,
.flags = OPT_FLAG_CLIENT_OPT
},
+ { .key = "performance.read-after-open",
+ .voltype = "performance/open-behind",
+ .option = "read-after-open",
+ .op_version = 3,
+ .flags = OPT_FLAG_CLIENT_OPT
+ },
{ .key = "performance.read-ahead-page-count",
.voltype = "performance/read-ahead",
.option = "page-count",
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
index 315259ece..d9055468e 100644
--- a/xlators/mount/fuse/src/fuse-bridge.c
+++ b/xlators/mount/fuse/src/fuse-bridge.c
@@ -5323,6 +5323,18 @@ init (xlator_t *this_xl)
GF_OPTION_INIT ("congestion-threshold", priv->congestion_threshold,
int32, cleanup_exit);
+ GF_OPTION_INIT("no-root-squash", priv->no_root_squash, bool,
+ cleanup_exit);
+ /* change the client_pid to no-root-squash pid only if the
+ client is none of defrag process, hadoop access and gsyncd process.
+ */
+ if (!priv->client_pid_set) {
+ if (priv->no_root_squash == _gf_true) {
+ priv->client_pid_set = _gf_true;
+ priv->client_pid = GF_CLIENT_PID_NO_ROOT_SQUASH;
+ }
+ }
+
/* user has set only background-qlen, not congestion-threshold,
use the fuse kernel driver formula to set congestion. ie, 75% */
if (dict_get (this_xl->options, "background-qlen") &&
@@ -5563,5 +5575,15 @@ struct volume_options options[] = {
.type = GF_OPTION_TYPE_BOOL,
.default_value = "yes"
},
+ { .key = {"no-root-squash"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "false",
+ .description = "This is the mount option for disabling the "
+ "root squash for the client irrespective of whether the root-squash "
+ "option for the volume is set or not. But this option is honoured "
+ "only for the trusted clients. For non trusted clients this value "
+ "does not have any affect and the volume option for root-squash is "
+ "honoured.",
+ },
{ .key = {NULL} },
};
diff --git a/xlators/mount/fuse/src/fuse-bridge.h b/xlators/mount/fuse/src/fuse-bridge.h
index 34794b6ea..f1c4cb3f0 100644
--- a/xlators/mount/fuse/src/fuse-bridge.h
+++ b/xlators/mount/fuse/src/fuse-bridge.h
@@ -104,6 +104,14 @@ struct fuse_private {
int32_t fopen_keep_cache;
int32_t gid_cache_timeout;
gf_boolean_t enable_ino32;
+ /* This is the mount option for disabling the root-squash for the
+ mount irrespective of whether the root-squash option for the
+ volume is set or not. But this option is honoured only for
+ thr trusted clients. For non trusted clients this value does
+ not have any affect and the volume option for root-squash is
+ honoured.
+ */
+ gf_boolean_t no_root_squash;
fdtable_t *fdtable;
gid_cache_t gid_cache;
char *fuse_mountopts;
diff --git a/xlators/mount/fuse/utils/mount.glusterfs.in b/xlators/mount/fuse/utils/mount.glusterfs.in
index ff6b52460..d22f6a69b 100755
--- a/xlators/mount/fuse/utils/mount.glusterfs.in
+++ b/xlators/mount/fuse/utils/mount.glusterfs.in
@@ -171,7 +171,11 @@ start_glusterfs ()
cmd_line=$(echo "$cmd_line --aux-gfid-mount");
fi
- # options with values start here
+ if [ -n "$no_root_squash" ]; then
+ cmd_line=$(echo "$cmd_line --no-root-squash");
+ fi
+
+#options with values start here
if [ -n "$log_level" ]; then
cmd_line=$(echo "$cmd_line --log-level=$log_level");
fi
@@ -442,6 +446,13 @@ with_options()
"use-readdirp")
use_readdirp=$value
;;
+ "root-squash")
+ if [ $value == "no" ] ||
+ [ $value == "off" ] ||
+ [ $value == "disable" ] ||
+ [ $value == "false" ] ; then
+ no_root_squash=1;
+ fi ;;
*)
echo "Invalid option: $key"
exit 0
diff --git a/xlators/performance/open-behind/src/open-behind.c b/xlators/performance/open-behind/src/open-behind.c
index 29ef64364..742e4df3f 100644
--- a/xlators/performance/open-behind/src/open-behind.c
+++ b/xlators/performance/open-behind/src/open-behind.c
@@ -23,6 +23,11 @@ typedef struct ob_conf {
like mandatory locks
*/
gf_boolean_t lazy_open; /* delay backend open as much as possible */
+ gf_boolean_t read_after_open; /* instead of sending readvs on
+ anonymous fds, open the file
+ first and then send readv i.e
+ similar to what writev does
+ */
} ob_conf_t;
@@ -367,8 +372,14 @@ ob_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
{
call_stub_t *stub = NULL;
fd_t *wind_fd = NULL;
+ ob_conf_t *conf = NULL;
- wind_fd = ob_get_wind_fd (this, fd);
+ conf = this->private;
+
+ if (!conf->read_after_open)
+ wind_fd = ob_get_wind_fd (this, fd);
+ else
+ wind_fd = fd_ref (fd);
stub = fop_readv_stub (frame, default_readv_resume, wind_fd,
size, offset, flags, xdata);
@@ -894,6 +905,8 @@ reconfigure (xlator_t *this, dict_t *options)
bool, out);
GF_OPTION_RECONF ("lazy-open", conf->lazy_open, options, bool, out);
+ GF_OPTION_RECONF ("read-after-open", conf->read_after_open, options,
+ bool, out);
ret = 0;
out:
@@ -924,7 +937,7 @@ init (xlator_t *this)
GF_OPTION_INIT ("use-anonymous-fd", conf->use_anonymous_fd, bool, err);
GF_OPTION_INIT ("lazy-open", conf->lazy_open, bool, err);
-
+ GF_OPTION_INIT ("read-after-open", conf->read_after_open, bool, err);
this->private = conf;
return 0;
@@ -996,6 +1009,12 @@ struct volume_options options[] = {
"FOP arrives (e.g writev on the FD, unlink of the file). When option "
"is disabled, perform backend open right after unwinding open().",
},
+ { .key = {"read-after-open"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "no",
+ .description = "read is sent only after actual open happens and real "
+ "fd is obtained, instead of doing on anonymous fd (similar to write)",
+ },
{ .key = {NULL} }
};
diff --git a/xlators/protocol/server/src/server-handshake.c b/xlators/protocol/server/src/server-handshake.c
index d4941011d..708acd936 100644
--- a/xlators/protocol/server/src/server-handshake.c
+++ b/xlators/protocol/server/src/server-handshake.c
@@ -448,6 +448,8 @@ server_setvolume (rpcsvc_request_t *req)
if (req->trans->xl_private != client)
req->trans->xl_private = client;
+ auth_set_username_passwd (params, config_params, client);
+
ret = dict_get_int32 (params, "fops-version", &fop_version);
if (ret < 0) {
ret = dict_set_str (reply, "ERROR",
diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c
index b2b6c486f..c11011abf 100644
--- a/xlators/protocol/server/src/server-helpers.c
+++ b/xlators/protocol/server/src/server-helpers.c
@@ -302,6 +302,11 @@ get_frame_from_request (rpcsvc_request_t *req)
{
call_frame_t *frame = NULL;
client_t *client = NULL;
+ client_t *tmp_client = NULL;
+ xlator_t *this = NULL;
+ server_conf_t *priv = NULL;
+ clienttable_t *clienttable = NULL;
+ unsigned int i = 0;
GF_VALIDATE_OR_GOTO ("server", req, out);
@@ -315,6 +320,57 @@ get_frame_from_request (rpcsvc_request_t *req)
frame->root->unique = req->xid;
+ client = req->trans->xl_private;
+ this = req->trans->xl;
+ priv = this->private;
+ clienttable = this->ctx->clienttable;
+
+ for (i = 0; i < clienttable->max_clients; i++) {
+ tmp_client = clienttable->cliententries[i].client;
+ if (client == tmp_client) {
+ /* for non trusted clients username and password
+ would not have been set. So for non trusted clients
+ (i.e clients not from the same machine as the brick,
+ and clients from outside the storage pool)
+ do the root-squashing.
+ TODO: If any client within the storage pool (i.e
+ mounting within a machine from the pool but using
+ other machine's ip/hostname from the same pool)
+ is present treat it as a trusted client
+ */
+ if (!client->auth.username && req->pid != NFS_PID)
+ RPC_AUTH_ROOT_SQUASH (req);
+
+ /* Problem: If we just check whether the client is
+ trusted client and do not do root squashing for
+ them, then for smb clients and UFO clients root
+ squashing will never happen as they use the fuse
+ mounts done within the trusted pool (i.e they are
+ trusted clients).
+ Solution: To fix it, do root squashing for trusted
+ clients also. If one wants to have a client within
+ the storage pool for which root-squashing does not
+ happen, then the client has to be mounted with
+ --no-root-squash option. But for defrag client and
+ gsyncd client do not do root-squashing.
+ */
+ if (client->auth.username &&
+ req->pid != GF_CLIENT_PID_NO_ROOT_SQUASH &&
+ req->pid != GF_CLIENT_PID_GSYNCD &&
+ req->pid != GF_CLIENT_PID_DEFRAG)
+ RPC_AUTH_ROOT_SQUASH (req);
+
+ /* For nfs clients the server processes will be running
+ within the trusted storage pool machines. So if we
+ do not do root-squashing for nfs servers, thinking
+ that its a trusted client, then root-squashing wont
+ work for nfs clients.
+ */
+ if (req->pid == NFS_PID)
+ RPC_AUTH_ROOT_SQUASH (req);
+ }
+ }
+
frame->root->uid = req->uid;
frame->root->gid = req->gid;
frame->root->pid = req->pid;
@@ -935,3 +991,104 @@ server_ctx_get (client_t *client, xlator_t *xlator)
out:
return ctx;
}
+
+int
+auth_set_username_passwd (dict_t *input_params, dict_t *config_params,
+ client_t *client)
+{
+ int ret = 0;
+ data_t *allow_user = NULL;
+ data_t *passwd_data = NULL;
+ char *username = NULL;
+ char *password = NULL;
+ char *brick_name = NULL;
+ char *searchstr = NULL;
+ char *username_str = NULL;
+ char *tmp = NULL;
+ char *username_cpy = NULL;
+
+ ret = dict_get_str (input_params, "username", &username);
+ if (ret) {
+ gf_log ("auth/login", GF_LOG_DEBUG,
+ "username not found, returning DONT-CARE");
+ /* For non trusted clients username and password
+ will not be there. So dont reject the client.
+ */
+ ret = 0;
+ goto out;
+ }
+
+ ret = dict_get_str (input_params, "password", &password);
+ if (ret) {
+ gf_log ("auth/login", GF_LOG_WARNING,
+ "password not found, returning DONT-CARE");
+ goto out;
+ }
+
+ ret = dict_get_str (input_params, "remote-subvolume", &brick_name);
+ if (ret) {
+ gf_log ("auth/login", GF_LOG_ERROR,
+ "remote-subvolume not specified");
+ ret = -1;
+ goto out;
+ }
+
+ ret = gf_asprintf (&searchstr, "auth.login.%s.allow", brick_name);
+ if (-1 == ret) {
+ ret = 0;
+ goto out;
+ }
+
+ allow_user = dict_get (config_params, searchstr);
+ GF_FREE (searchstr);
+
+ if (allow_user) {
+ username_cpy = gf_strdup (allow_user->data);
+ if (!username_cpy)
+ goto out;
+
+ username_str = strtok_r (username_cpy, " ,", &tmp);
+
+ while (username_str) {
+ if (!fnmatch (username_str, username, 0)) {
+ ret = gf_asprintf (&searchstr,
+ "auth.login.%s.password",
+ username);
+ if (-1 == ret)
+ goto out;
+
+ passwd_data = dict_get (config_params,
+ searchstr);
+ GF_FREE (searchstr);
+
+ if (!passwd_data) {
+ gf_log ("auth/login", GF_LOG_ERROR,
+ "wrong username/password "
+ "combination");
+ ret = -1;
+ goto out;
+ }
+
+ ret = !((strcmp (data_to_str (passwd_data),
+ password))?0: -1);
+ if (!ret) {
+ client->auth.username =
+ gf_strdup (username);
+ client->auth.passwd =
+ gf_strdup (password);
+ }
+ if (ret == -1)
+ gf_log ("auth/login", GF_LOG_ERROR,
+ "wrong password for user %s",
+ username);
+ break;
+ }
+ username_str = strtok_r (NULL, " ,", &tmp);
+ }
+ }
+
+out:
+ GF_FREE (username_cpy);
+
+ return ret;
+}
diff --git a/xlators/protocol/server/src/server-helpers.h b/xlators/protocol/server/src/server-helpers.h
index 93ea35851..3c257b3bc 100644
--- a/xlators/protocol/server/src/server-helpers.h
+++ b/xlators/protocol/server/src/server-helpers.h
@@ -53,6 +53,8 @@ int serialize_rsp_dirent (gf_dirent_t *entries, gfs3_readdir_rsp *rsp);
int serialize_rsp_direntp (gf_dirent_t *entries, gfs3_readdirp_rsp *rsp);
int readdirp_rsp_cleanup (gfs3_readdirp_rsp *rsp);
int readdir_rsp_cleanup (gfs3_readdir_rsp *rsp);
+int auth_set_username_passwd (dict_t *input_params, dict_t *config_params,
+ struct _client_t *client);
server_ctx_t *server_ctx_get (client_t *client, xlator_t *xlator);