summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorMatthew Dempsky <matthew@cvs.openbsd.org>2012-04-23 15:36:08 +0000
committerMatthew Dempsky <matthew@cvs.openbsd.org>2012-04-23 15:36:08 +0000
commit6b489094240ed83c3bee6b2b018efd78f506a38d (patch)
tree78a0030d92df3bb72fa181c5781efd57c505ca12 /sys/kern
parent26a31b20226a49e9bbdd8fc56a225187e51f26d3 (diff)
Don't leak mbufs when bind() on a PF_UNIX socket fails.
ok deraadt, miod, guenther
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/uipc_usrreq.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 94c38e4a098..8e6fe6447b7 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_usrreq.c,v 1.64 2012/04/14 09:42:32 claudio Exp $ */
+/* $OpenBSD: uipc_usrreq.c,v 1.65 2012/04/23 15:36:07 matthew Exp $ */
/* $NetBSD: uipc_usrreq.c,v 1.18 1996/02/09 19:00:50 christos Exp $ */
/*
@@ -398,6 +398,7 @@ int
unp_bind(struct unpcb *unp, struct mbuf *nam, struct proc *p)
{
struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *);
+ struct mbuf *nam2;
struct vnode *vp;
struct vattr vattr;
int error, namelen;
@@ -416,19 +417,21 @@ unp_bind(struct unpcb *unp, struct mbuf *nam, struct proc *p)
* will NUL terminate it
*/
- 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,
+ nam2 = m_getclr(M_WAITOK, MT_SONAME);
+ nam2->m_len = soun->sun_len;
+ memcpy(mtod(nam2, caddr_t), soun,
offsetof(struct sockaddr_un, sun_path));
- strncpy(mtod(unp->unp_addr, caddr_t) +
+ strncpy(mtod(nam2, caddr_t) +
offsetof(struct sockaddr_un, sun_path), soun->sun_path, namelen);
- soun = mtod(unp->unp_addr, struct sockaddr_un *);
+ soun = mtod(nam2, 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)
+ if ((error = namei(&nd)) != 0) {
+ m_freem(nam2);
return (error);
+ }
vp = nd.ni_vp;
if (vp != NULL) {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
@@ -437,14 +440,18 @@ unp_bind(struct unpcb *unp, struct mbuf *nam, struct proc *p)
else
vput(nd.ni_dvp);
vrele(vp);
+ m_freem(nam2);
return (EADDRINUSE);
}
VATTR_NULL(&vattr);
vattr.va_type = VSOCK;
vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
- if (error)
+ if (error) {
+ m_freem(nam2);
return (error);
+ }
+ unp->unp_addr = nam2;
vp = nd.ni_vp;
vp->v_socket = unp->unp_socket;
unp->unp_vnode = vp;