summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/nfs/nfs4_srv.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/fs/nfs/nfs4_srv.c')
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_srv.c100
1 files changed, 55 insertions, 45 deletions
diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv.c b/usr/src/uts/common/fs/nfs/nfs4_srv.c
index 29a9d67497..f2a9734541 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_srv.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv.c
@@ -21,6 +21,9 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
+/*
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ */
/*
* Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
@@ -1131,6 +1134,7 @@ rfs4_op_secinfo(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
char *nm;
struct sockaddr *ca;
char *name = NULL;
+ nfsstat4 status = NFS4_OK;
DTRACE_NFSV4_2(op__secinfo__start, struct compound_state *, cs,
SECINFO4args *, args);
@@ -1154,11 +1158,12 @@ rfs4_op_secinfo(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
* do not error out if the component name is a "..".
* SECINFO will return its parents secinfo data for SECINFO "..".
*/
- if (!utf8_dir_verify(utfnm)) {
+ status = utf8_dir_verify(utfnm);
+ if (status != NFS4_OK) {
if (utfnm->utf8string_len != 2 ||
utfnm->utf8string_val[0] != '.' ||
utfnm->utf8string_val[1] != '.') {
- *cs->statusp = resp->status = NFS4ERR_INVAL;
+ *cs->statusp = resp->status = status;
goto out;
}
}
@@ -1336,7 +1341,8 @@ rfs4_op_access(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
blequal(clabel, slabel)))
resp->access |=
(args->access & (ACCESS4_MODIFY | ACCESS4_EXTEND));
- resp->supported |= (ACCESS4_MODIFY | ACCESS4_EXTEND);
+ resp->supported |=
+ resp->access & (ACCESS4_MODIFY | ACCESS4_EXTEND);
}
if (checkwriteperm &&
@@ -1570,8 +1576,9 @@ rfs4_op_create(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
*cs->statusp = resp->status = NFS4ERR_NOTDIR;
goto out;
}
- if (!utf8_dir_verify(&args->objname)) {
- *cs->statusp = resp->status = NFS4ERR_INVAL;
+ status = utf8_dir_verify(&args->objname);
+ if (status != NFS4_OK) {
+ *cs->statusp = resp->status = status;
goto out;
}
@@ -2446,6 +2453,7 @@ rfs4_op_link(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
uint_t len;
struct sockaddr *ca;
char *name = NULL;
+ nfsstat4 status;
DTRACE_NFSV4_2(op__link__start, struct compound_state *, cs,
LINK4args *, args);
@@ -2495,8 +2503,9 @@ rfs4_op_link(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
goto out;
}
- if (!utf8_dir_verify(&args->newname)) {
- *cs->statusp = resp->status = NFS4ERR_INVAL;
+ status = utf8_dir_verify(&args->newname);
+ if (status != NFS4_OK) {
+ *cs->statusp = resp->status = status;
goto out;
}
@@ -2886,6 +2895,7 @@ rfs4_op_lookup(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
uint_t len;
struct sockaddr *ca;
char *name = NULL;
+ nfsstat4 status;
DTRACE_NFSV4_2(op__lookup__start, struct compound_state *, cs,
LOOKUP4args *, args);
@@ -2905,8 +2915,9 @@ rfs4_op_lookup(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
goto out;
}
- if (!utf8_dir_verify(&args->objname)) {
- *cs->statusp = resp->status = NFS4ERR_INVAL;
+ status = utf8_dir_verify(&args->objname);
+ if (status != NFS4_OK) {
+ *cs->statusp = resp->status = status;
goto out;
}
@@ -3655,30 +3666,6 @@ out:
}
/*
- * A directory entry is a valid nfsv4 entry if
- * - it has a non-zero ino
- * - it is not a dot or dotdot name
- * - it is visible in a pseudo export or in a real export that can
- * only have a limited view.
- */
-static bool_t
-valid_nfs4_entry(struct exportinfo *exi, struct dirent64 *dp,
- int *expseudo, int check_visible)
-{
- if (dp->d_ino == 0 || NFS_IS_DOTNAME(dp->d_name)) {
- *expseudo = 0;
- return (FALSE);
- }
-
- if (! check_visible) {
- *expseudo = 0;
- return (TRUE);
- }
-
- return (nfs_visible_inode(exi, dp->d_ino, expseudo));
-}
-
-/*
* set_rdattr_params sets up the variables used to manage what information
* to get for each directory entry.
*/
@@ -4101,6 +4088,7 @@ rfs4_op_remove(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
bslabel_t *clabel;
struct sockaddr *ca;
char *name = NULL;
+ nfsstat4 status;
DTRACE_NFSV4_2(op__remove__start, struct compound_state *, cs,
REMOVE4args *, args);
@@ -4131,8 +4119,9 @@ rfs4_op_remove(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
goto out;
}
- if (!utf8_dir_verify(&args->target)) {
- *cs->statusp = resp->status = NFS4ERR_INVAL;
+ status = utf8_dir_verify(&args->target);
+ if (status != NFS4_OK) {
+ *cs->statusp = resp->status = status;
goto out;
}
@@ -4398,6 +4387,7 @@ rfs4_op_rename(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
struct sockaddr *ca;
char *converted_onm = NULL;
char *converted_nnm = NULL;
+ nfsstat4 status;
DTRACE_NFSV4_2(op__rename__start, struct compound_state *, cs,
RENAME4args *, args);
@@ -4454,13 +4444,15 @@ rfs4_op_rename(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
goto out;
}
- if (!utf8_dir_verify(&args->oldname)) {
- *cs->statusp = resp->status = NFS4ERR_INVAL;
+ status = utf8_dir_verify(&args->oldname);
+ if (status != NFS4_OK) {
+ *cs->statusp = resp->status = status;
goto out;
}
- if (!utf8_dir_verify(&args->newname)) {
- *cs->statusp = resp->status = NFS4ERR_INVAL;
+ status = utf8_dir_verify(&args->newname);
+ if (status != NFS4_OK) {
+ *cs->statusp = resp->status = status;
goto out;
}
@@ -5789,6 +5781,8 @@ rfs4_compound(COMPOUND4args *args, COMPOUND4res *resp, struct exportinfo *exi,
cs.statusp = &resp->status;
cs.req = req;
+ resp->array = NULL;
+ resp->array_len = 0;
/*
* XXX for now, minorversion should be zero
@@ -5796,14 +5790,17 @@ rfs4_compound(COMPOUND4args *args, COMPOUND4res *resp, struct exportinfo *exi,
if (args->minorversion != NFS4_MINORVERSION) {
DTRACE_NFSV4_2(compound__start, struct compound_state *,
&cs, COMPOUND4args *, args);
- resp->array_len = 0;
- resp->array = NULL;
resp->status = NFS4ERR_MINOR_VERS_MISMATCH;
DTRACE_NFSV4_2(compound__done, struct compound_state *,
&cs, COMPOUND4res *, resp);
return;
}
+ if (args->array_len == 0) {
+ resp->status = NFS4_OK;
+ return;
+ }
+
ASSERT(exi == NULL);
ASSERT(cr == NULL);
@@ -6079,8 +6076,9 @@ rfs4_lookup(component4 *component, struct svc_req *req,
return (NFS4ERR_NOTDIR);
}
- if (!utf8_dir_verify(component))
- return (NFS4ERR_INVAL);
+ status = utf8_dir_verify(component);
+ if (status != NFS4_OK)
+ return (status);
nm = utf8_to_fn(component, &len, NULL);
if (nm == NULL) {
@@ -6372,8 +6370,9 @@ rfs4_createfile(OPEN4args *args, struct svc_req *req, struct compound_state *cs,
* the including directory on success.
*/
component = &args->open_claim4_u.file;
- if (!utf8_dir_verify(component))
- return (NFS4ERR_INVAL);
+ status = utf8_dir_verify(component);
+ if (status != NFS4_OK)
+ return (status);
nm = utf8_to_fn(component, &buflen, NULL);
@@ -7594,6 +7593,12 @@ rfs4_op_open_confirm(nfs_argop4 *argop, nfs_resop4 *resop,
goto out;
}
+ if (cs->vp->v_type != VREG) {
+ *cs->statusp = resp->status =
+ cs->vp->v_type == VDIR ? NFS4ERR_ISDIR : NFS4ERR_INVAL;
+ return;
+ }
+
status = rfs4_get_state(&args->open_stateid, &sp, RFS4_DBS_VALID);
if (status != NFS4_OK) {
*cs->statusp = resp->status = status;
@@ -7709,6 +7714,11 @@ rfs4_op_open_downgrade(nfs_argop4 *argop, nfs_resop4 *resop,
goto out;
}
+ if (cs->vp->v_type != VREG) {
+ *cs->statusp = resp->status = NFS4ERR_INVAL;
+ return;
+ }
+
status = rfs4_get_state(&args->open_stateid, &sp, RFS4_DBS_VALID);
if (status != NFS4_OK) {
*cs->statusp = resp->status = status;