Module Name: src Committed By: snj Date: Sat Aug 19 04:44:54 UTC 2017
Modified Files: src/sys/netsmb [netbsd-6-1]: smb_dev.c smb_subr.c smb_subr.h smb_usr.c Log Message: Pull up following revision(s) (requested by mrg in ticket #1487): sys/netsmb/smb_dev.c: 1.50 sys/netsmb/smb_subr.c: 1.38 sys/netsmb/smb_subr.h: 1.22 sys/netsmb/smb_usr.c: 1.17-1.19 Reject allocations for too-small buffers from userland. >From Ilja Van Sprundel. -- Plug another overflow: refuse bogus sa_len from user. -- Reject negative ioc_setupcnt. -- Reject negative offset/count for smb read/write. Not clear that this is actually a problem for the kernel -- might overwrite user's buffers or return garbage to user, but that's their own damn fault. But it's hard to imagine that negative offset/count ever makes sense, and I haven't ruled out a problem for the kernel. To generate a diff of this commit: cvs rdiff -u -r1.39 -r1.39.20.1 src/sys/netsmb/smb_dev.c cvs rdiff -u -r1.36 -r1.36.22.1 src/sys/netsmb/smb_subr.c cvs rdiff -u -r1.20 -r1.20.20.1 src/sys/netsmb/smb_subr.h cvs rdiff -u -r1.16 -r1.16.32.1 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_dev.c diff -u src/sys/netsmb/smb_dev.c:1.39 src/sys/netsmb/smb_dev.c:1.39.20.1 --- src/sys/netsmb/smb_dev.c:1.39 Fri Dec 17 14:27:34 2010 +++ src/sys/netsmb/smb_dev.c Sat Aug 19 04:44:53 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: smb_dev.c,v 1.39 2010/12/17 14:27:34 pooka Exp $ */ +/* $NetBSD: smb_dev.c,v 1.39.20.1 2017/08/19 04:44:53 snj Exp $ */ /* * Copyright (c) 2000-2001 Boris Popov @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: smb_dev.c,v 1.39 2010/12/17 14:27:34 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: smb_dev.c,v 1.39.20.1 2017/08/19 04:44:53 snj Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -334,6 +334,8 @@ nsmb_dev_ioctl(dev_t dev, u_long cmd, vo struct uio auio; struct iovec iov; + if (rwrq->ioc_cnt < 0 || rwrq->ioc_offset < 0) + return EINVAL; if ((ssp = sdp->sd_share) == NULL) return ENOTCONN; iov.iov_base = rwrq->ioc_base; Index: src/sys/netsmb/smb_subr.c diff -u src/sys/netsmb/smb_subr.c:1.36 src/sys/netsmb/smb_subr.c:1.36.22.1 --- src/sys/netsmb/smb_subr.c:1.36 Sun Sep 25 13:42:30 2011 +++ src/sys/netsmb/smb_subr.c Sat Aug 19 04:44:53 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: smb_subr.c,v 1.36 2011/09/25 13:42:30 chs Exp $ */ +/* $NetBSD: smb_subr.c,v 1.36.22.1 2017/08/19 04:44:53 snj Exp $ */ /* * Copyright (c) 2000-2001 Boris Popov @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: smb_subr.c,v 1.36 2011/09/25 13:42:30 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: smb_subr.c,v 1.36.22.1 2017/08/19 04:44:53 snj Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -371,3 +371,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.20 src/sys/netsmb/smb_subr.h:1.20.20.1 --- src/sys/netsmb/smb_subr.h:1.20 Fri Dec 17 13:05:29 2010 +++ src/sys/netsmb/smb_subr.h Sat Aug 19 04:44:53 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: smb_subr.h,v 1.20 2010/12/17 13:05:29 pooka Exp $ */ +/* $NetBSD: smb_subr.h,v 1.20.20.1 2017/08/19 04:44:53 snj Exp $ */ /* * Copyright (c) 2000-2001, Boris Popov @@ -127,5 +127,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.16 src/sys/netsmb/smb_usr.c:1.16.32.1 --- src/sys/netsmb/smb_usr.c:1.16 Wed Mar 18 16:00:24 2009 +++ src/sys/netsmb/smb_usr.c Sat Aug 19 04:44:53 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: smb_usr.c,v 1.16 2009/03/18 16:00:24 cegger Exp $ */ +/* $NetBSD: smb_usr.c,v 1.16.32.1 2017/08/19 04:44:53 snj Exp $ */ /* * Copyright (c) 2000-2001 Boris Popov @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: smb_usr.c,v 1.16 2009/03/18 16:00:24 cegger Exp $"); +__KERNEL_RCSID(0, "$NetBSD: smb_usr.c,v 1.16.32.1 2017/08/19 04:44:53 snj 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) @@ -76,14 +77,15 @@ smb_usr_vc2spec(struct smbioc_ossn *dp, 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) { - 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; @@ -298,7 +300,7 @@ smb_usr_t2request(struct smb_share *ssp, struct mdchain *mdp; int error, len; - if (dp->ioc_setupcnt > 3) + if (dp->ioc_setupcnt < 0 || dp->ioc_setupcnt > 3) return EINVAL; error = smb_t2_alloc(SSTOCP(ssp), dp->ioc_setup[0], scred, &t2p); if (error)