changeset 13823:3abbdbfdfaf3

3156 nfs: '.', '..', and filename with '/' return wrong error code Reviewed by: Eric Schrock <eric.schrock@delphix.com> Approved by: Richard Lowe <richlowe@richlowe.net>
author Daniil Lunev <d.lunev.mail@gmail.com>
date Thu, 30 Aug 2012 15:48:18 -0500
parents d13dbeb3e979
children 17189d594419
files usr/src/uts/common/fs/nfs/nfs4_srv.c usr/src/uts/common/fs/nfs/nfs4_subr.c usr/src/uts/common/nfs/nfs4.h
diffstat 3 files changed, 54 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/nfs/nfs4_srv.c	Thu Aug 30 15:30:57 2012 -0500
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv.c	Thu Aug 30 15:48:18 2012 -0500
@@ -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 @@
 	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 @@
 	 * 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;
 		}
 	}
@@ -1570,8 +1575,9 @@
 		*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 +2452,7 @@
 	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 +2502,9 @@
 		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 +2894,7 @@
 	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 +2914,9 @@
 		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;
 	}
 
@@ -4101,6 +4111,7 @@
 	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 +4142,9 @@
 		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 +4410,7 @@
 	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 +4467,15 @@
 		goto out;
 	}
 
-	if (!utf8_dir_verify(&args->oldname)) {
-		*cs->statusp = resp->status = NFS4ERR_INVAL;
-		goto out;
-	}
-
-	if (!utf8_dir_verify(&args->newname)) {
-		*cs->statusp = resp->status = NFS4ERR_INVAL;
+	status = utf8_dir_verify(&args->oldname);
+	if (status != NFS4_OK) {
+		*cs->statusp = resp->status = status;
+		goto out;
+	}
+
+	status = utf8_dir_verify(&args->newname);
+	if (status != NFS4_OK) {
+		*cs->statusp = resp->status = status;
 		goto out;
 	}
 
@@ -6079,8 +6094,9 @@
 		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 +6388,9 @@
 	 * 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);
 
--- a/usr/src/uts/common/fs/nfs/nfs4_subr.c	Thu Aug 30 15:30:57 2012 -0500
+++ b/usr/src/uts/common/fs/nfs/nfs4_subr.c	Thu Aug 30 15:48:18 2012 -0500
@@ -22,6 +22,9 @@
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ */
 
 /*
  *  	Copyright (c) 1983,1984,1985,1986,1987,1988,1989  AT&T.
@@ -713,33 +716,33 @@
 /*
  * utf8_dir_verify - checks that the utf8 string is valid
  */
-int
+nfsstat4
 utf8_dir_verify(utf8string *str)
 {
 	char *nm;
 	int len;
 
 	if (str == NULL)
-		return (0);
+		return (NFS4ERR_INVAL);
 
 	nm = str->utf8string_val;
 	len = str->utf8string_len;
 	if (nm == NULL || len == 0) {
-		return (0);
+		return (NFS4ERR_INVAL);
 	}
 
 	if (len == 1 && nm[0] == '.')
-		return (0);
+		return (NFS4ERR_BADNAME);
 	if (len == 2 && nm[0] == '.' && nm[1] == '.')
-		return (0);
+		return (NFS4ERR_BADNAME);
 
 	if (utf8_strchr(str, '/') != NULL)
-		return (0);
+		return (NFS4ERR_BADNAME);
 
 	if (utf8_strchr(str, '\0') != NULL)
-		return (0);
-
-	return (1);
+		return (NFS4ERR_BADNAME);
+
+	return (NFS4_OK);
 }
 
 /*
--- a/usr/src/uts/common/nfs/nfs4.h	Thu Aug 30 15:30:57 2012 -0500
+++ b/usr/src/uts/common/nfs/nfs4.h	Thu Aug 30 15:48:18 2012 -0500
@@ -22,6 +22,9 @@
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ */
 
 #ifndef _NFS4_H
 #define	_NFS4_H
@@ -1307,7 +1310,7 @@
 extern utf8string *str_to_utf8(char *, utf8string *);
 extern utf8string *utf8_copy(utf8string *, utf8string *);
 extern int	utf8_compare(const utf8string *, const utf8string *);
-extern int	utf8_dir_verify(utf8string *);
+extern nfsstat4	utf8_dir_verify(utf8string *);
 extern char	*utf8_strchr(utf8string *, const char);
 extern int	ln_ace4_cmp(nfsace4 *, nfsace4 *, int);
 extern int	vs_aent_to_ace4(vsecattr_t *, vsecattr_t *, int, int);