Module Name: src Committed By: riastradh Date: Fri Jul 28 16:55:48 UTC 2017
Modified Files: src/sys/compat/svr4: svr4_stream.c Log Message: Fix some of the multitudinous holes in svr4 streams. We should never have enabled this by default; it is a minefield. >From Ilja Van Sprundel. To generate a diff of this commit: cvs rdiff -u -r1.88 -r1.89 src/sys/compat/svr4/svr4_stream.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/compat/svr4/svr4_stream.c diff -u src/sys/compat/svr4/svr4_stream.c:1.88 src/sys/compat/svr4/svr4_stream.c:1.89 --- src/sys/compat/svr4/svr4_stream.c:1.88 Wed Apr 26 03:02:48 2017 +++ src/sys/compat/svr4/svr4_stream.c Fri Jul 28 16:55:48 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: svr4_stream.c,v 1.88 2017/04/26 03:02:48 riastradh Exp $ */ +/* $NetBSD: svr4_stream.c,v 1.89 2017/07/28 16:55:48 riastradh Exp $ */ /*- * Copyright (c) 1994, 2008 The NetBSD Foundation, Inc. @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: svr4_stream.c,v 1.88 2017/04/26 03:02:48 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: svr4_stream.c,v 1.89 2017/07/28 16:55:48 riastradh Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -527,7 +527,8 @@ si_listen(file_t *fp, int fd, struct svr if (st == NULL) return EINVAL; - if (ioc->len > sizeof(lst)) + if (ioc->len < offsetof(struct svr4_strmcmd, pad) || + ioc->len > sizeof(lst)) return EINVAL; if ((error = copyin(NETBSD32PTR(ioc->buf), &lst, ioc->len)) != 0) @@ -717,7 +718,9 @@ ti_getinfo(file_t *fp, int fd, struct sv memset(&info, 0, sizeof(info)); - if (ioc->len > sizeof(info)) + /* tsdu is next after cmd, the only field we read */ + if (ioc->len < offsetof(struct svr4_infocmd, tsdu) || + ioc->len > sizeof(info)) return EINVAL; if ((error = copyin(NETBSD32PTR(ioc->buf), &info, ioc->len)) != 0) @@ -763,7 +766,8 @@ ti_bind(file_t *fp, int fd, struct svr4_ return EINVAL; } - if (ioc->len > sizeof(bnd)) + if (ioc->len < offsetof(struct svr4_strmcmd, pad) || + ioc->len > sizeof(bnd)) return EINVAL; if ((error = copyin(NETBSD32PTR(ioc->buf), &bnd, ioc->len)) != 0) @@ -773,6 +777,8 @@ ti_bind(file_t *fp, int fd, struct svr4_ DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd)); return EINVAL; } + if (bnd.offs < 0) + return EINVAL; switch (st->s_family) { case AF_INET: @@ -782,6 +788,9 @@ ti_bind(file_t *fp, int fd, struct svr4_ if (bnd.offs == 0) goto reply; + if (ioc->len < sizeof(struct svr4_netaddr_in) || + bnd.offs > ioc->len - sizeof(struct svr4_netaddr_in)) + return EINVAL; netaddr_to_sockaddr_in(sain, &bnd); DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n", @@ -795,6 +804,9 @@ ti_bind(file_t *fp, int fd, struct svr4_ if (bnd.offs == 0) goto reply; + if (ioc->len < sizeof(struct svr4_netaddr_un) || + bnd.offs > ioc->len - sizeof(struct svr4_netaddr_un)) + return EINVAL; netaddr_to_sockaddr_un(saun, &bnd); if (saun->sun_path[0] == '\0') @@ -1412,7 +1424,8 @@ svr4_sys_putmsg(struct lwp *l, const str goto out; } - if (ctl.len > sizeof(sc)) { + if (ctl.len < offsetof(struct svr4_strmcmd, pad) || + ctl.len > sizeof(sc)) { DPRINTF(("putmsg: Bad control size %ld != %d\n", (unsigned long)sizeof(struct svr4_strmcmd), ctl.len)); error = EINVAL; @@ -1421,6 +1434,10 @@ svr4_sys_putmsg(struct lwp *l, const str if ((error = copyin(NETBSD32PTR(ctl.buf), &sc, ctl.len)) != 0) goto out; + if (sc.offs < 0) { + error = EINVAL; + goto out; + } switch (st->s_family) { case AF_INET: @@ -1723,8 +1740,16 @@ svr4_sys_getmsg(struct lwp *l, const str if (ctl.len > sizeof(sc)) ctl.len = sizeof(sc); + if (ctl.len < offsetof(struct svr4_strmcmd, pad)) { + error = EINVAL; + goto out; + } if ((error = copyin(NETBSD32PTR(ctl.buf), &sc, ctl.len)) != 0) goto out; + if (sc.offs < 0) { + error = EINVAL; + goto out; + } msg.msg_name = NULL; msg.msg_namelen = 0;