mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
Fix some security bugs in the SVR4 emulator:
- Return NULL instead of returning memory outside of the stackgap in stackgap_alloc() (FreeBSD-SA-00:42.linux) - Check for stackgap_alloc() returning NULL in svr4_emul_find(), and clean_pipe(). - Avoid integer overflow on large nfds argument in svr4_sys_poll() - Reject negative nbytes argument in svr4_sys_getdents() - Don't copy out past the end of the struct componentname pathname buffer in svr4_sys_resolvepath() - Reject out-of-range signal numbers in svr4_sys_sigaction(), svr4_sys_signal(), and svr4_sys_kill(). - Don't malloc() user-specified lengths in show_ioc() and show_strbuf(), place arbitrary limits instead. - Range-check lengths in si_listen(), ti_getinfo(), ti_bind(), svr4_do_putmsg(), svr4_do_getmsg(), svr4_stream_ti_ioctl(). Some fixes obtain from OpenBSD.
This commit is contained in:
parent
fc9cfabba9
commit
78b73f3e05
6 changed files with 78 additions and 20 deletions
|
|
@ -40,6 +40,8 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/poll.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/resourcevar.h>
|
||||
|
||||
#include <sys/sysproto.h>
|
||||
|
||||
|
|
@ -64,6 +66,11 @@ svr4_sys_poll(td, uap)
|
|||
int idx = 0, cerr;
|
||||
u_long siz;
|
||||
|
||||
mtx_assert(&Giant, MA_OWNED);
|
||||
if (uap->nfds > td->td_proc->p_rlimit[RLIMIT_NOFILE].rlim_cur &&
|
||||
uap->nfds > FD_SETSIZE)
|
||||
return (EINVAL);
|
||||
|
||||
pa.fds = uap->fds;
|
||||
pa.nfds = uap->nfds;
|
||||
pa.timeout = uap->timeout;
|
||||
|
|
|
|||
|
|
@ -444,6 +444,9 @@ svr4_sys_getdents(td, uap)
|
|||
u_long *cookiebuf = NULL, *cookie;
|
||||
int ncookies = 0, *retval = td->td_retval;
|
||||
|
||||
if (uap->nbytes < 0)
|
||||
return (EINVAL);
|
||||
|
||||
if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
|
||||
return (error);
|
||||
|
||||
|
|
@ -1734,6 +1737,7 @@ svr4_sys_resolvepath(td, uap)
|
|||
{
|
||||
struct nameidata nd;
|
||||
int error, *retval = td->td_retval;
|
||||
unsigned int ncopy;
|
||||
|
||||
NDINIT(&nd, LOOKUP, NOFOLLOW | SAVENAME, UIO_USERSPACE,
|
||||
uap->path, td);
|
||||
|
|
@ -1741,12 +1745,11 @@ svr4_sys_resolvepath(td, uap)
|
|||
if ((error = namei(&nd)) != 0)
|
||||
return error;
|
||||
|
||||
if ((error = copyout(nd.ni_cnd.cn_pnbuf, uap->buf,
|
||||
uap->bufsiz)) != 0)
|
||||
ncopy = min(uap->bufsiz, strlen(nd.ni_cnd.cn_pnbuf) + 1);
|
||||
if ((error = copyout(nd.ni_cnd.cn_pnbuf, uap->buf, ncopy)) != 0)
|
||||
goto bad;
|
||||
|
||||
*retval = strlen(nd.ni_cnd.cn_pnbuf) < uap->bufsiz ?
|
||||
strlen(nd.ni_cnd.cn_pnbuf) + 1 : uap->bufsiz;
|
||||
*retval = ncopy;
|
||||
bad:
|
||||
NDFREE(&nd, NDF_ONLY_PNBUF);
|
||||
vput(nd.ni_vp);
|
||||
|
|
|
|||
|
|
@ -269,6 +269,9 @@ svr4_sys_sigaction(td, uap)
|
|||
struct sigaction *nbsap;
|
||||
int error;
|
||||
|
||||
if (uap->signum < 0 || uap->signum >= SVR4_NSIG)
|
||||
return (EINVAL);
|
||||
|
||||
DPRINTF(("@@@ svr4_sys_sigaction(%d, %d, %d)\n", td->td_proc->p_pid,
|
||||
uap->signum,
|
||||
SVR4_SVR42BSD_SIG(uap->signum)));
|
||||
|
|
@ -337,9 +340,14 @@ svr4_sys_signal(td, uap)
|
|||
p = td->td_proc;
|
||||
DPRINTF(("@@@ svr4_sys_signal(%d)\n", p->p_pid));
|
||||
|
||||
signum = SVR4_SVR42BSD_SIG(SVR4_SIGNO(uap->signum));
|
||||
if (signum <= 0 || signum > SVR4_NSIG)
|
||||
signum = SVR4_SIGNO(uap->signum);
|
||||
if (signum < 0 || signum >= SVR4_NSIG) {
|
||||
if (SVR4_SIGCALL(uap->signum) == SVR4_SIGNAL_MASK ||
|
||||
SVR4_SIGCALL(uap->signum) == SVR4_SIGDEFER_MASK)
|
||||
td->td_retval[0] = (int)SVR4_SIG_ERR;
|
||||
return (EINVAL);
|
||||
}
|
||||
signum = SVR4_SVR42BSD_SIG(signum);
|
||||
|
||||
switch (SVR4_SIGCALL(uap->signum)) {
|
||||
case SVR4_SIGDEFER_MASK:
|
||||
|
|
@ -509,6 +517,8 @@ svr4_sys_kill(td, uap)
|
|||
{
|
||||
struct kill_args ka;
|
||||
|
||||
if (uap->signum < 0 || uap->signum >= SVR4_NSIG)
|
||||
return (EINVAL);
|
||||
ka.pid = uap->pid;
|
||||
ka.signum = SVR4_SVR42BSD_SIG(uap->signum);
|
||||
return kill(td, &ka);
|
||||
|
|
|
|||
|
|
@ -406,22 +406,32 @@ show_ioc(str, ioc)
|
|||
const char *str;
|
||||
struct svr4_strioctl *ioc;
|
||||
{
|
||||
u_char *ptr = (u_char *) malloc(ioc->len, M_TEMP, M_WAITOK);
|
||||
u_char *ptr = NULL;
|
||||
int len;
|
||||
int error;
|
||||
|
||||
len = ioc->len;
|
||||
if (len > 1024)
|
||||
len = 1024;
|
||||
|
||||
if (len > 0) {
|
||||
ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
|
||||
if ((error = copyin(ioc->buf, ptr, len)) != 0) {
|
||||
free((char *) ptr, M_TEMP);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ",
|
||||
str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf);
|
||||
|
||||
if ((error = copyin(ioc->buf, ptr, ioc->len)) != 0) {
|
||||
free((char *) ptr, M_TEMP);
|
||||
return error;
|
||||
}
|
||||
|
||||
bufprint(ptr, ioc->len);
|
||||
if (ptr != NULL)
|
||||
bufprint(ptr, len);
|
||||
|
||||
uprintf("}\n");
|
||||
|
||||
free((char *) ptr, M_TEMP);
|
||||
if (ptr != NULL)
|
||||
free((char *) ptr, M_TEMP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -435,6 +445,9 @@ show_strbuf(str)
|
|||
int maxlen = str->maxlen;
|
||||
int len = str->len;
|
||||
|
||||
if (maxlen > 8192)
|
||||
maxlen = 8192;
|
||||
|
||||
if (maxlen < 0)
|
||||
maxlen = 0;
|
||||
|
||||
|
|
@ -521,7 +534,8 @@ clean_pipe(td, path)
|
|||
size_t l = strlen(path) + 1;
|
||||
void *tpath;
|
||||
|
||||
tpath = stackgap_alloc(&sg, l);
|
||||
if ((tpath = stackgap_alloc(&sg, l)) == NULL)
|
||||
return ENAMETOOLONG;
|
||||
la.ub = stackgap_alloc(&sg, sizeof(struct stat));
|
||||
|
||||
if ((error = copyout(path, tpath, l)) != 0)
|
||||
|
|
@ -760,6 +774,9 @@ si_listen(fp, fd, ioc, td)
|
|||
if (st == NULL)
|
||||
return EINVAL;
|
||||
|
||||
if (ioc->len < 0 || ioc->len > sizeof(lst))
|
||||
return EINVAL;
|
||||
|
||||
if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0)
|
||||
return error;
|
||||
|
||||
|
|
@ -961,6 +978,9 @@ ti_getinfo(fp, fd, ioc, td)
|
|||
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
if (ioc->len < 0 || ioc->len > sizeof(info))
|
||||
return EINVAL;
|
||||
|
||||
if ((error = copyin(ioc->buf, &info, ioc->len)) != 0)
|
||||
return error;
|
||||
|
||||
|
|
@ -1009,6 +1029,9 @@ ti_bind(fp, fd, ioc, td)
|
|||
return EINVAL;
|
||||
}
|
||||
|
||||
if (ioc->len < 0 || ioc->len > sizeof(bnd))
|
||||
return EINVAL;
|
||||
|
||||
if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0)
|
||||
return error;
|
||||
|
||||
|
|
@ -1137,7 +1160,7 @@ svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
|
|||
struct sockaddr_in sain;
|
||||
struct sockaddr_un saun;
|
||||
struct svr4_strmcmd sc;
|
||||
int sasize;
|
||||
int sasize, oldsasize;
|
||||
caddr_t sg;
|
||||
int *lenp;
|
||||
|
||||
|
|
@ -1225,11 +1248,16 @@ svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
|
|||
return error;
|
||||
}
|
||||
|
||||
oldsasize = sasize;
|
||||
|
||||
if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) {
|
||||
DPRINTF(("ti_ioctl: error copying in socket size\n"));
|
||||
return error;
|
||||
}
|
||||
|
||||
if (sasize < 0 || sasize > oldsasize)
|
||||
return EINVAL;
|
||||
|
||||
switch (st->s_family) {
|
||||
case AF_INET:
|
||||
sockaddr_to_netaddr_in(&sc, &sain);
|
||||
|
|
@ -1794,7 +1822,7 @@ svr4_do_putmsg(td, uap, fp)
|
|||
return EINVAL;
|
||||
}
|
||||
|
||||
if (ctl.len > sizeof(sc)) {
|
||||
if (ctl.len < 0 || ctl.len > sizeof(sc)) {
|
||||
DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
|
||||
sizeof(struct svr4_strmcmd)));
|
||||
return EINVAL;
|
||||
|
|
@ -1962,6 +1990,8 @@ svr4_do_getmsg(td, uap, fp)
|
|||
if (uap->ctl != NULL) {
|
||||
if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0)
|
||||
return error;
|
||||
if (ctl.len < 0)
|
||||
return EINVAL;
|
||||
}
|
||||
else {
|
||||
ctl.len = -1;
|
||||
|
|
@ -2147,6 +2177,9 @@ svr4_do_getmsg(td, uap, fp)
|
|||
if (ctl.maxlen > 36 && ctl.len < 36)
|
||||
ctl.len = 36;
|
||||
|
||||
if (ctl.len > sizeof(sc))
|
||||
ctl.len = sizeof(sc);
|
||||
|
||||
if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
|
||||
return error;
|
||||
|
||||
|
|
|
|||
|
|
@ -364,8 +364,10 @@ svr4_emul_find(td, sgp, prefix, path, pbuf, cflag)
|
|||
*pbuf = buf;
|
||||
else {
|
||||
sz = &ptr[len] - buf;
|
||||
*pbuf = stackgap_alloc(sgp, sz + 1);
|
||||
error = copyout(buf, *pbuf, sz);
|
||||
if ((*pbuf = stackgap_alloc(sgp, sz + 1)) != NULL)
|
||||
error = copyout(buf, *pbuf, sz);
|
||||
else
|
||||
error = ENAMETOOLONG;
|
||||
free(buf, M_TEMP);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,10 @@ stackgap_alloc(sgp, sz)
|
|||
size_t sz;
|
||||
{
|
||||
void *p = (void *) *sgp;
|
||||
*sgp += ALIGN(sz);
|
||||
sz = ALIGN(sz);
|
||||
if (*sgp + sz > (caddr_t)(PS_STRINGS - szsigcode))
|
||||
return NULL;
|
||||
*sgp += sz;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue