diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2011-07-05 23:06:44 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2011-07-05 23:06:44 +0000 |
commit | f1303edfde79aacbe075553a2fa8999de7266cbb (patch) | |
tree | 2c09eb5543a48578d1c7cc0f08af31fc32c6ccbf /sys/kern | |
parent | e38ae7fb683c329831aba5bb5c866da618bcc03a (diff) |
Enforce that the path to the unix socket fits into struct sockaddr_un
and that it is nul terminated. This means the longest path is now 103
char longs. With and OK guenther@
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/uipc_usrreq.c | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 52861e3d610..53acf003c10 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_usrreq.c,v 1.52 2011/06/28 10:15:38 thib Exp $ */ +/* $OpenBSD: uipc_usrreq.c,v 1.53 2011/07/05 23:06:43 claudio Exp $ */ /* $NetBSD: uipc_usrreq.c,v 1.18 1996/02/09 19:00:50 christos Exp $ */ /* @@ -389,16 +389,26 @@ unp_bind(struct unpcb *unp, struct mbuf *nam, struct proc *p) struct vattr vattr; int error, namelen; struct nameidata nd; - char buf[MLEN]; if (unp->unp_vnode != NULL) return (EINVAL); namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path); - if (namelen <= 0 || namelen >= MLEN) + if (namelen <= 0 || namelen > sizeof(soun->sun_path)) return EINVAL; - strncpy(buf, soun->sun_path, namelen); - buf[namelen] = 0; /* null-terminate the string */ - NDINIT(&nd, CREATE, NOFOLLOW | LOCKPARENT, UIO_SYSSPACE, buf, p); + if (namelen == sizeof(soun->sun_path) && + soun->sun_path[namelen - 1] != '\0') + return EINVAL; + + unp->unp_addr = m_getclr(M_WAITOK, MT_SONAME); + unp->unp_addr->m_len = soun->sun_len; + memcpy(mtod(unp->unp_addr, caddr_t *), soun, + offsetof(struct sockaddr_un, sun_path)); + strncpy(mtod(unp->unp_addr, caddr_t) + + offsetof(struct sockaddr_un, sun_path), soun->sun_path, namelen); + + soun = mtod(unp->unp_addr, struct sockaddr_un *); + NDINIT(&nd, CREATE, NOFOLLOW | LOCKPARENT, UIO_SYSSPACE, + soun->sun_path, p); /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */ if ((error = namei(&nd)) != 0) return (error); @@ -421,7 +431,6 @@ unp_bind(struct unpcb *unp, struct mbuf *nam, struct proc *p) vp = nd.ni_vp; vp->v_socket = unp->unp_socket; unp->unp_vnode = vp; - unp->unp_addr = m_copy(nam, 0, (int)M_COPYALL); unp->unp_connid.uid = p->p_ucred->cr_uid; unp->unp_connid.gid = p->p_ucred->cr_gid; unp->unp_connid.pid = p->p_p->ps_mainproc->p_pid; @@ -440,12 +449,13 @@ unp_connect(struct socket *so, struct mbuf *nam, struct proc *p) int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, soun->sun_path, p); - if (nam->m_data + nam->m_len == &nam->m_dat[MLEN]) { /* XXX */ - if (*(mtod(nam, caddr_t) + nam->m_len - 1) != 0) + if (nam->m_len >= sizeof(struct sockaddr_un)) { + if (nam->m_len > sizeof(struct sockaddr_un) || + *(mtod(nam, caddr_t) + nam->m_len - 1) != 0) return (EMSGSIZE); } else *(mtod(nam, caddr_t) + nam->m_len) = 0; + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, soun->sun_path, p); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; |