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.
)
This commit is contained in:
lukem 1999-03-23 10:45:37 +00:00
parent 4ca3cf8411
commit 8a931fcdd8
4 changed files with 23 additions and 5 deletions

View File

@ -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) {

View File

@ -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,

View File

@ -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);

View File

@ -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 */
};
/*