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;