Module Name:    src
Committed By:   riastradh
Date:           Fri Jul 28 14:37:27 UTC 2017

Modified Files:
        src/sys/netsmb: smb_subr.c smb_subr.h smb_usr.c

Log Message:
Plug another overflow: refuse bogus sa_len from user.


To generate a diff of this commit:
cvs rdiff -u -r1.37 -r1.38 src/sys/netsmb/smb_subr.c
cvs rdiff -u -r1.21 -r1.22 src/sys/netsmb/smb_subr.h
cvs rdiff -u -r1.17 -r1.18 src/sys/netsmb/smb_usr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netsmb/smb_subr.c
diff -u src/sys/netsmb/smb_subr.c:1.37 src/sys/netsmb/smb_subr.c:1.38
--- src/sys/netsmb/smb_subr.c:1.37	Sat Nov 15 18:52:45 2014
+++ src/sys/netsmb/smb_subr.c	Fri Jul 28 14:37:27 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: smb_subr.c,v 1.37 2014/11/15 18:52:45 nakayama Exp $	*/
+/*	$NetBSD: smb_subr.c,v 1.38 2017/07/28 14:37:27 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2000-2001 Boris Popov
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: smb_subr.c,v 1.37 2014/11/15 18:52:45 nakayama Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smb_subr.c,v 1.38 2017/07/28 14:37:27 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -380,3 +380,32 @@ dup_sockaddr(struct sockaddr *sa, int ca
 		memcpy(sa2, sa, sa->sa_len);
 	return sa2;
 }
+
+int
+dup_sockaddr_copyin(struct sockaddr **ksap, struct sockaddr *usa,
+    size_t usalen)
+{
+	struct sockaddr *ksa;
+
+	/* Make sure user provided enough data for a generic sockaddr.  */
+	if (usalen < sizeof(*ksa))
+		return EINVAL;
+
+	/* Don't let the user overfeed us.  */
+	usalen = MIN(usalen, sizeof(struct sockaddr_storage));
+
+	/* Copy the buffer in from userland.  */
+	ksa = smb_memdupin(usa, usalen);
+	if (ksa == NULL)
+		return ENOMEM;
+
+	/* Make sure the user's idea of sa_len is reasonable.  */
+	if (ksa->sa_len > usalen) {
+		smb_memfree(ksa);
+		return EINVAL;
+	}
+
+	/* Success!  */
+	*ksap = ksa;
+	return 0;
+}

Index: src/sys/netsmb/smb_subr.h
diff -u src/sys/netsmb/smb_subr.h:1.21 src/sys/netsmb/smb_subr.h:1.22
--- src/sys/netsmb/smb_subr.h:1.21	Tue Mar 13 18:41:01 2012
+++ src/sys/netsmb/smb_subr.h	Fri Jul 28 14:37:27 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: smb_subr.h,v 1.21 2012/03/13 18:41:01 elad Exp $	*/
+/*	$NetBSD: smb_subr.h,v 1.22 2017/07/28 14:37:27 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2000-2001, Boris Popov
@@ -128,5 +128,6 @@ int  smb_put_asunistring(struct smb_rq *
 #endif
 
 struct sockaddr *dup_sockaddr(struct sockaddr *, int);
+int dup_sockaddr_copyin(struct sockaddr **, struct sockaddr *, size_t);
 
 #endif /* !_NETSMB_SMB_SUBR_H_ */

Index: src/sys/netsmb/smb_usr.c
diff -u src/sys/netsmb/smb_usr.c:1.17 src/sys/netsmb/smb_usr.c:1.18
--- src/sys/netsmb/smb_usr.c:1.17	Fri Jul 28 14:20:46 2017
+++ src/sys/netsmb/smb_usr.c	Fri Jul 28 14:37:27 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: smb_usr.c,v 1.17 2017/07/28 14:20:46 riastradh Exp $	*/
+/*	$NetBSD: smb_usr.c,v 1.18 2017/07/28 14:37:27 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2000-2001 Boris Popov
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: smb_usr.c,v 1.17 2017/07/28 14:20:46 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smb_usr.c,v 1.18 2017/07/28 14:37:27 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/malloc.h>
@@ -65,6 +65,7 @@ static int
 smb_usr_vc2spec(struct smbioc_ossn *dp, struct smb_vcspec *spec)
 {
 	int flags = 0;
+	int error;
 
 	memset(spec, 0, sizeof(*spec));
 	if (dp->ioc_user[0] == 0)
@@ -75,21 +76,16 @@ smb_usr_vc2spec(struct smbioc_ossn *dp, 
 		SMBERROR(("no local charset ?\n"));
 		return EINVAL;
 	}
-	if (dp->ioc_svlen < sizeof(*spec->sap))
-		return EINVAL;
 
-	spec->sap = smb_memdupin(dp->ioc_server, dp->ioc_svlen);
-	if (spec->sap == NULL)
-		return ENOMEM;
+	error = dup_sockaddr_copyin(&spec->sap, dp->ioc_server, dp->ioc_svlen);
+	if (error)
+		return error;
 	if (dp->ioc_local) {
-		if (dp->ioc_lolen < sizeof(*spec->lap)) {
-			smb_usr_vcspec_free(spec);
-			return ENOMEM;
-		}
-		spec->lap = smb_memdupin(dp->ioc_local, dp->ioc_lolen);
-		if (spec->lap == NULL) {
+		error = dup_sockaddr_copyin(&spec->lap, dp->ioc_local,
+		    dp->ioc_lolen);
+		if (error) {
 			smb_usr_vcspec_free(spec);
-			return ENOMEM;
+			return error;
 		}
 	}
 	spec->srvname = dp->ioc_srvname;

Reply via email to