On 03/31/16 14:07, Alexander Bluhm wrote: > On Wed, Mar 30, 2016 at 10:44:14PM +0200, Vincent Gross wrote: >> This diff moves the "are we binding to a privileged port while not being >> root ?" >> check from in(6)_pcbaddrisavail() to in_pcbbind(). > >> --- sys/netinet/in_pcb.c 26 Mar 2016 21:56:04 -0000 1.198 >> +++ sys/netinet/in_pcb.c 30 Mar 2016 20:33:00 -0000 >> @@ -341,9 +341,14 @@ in_pcbbind(struct inpcb *inp, struct mbu >> } >> } >> >> - if (lport == 0) >> + if (lport == 0) { >> if ((error = in_pcbpickport(&lport, wild, inp, p))) >> return (error); >> + } else { >> + if (ntohs(lport) < IPPORT_RESERVED && >> + (error = suser(p, 0))) >> + return (EACCES); >> + } >> inp->inp_lport = lport; > > At this point inp has already been modified. So when we bail out > with EACCES here, we have a partially successful system call. > > Move the assignments > inp->inp_laddr6 = sin6->sin6_addr; > inp->inp_laddr = sin->sin_addr; > down after the return (EACCES). > > Looks like that return (error) was wrong before.
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 1ff0056..63b3357 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -343,9 +343,22 @@ in_pcbbind(struct inpcb *inp, struct mbuf *nam, struct proc *p) } } - if (lport == 0) + if (lport == 0) { if ((error = in_pcbpickport(&lport, laddr, wild, inp, p))) return (error); + } else { + /* + * Question: Do we wish to continue the Berkeley + * tradition of ports < IPPORT_RESERVED be only for + * root? + * Answer: For now yes, but IMHO, it should be REMOVED! + * OUCH: One other thing, is there no better way of + * finding a process for a socket instead of using + * curproc? (Marked with BSD's {in,}famous XXX ? + */ + if (ntohs(lport) < IPPORT_RESERVED && (error = suser(p, 0))) + return (EACCES); + } if (nam) { switch (sotopf(so)) { #ifdef INET6 @@ -371,7 +384,6 @@ in_pcbaddrisavail(struct inpcb *inp, struct sockaddr_in *sin, int wild, struct inpcbtable *table = inp->inp_table; u_int16_t lport = sin->sin_port; int reuseport = (so->so_options & SO_REUSEPORT); - int error; if (IN_MULTICAST(sin->sin_addr.s_addr)) { /* @@ -411,10 +423,6 @@ in_pcbaddrisavail(struct inpcb *inp, struct sockaddr_in *sin, int wild, if (lport) { struct inpcb *t; - /* GROSS */ - if (ntohs(lport) < IPPORT_RESERVED && - (error = suser(p, 0))) - return (EACCES); if (so->so_euid) { t = in_pcblookup(table, &zeroin_addr, 0, &sin->sin_addr, lport, INPLOOKUP_WILDCARD, diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index 4fde210..c11b936 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -158,7 +158,6 @@ in6_pcbaddrisavail(struct inpcb *inp, struct sockaddr_in6 *sin6, int wild, struct inpcbtable *table = inp->inp_table; u_short lport = sin6->sin6_port; int reuseport = (so->so_options & SO_REUSEPORT); - int error; wild |= INPLOOKUP_IPV6; /* KAME hack: embed scopeid */ @@ -217,17 +216,6 @@ in6_pcbaddrisavail(struct inpcb *inp, struct sockaddr_in6 *sin6, int wild, if (lport) { struct inpcb *t; - /* - * Question: Do we wish to continue the Berkeley - * tradition of ports < IPPORT_RESERVED be only for - * root? - * Answer: For now yes, but IMHO, it should be REMOVED! - * OUCH: One other thing, is there no better way of - * finding a process for a socket instead of using - * curproc? (Marked with BSD's {in,}famous XXX ? - */ - if (ntohs(lport) < IPPORT_RESERVED && (error = suser(p, 0))) - return error; if (so->so_euid) { t = in_pcblookup(table, (struct in_addr *)&zeroin6_addr, 0,