Eliminate use of the global ripsrc which was being used to pass address

information from rip_input() to rip_append().  Instead, pass the source
address for an IP datagram to rip_append() using a stack-allocated
sockaddr_in, similar to udp_input() and udp_append().

Prior to the move to rwlocks for inpcbinfo, this was not a problem, as
use of the global was synchronized using the ripcbinfo mutex, but with
read-locking there is the potential for a race during concurrent
receive.

This problem is not present in the IPv6 raw IP socket code, which
already used a stack variable for the address.

Spotted by:	mav
MFC after:	1 week (before inpcbinfo rwlock changes)
This commit is contained in:
Robert Watson 2008-07-18 10:47:07 +00:00
parent 694382c8eb
commit 3b19fa3597
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=180589

View File

@ -153,10 +153,9 @@ rip_init(void)
EVENTHANDLER_PRI_ANY);
}
static struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
static int
rip_append(struct inpcb *last, struct ip *ip, struct mbuf *n)
rip_append(struct inpcb *last, struct ip *ip, struct mbuf *n,
struct sockaddr_in *ripsrc)
{
int policyfail = 0;
@ -185,7 +184,7 @@ rip_append(struct inpcb *last, struct ip *ip, struct mbuf *n)
ip_savecontrol(last, &opts, ip, n);
SOCKBUF_LOCK(&so->so_rcv);
if (sbappendaddr_locked(&so->so_rcv,
(struct sockaddr *)&ripsrc, n, opts) == 0) {
(struct sockaddr *)ripsrc, n, opts) == 0) {
/* should notify about lost packet */
m_freem(n);
if (opts)
@ -208,10 +207,14 @@ rip_input(struct mbuf *m, int off)
struct ip *ip = mtod(m, struct ip *);
int proto = ip->ip_p;
struct inpcb *inp, *last;
struct sockaddr_in ripsrc;
INP_INFO_RLOCK(&ripcbinfo);
bzero(&ripsrc, sizeof(ripsrc));
ripsrc.sin_len = sizeof(ripsrc);
ripsrc.sin_family = AF_INET;
ripsrc.sin_addr = ip->ip_src;
last = NULL;
INP_INFO_RLOCK(&ripcbinfo);
LIST_FOREACH(inp, &ripcb, inp_list) {
INP_RLOCK(inp);
if (inp->inp_ip_p && inp->inp_ip_p != proto) {
@ -238,14 +241,14 @@ rip_input(struct mbuf *m, int off)
n = m_copy(m, 0, (int)M_COPYALL);
if (n != NULL)
(void) rip_append(last, ip, n);
(void) rip_append(last, ip, n, &ripsrc);
/* XXX count dropped packet */
INP_RUNLOCK(last);
}
last = inp;
}
if (last != NULL) {
if (rip_append(last, ip, m) != 0)
if (rip_append(last, ip, m, &ripsrc) != 0)
ipstat.ips_delivered--;
INP_RUNLOCK(last);
} else {