Fix bugs concerning cached route entry in UDP inpcb.
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 26 Mar 2008 14:44:59 +0000 (14:44 +0000)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 26 Mar 2008 14:44:59 +0000 (14:44 +0000)
commit9b37b73b7edc1562017d1fc8f163ffaaba59d5a3
treed170273607aba8a07c0823eb64989f989a110727
parent4fa8e46eca5dd23836e3852f8cdf4fc4596e69aa
Fix bugs concerning cached route entry in UDP inpcb.

For an unconnected and unbound UDP socket, first sending calls in_pcbladdr()
to fix the local port, which may change the target CPU of the next sending.
in_pcbladdr() has a side effect to allocate the route entry cached in inpcb.
If the target CPU after in_pcbladdr() is no longer the current CPU, then
the route entry will be accessed/freed on non-owner CPU during later sending.
Similarly, connect/disconnect a UDP socket may change the target CPU too; the
target CPU may no longer the owner of the cached route entry.

So, for the first sending happens on an unconnected and unbound UDP socket,
the target CPU of next sending is compared with the current CPU.  If they
are different, then cached route entry will be freed, so next time a packet
sent on this socket, a new route entry owned by the correct CPU will be
cached.  Same target CPU check is applied to UDP socket connect/disconnect.

Originally UDP PRU_CONNECT always happens on CPU0, which will cause problem if
following conditions are met:
- Dst of the cached route entry is different from the dst to be connected
- Cached route entry is not allocated on CPU0
This could happen if two datagram are sent on an unbounded and unconnected UDP
socket, then later connectting this UDP socket will cause cached route entry
being freed on different CPU.  To solve this problem, PRU_CONNECT is dispatched
according to existing [lf]{addr,port} pairs.

If in_pcbladdr() fails after altering the cached route entry, the cached route
entry is freed to make sure that freeing this cached route entry happens on
its owner CPU.

Reported-by: y0netan1@
Tested-by: y0netan1@
sys/netinet/in_pcb.c
sys/netinet/ip_demux.c
sys/netinet/udp_usrreq.c