From 8a931fcdd83df19cc0f68df8e0d9583739a015aa Mon Sep 17 00:00:00 2001 From: lukem Date: Tue, 23 Mar 1999 10:45:37 +0000 Subject: [PATCH] Ensure that you can only bind a more specific address when it is done by the same uid or by root. This code is from FreeBSD. (Whilst it was originally obtained from OpenBSD, FreeBSD fixed it to work with multicast. To quote the commit message: - Don't bother checking for conflicting sockets if we're binding to a multicast address. - Don't return an error if we're binding to INADDR_ANY, the conflicting socket is bound to INADDR_ANY, and the conflicting socket has SO_REUSEPORT set. ) --- sys/kern/uipc_socket.c | 4 +++- sys/kern/uipc_socket2.c | 3 ++- sys/netinet/in_pcb.c | 17 ++++++++++++++++- sys/sys/socketvar.h | 4 ++-- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index b90d09318775..618c39a45dbe 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $NetBSD: uipc_socket.c,v 1.43 1999/01/21 22:09:10 mycroft Exp $ */ +/* $NetBSD: uipc_socket.c,v 1.44 1999/03/23 10:45:37 lukem Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 @@ -100,6 +100,8 @@ socreate(dom, aso, type, proto) so->so_proto = prp; so->so_send = sosend; so->so_receive = soreceive; + if (p != 0) + so->so_uid = p->p_ucred->cr_uid; error = (*prp->pr_usrreq)(so, PRU_ATTACH, (struct mbuf *)0, (struct mbuf *)(long)proto, (struct mbuf *)0, p); if (error) { diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index c80aecb88672..39de8c66fc59 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -1,4 +1,4 @@ -/* $NetBSD: uipc_socket2.c,v 1.27 1999/01/20 09:15:41 mycroft Exp $ */ +/* $NetBSD: uipc_socket2.c,v 1.28 1999/03/23 10:45:37 lukem Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 @@ -174,6 +174,7 @@ sonewconn1(head, connstatus) so->so_pgid = head->so_pgid; so->so_send = head->so_send; so->so_receive = head->so_receive; + so->so_uid = head->so_uid; (void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat); soqinsque(head, so, soqueue); if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 6d128b74b673..7f6e0d97978b 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $NetBSD: in_pcb.c,v 1.57 1998/12/19 02:46:12 thorpej Exp $ */ +/* $NetBSD: in_pcb.c,v 1.58 1999/03/23 10:45:37 lukem Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -219,6 +219,21 @@ in_pcbbind(v, nam, p) (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))) return (EACCES); #endif + if (so->so_uid && !IN_MULTICAST(sin->sin_addr.s_addr)) { + t = in_pcblookup_port(table, sin->sin_addr, lport, 1); + /* + * XXX: investigate ramifications of loosening this + * restriction so that as long as both ports have + * SO_REUSEPORT allow the bind + */ + if (t && + (!in_nullhost(sin->sin_addr) || + !in_nullhost(t->inp_laddr) || + (t->inp_socket->so_options & SO_REUSEPORT) == 0) + && (so->so_uid != t->inp_socket->so_uid)) { + return (EADDRINUSE); + } + } t = in_pcblookup_port(table, sin->sin_addr, lport, wild); if (t && (reuseport & t->inp_socket->so_options) == 0) return (EADDRINUSE); diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 1da54d9d52cb..019a9014af47 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: socketvar.h,v 1.36 1999/02/10 14:37:25 tron Exp $ */ +/* $NetBSD: socketvar.h,v 1.37 1999/03/23 10:45:37 lukem Exp $ */ /*- * Copyright (c) 1982, 1986, 1990, 1993 @@ -121,7 +121,7 @@ struct socket { int (*so_receive) __P((struct socket *so, struct mbuf **paddr, struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp)); - + uid_t so_uid; /* who opened the socket */ }; /*