diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 00a592051ad9..984561c899c0 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $NetBSD: in_pcb.c,v 1.134 2009/04/30 18:18:34 elad Exp $ */ +/* $NetBSD: in_pcb.c,v 1.135 2009/04/30 20:26:09 elad Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -91,7 +91,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.134 2009/04/30 18:18:34 elad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.135 2009/04/30 20:26:09 elad Exp $"); #include "opt_inet.h" #include "opt_ipsec.h" @@ -273,6 +273,7 @@ in_pcbsetport(struct sockaddr_in *sin, struct inpcb *inp, kauth_cred_t cred) lport = mymax; if (!in_pcblookup_port(table, sin->sin_addr, htons(lport), 1)) { /* We have a free port, check with the secmodel(s). */ + sin->sin_port = lport; error = kauth_authorize_network(cred, KAUTH_NETWORK_BIND, req, so, sin, NULL); if (error) { diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c index e54693b86f8c..05b727142918 100644 --- a/sys/netinet6/in6_src.c +++ b/sys/netinet6/in6_src.c @@ -65,7 +65,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.46 2009/03/18 16:00:22 cegger Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.47 2009/04/30 20:26:09 elad Exp $"); #include "opt_inet.h" @@ -814,7 +814,7 @@ in6_selecthlim(struct in6pcb *in6p, struct ifnet *ifp) * Find an empty port and set it to the specified PCB. */ int -in6_pcbsetport(struct in6_addr *laddr, struct in6pcb *in6p, struct lwp *l) +in6_pcbsetport(struct sockaddr_in6 *sin6, struct in6pcb *in6p, struct lwp *l) { struct socket *so = in6p->in6p_socket; struct inpcbtable *table = in6p->in6p_table; @@ -823,6 +823,8 @@ in6_pcbsetport(struct in6_addr *laddr, struct in6pcb *in6p, struct lwp *l) u_int16_t lport, *lastport; int wild = 0; void *t; + int error; + enum kauth_network_req req; /* XXX: this is redundant when called from in6_pcbbind */ if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 && @@ -832,19 +834,28 @@ in6_pcbsetport(struct in6_addr *laddr, struct in6pcb *in6p, struct lwp *l) if (in6p->in6p_flags & IN6P_LOWPORT) { #ifndef IPNOPRIVPORTS - if (l == 0 || (kauth_authorize_generic(l->l_cred, - KAUTH_GENERIC_ISSUSER, NULL) != 0)) - return (EACCES); + req = KAUTH_REQ_NETWORK_BIND_PRIVPORT; +#else + req = KAUTH_REQ_NETWORK_BIND_PORT; #endif + minport = ip6_lowportmin; maxport = ip6_lowportmax; lastport = &table->inpt_lastlow; } else { + req = KAUTH_REQ_NETWORK_BIND_PORT; + minport = ip6_anonportmin; maxport = ip6_anonportmax; lastport = &table->inpt_lastport; } + /* XXX-kauth: KAUTH_REQ_NETWORK_BIND_AUTOASSIGN_{,PRIV}PORT */ + error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_BIND, req, so, + sin6, NULL); + if (error) + return (error); + if (minport > maxport) { /* sanity check */ u_int16_t swp; @@ -858,18 +869,28 @@ in6_pcbsetport(struct in6_addr *laddr, struct in6pcb *in6p, struct lwp *l) if (lport < minport || lport > maxport) lport = maxport; #ifdef INET - if (IN6_IS_ADDR_V4MAPPED(laddr)) { + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { t = in_pcblookup_port(table, - *(struct in_addr *)&laddr->s6_addr32[3], + *(struct in_addr *)&sin6->sin6_addr.s6_addr32[3], htons(lport), wild); } else #endif { - t = in6_pcblookup_port(table, laddr, htons(lport), - wild); + t = in6_pcblookup_port(table, &sin6->sin6_addr, + htons(lport), wild); } - if (t == 0) + if (t == 0) { + /* We have a free port. Check with the secmodel. */ + sin6->sin6_port = lport; + error = kauth_authorize_network(l->l_cred, + KAUTH_NETWORK_BIND, req, so, sin6, NULL); + if (error) { + /* Secmodel says no. Keep looking. */ + continue; + } + goto found; + } } return (EAGAIN);