Skip to content

Commit

Permalink
udp: fix sending of IPv4-mapped addresses
Browse files Browse the repository at this point in the history
The inp_vflags field must be adjusted during the call of
in_pcbbind_setup(). This is consistent with the other places in the
code, but not elegant at all.

PR:			274009
Reported by:		syzbot+81ccc423a2737ed031ac@syzkaller.appspotmail.com
Reported by:		syzbot+c8e3dac881bba85bc029@syzkaller.appspotmail.com
Reviewed by:		markj, rrs, rscheff
MFC after:		3 days
Sponsored by:		Netflix, Inc.
Differential Revision:	https://reviews.freebsd.org/D42031
  • Loading branch information
tuexen committed Oct 7, 2023
1 parent f7a2eea commit abca3ae
Showing 1 changed file with 17 additions and 2 deletions.
19 changes: 17 additions & 2 deletions sys/netinet/udp_usrreq.c
Expand Up @@ -1050,7 +1050,7 @@ udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
int cscov_partial = 0;
int ipflags = 0;
u_short fport, lport;
u_char tos;
u_char tos, vflagsav;
uint8_t pr;
uint16_t cscov = 0;
uint32_t flowid = 0;
Expand Down Expand Up @@ -1092,7 +1092,8 @@ udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
* pcb hash.
*/
if (sin == NULL ||
(inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0))
(inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0) ||
(flags & PRUS_IPV6) != 0)
INP_WLOCK(inp);
else
INP_RLOCK(inp);
Expand Down Expand Up @@ -1203,10 +1204,17 @@ udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
error = EINVAL;
goto release;
}
if ((flags & PRUS_IPV6) != 0) {
vflagsav = inp->inp_vflag;
inp->inp_vflag |= INP_IPV4;
inp->inp_vflag &= ~INP_IPV6;
}
INP_HASH_WLOCK(pcbinfo);
error = in_pcbbind_setup(inp, &src, &laddr.s_addr, &lport,
td->td_ucred);
INP_HASH_WUNLOCK(pcbinfo);
if ((flags & PRUS_IPV6) != 0)
inp->inp_vflag = vflagsav;
if (error)
goto release;
}
Expand Down Expand Up @@ -1249,9 +1257,16 @@ udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
inp->inp_lport == 0 ||
sin->sin_addr.s_addr == INADDR_ANY ||
sin->sin_addr.s_addr == INADDR_BROADCAST) {
if ((flags & PRUS_IPV6) != 0) {
vflagsav = inp->inp_vflag;
inp->inp_vflag |= INP_IPV4;
inp->inp_vflag &= ~INP_IPV6;
}
INP_HASH_WLOCK(pcbinfo);
error = in_pcbconnect_setup(inp, sin, &laddr.s_addr,
&lport, &faddr.s_addr, &fport, td->td_ucred);
if ((flags & PRUS_IPV6) != 0)
inp->inp_vflag = vflagsav;
if (error) {
INP_HASH_WUNLOCK(pcbinfo);
goto release;
Expand Down

0 comments on commit abca3ae

Please sign in to comment.