diff options
author | Niels de Vos <ndevos@redhat.com> | 2017-07-06 17:04:17 +0200 |
---|---|---|
committer | Niels de Vos <ndevos@redhat.com> | 2017-07-09 09:14:22 +0000 |
commit | e304f48fa262e5cdbe181fb3fee5dfb9c893108c (patch) | |
tree | 433aa5ca96c57789cad383f15fb34a4fc49ba657 /xlators/nfs/server/src/nfs3.c | |
parent | b81997264f079983fa02bd5fa2b3715224942b00 (diff) |
nfs: add permission checking for mounting over WebNFS
Solaris 10 uses WebNFS and not the MOUNT protocol. All permission checks
for allowing/denying clients to mount are done through the MNT handlers.
These handlers will not give out a filehandle to the NFS-client when
mounting is denied. This prevents clients from successful mounting.
However, over WebNFS a well known 'root-filehandle' is used directly
with the NFSv3 protocol.
When WebNFS was used, no permission checks (the "nfs.export-dir" option)
were applied. Now the WebNFS mount-handler in Gluster/NFS calls the
mnt3_parse_dir_exports() function that takes care of the permission
checking.
BUG: 1468291
Change-Id: Ic9dfd092473ba9c1c7b5fa38401cf9c0aa8395bb
Signed-off-by: Niels de Vos <ndevos@redhat.com>
Reviewed-on: https://review.gluster.org/17718
Smoke: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: soumya k <skoduri@redhat.com>
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
Diffstat (limited to 'xlators/nfs/server/src/nfs3.c')
-rw-r--r-- | xlators/nfs/server/src/nfs3.c | 69 |
1 files changed, 39 insertions, 30 deletions
diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c index 7da412d0a35..836428f8111 100644 --- a/xlators/nfs/server/src/nfs3.c +++ b/xlators/nfs/server/src/nfs3.c @@ -349,44 +349,51 @@ out: } -static enum nfsstat3 -nfs3_funge_webnfs_zerolen_fh (struct nfs3_state *nfs3st, struct nfs3_fh *fhd, - char *name) +static int +nfs3_funge_webnfs_zerolen_fh (rpcsvc_request_t *req, struct nfs3_state *nfs3st, + struct nfs3_fh *fhd, char *name) { - xlator_t *fungexl = NULL; - glfs_t *fs = NULL; - loc_t loc = { 0, }; - enum nfsstat3 nfsstat = NFS3ERR_SERVERFAULT; - int ret = -1; - size_t namelen = -1; + xlator_t *fungexl = NULL; + struct nfs_state *nfs = NULL; + glfs_t *fs = NULL; + loc_t loc = { 0, }; + int ret = -1; + char *subdir = NULL; + char volname[NAME_MAX] = { 0, }; fungexl = nfs_mntpath_to_xlator (nfs3st->exportslist, name); if (!fungexl) { - nfsstat = NFS3ERR_NOENT; + gf_msg_trace (GF_NFS3, 0, "failed to find xlator for volume"); + ret = -ENOENT; + goto out; + } + /* fungexl is valid, set for nfs3_request_xlator_deviceid() */ + rpcsvc_request_set_private (req, fungexl); + + /* Permission checks are done through mnt3_parse_dir_exports(). The + * "nfs.export-dir" option gets checked as well. */ + nfs = nfs_state (nfs3st->nfsx); + ret = mnt3_parse_dir_exports (req, nfs->mstate, name, _gf_false); + if (ret) { + gf_msg_trace (GF_NFS3, -ret, "mounting not possible"); goto out; } /* glfs_resolve_at copied from UDP MNT support */ fs = glfs_new_from_ctx (fungexl->ctx); if (!fs) { - nfsstat = NFS3ERR_NOENT; + gf_msg_trace (GF_NFS3, 0, "failed to create glfs instance"); + ret = -ENOENT; goto out; } - /* strip volname/ from 'name' */ - namelen = strlen(name); - while (namelen != 0) { - name++; - if (name[0] == '/') { - break; - } - namelen--; - } - gf_msg_debug (GF_NFS, 0, "NAME :%s ", name); + /* split name "volname/sub/dir/s" into pieces */ + subdir = mnt3_get_volume_subdir (name, (char**) &volname); - ret = glfs_resolve_at (fs, fungexl, NULL, name, &loc, NULL, 1, 0); + ret = glfs_resolve_at (fs, fungexl, NULL, subdir, &loc, NULL, 1, 0); if (ret != 0) { - nfsstat = NFS3ERR_NOENT; + gf_msg_trace (GF_NFS3, 0, "failed to resolve %s", subdir); + ret = -ENOENT; goto out; } @@ -399,17 +406,17 @@ nfs3_funge_webnfs_zerolen_fh (struct nfs3_state *nfs3st, struct nfs3_fh *fhd, fungexl); else { if (__nfs3_get_volume_id (nfs3st, fungexl, fhd->exportid) < 0) { - nfsstat = NFS3ERR_STALE; + ret = -ESTALE; goto out; } } - nfsstat = NFS3_OK; + ret = 0; out: if (fs) glfs_free_from_ctx (fs); - return nfsstat; + return ret; } @@ -513,8 +520,10 @@ nfs3_solaris_zerolen_fh (struct nfs3_fh *fh, int fhlen) if (nfs3_fh_validate (fh)) return 0; - if (fhlen == 0) + if (fhlen == 0) { + gf_msg_trace (GF_NFS3, 0, "received WebNFS request"); return 1; + } return 0; } @@ -1593,8 +1602,8 @@ nfs3_lookup (rpcsvc_request_t *req, struct nfs3_fh *fh, int fhlen, char *name) name); nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret); if (nfs3_solaris_zerolen_fh (fh, fhlen)) { - stat = nfs3_funge_webnfs_zerolen_fh (nfs3, fh, name); - if (stat != NFS3_OK) + ret = nfs3_funge_webnfs_zerolen_fh (req, nfs3, fh, name); + if (ret < 0) goto nfs3err; /* this fh means we're doing a mount, name is no more useful */ @@ -1614,11 +1623,11 @@ nfs3_lookup (rpcsvc_request_t *req, struct nfs3_fh *fh, int fhlen, char *name) gf_msg (GF_NFS, GF_LOG_ERROR, -ret, NFS_MSG_HARD_RESOLVE_FAIL, "failed to start hard resolve"); - stat = nfs3_errno_to_nfsstat3 (-ret); } nfs3err: if (ret < 0) { + stat = nfs3_errno_to_nfsstat3 (-ret); nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_LOOKUP, stat, -ret, cs ? cs->resolvedloc.path : NULL); |