summaryrefslogtreecommitdiff
path: root/sys/netinet/tcp_subr.c
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2022-08-08 12:06:32 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2022-08-08 12:06:32 +0000
commit2c56b01a18fc4cacc0b9509a2657a57be470d69b (patch)
treead5503da9e75dfee7b34906402bcfbcfa3249fad /sys/netinet/tcp_subr.c
parent8d515cf4247f32f44f2291ad4eb92432f69ee447 (diff)
To make protocol input functions MP safe, internet PCB need protection.
Use their reference counter in more places. The in_pcb lookup functions hold the PCBs in hash tables protected by table->inpt_mtx mutex. Whenever a result is returned, increment the ref count before releasing the mutex. Then the inp can be used as long as neccessary. Unref it at the end of all functions that call in_pcb lookup. As a shortcut, pf may also hold a reference to the PCB. When pf_inp_lookup() returns it, it also incements the ref count and the caller can handle it like the inp from table lookup. OK sashan@
Diffstat (limited to 'sys/netinet/tcp_subr.c')
-rw-r--r--sys/netinet/tcp_subr.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index bd0671b319a..b7d5eb22dec 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_subr.c,v 1.184 2022/03/02 12:53:15 bluhm Exp $ */
+/* $OpenBSD: tcp_subr.c,v 1.185 2022/08/08 12:06:30 bluhm Exp $ */
/* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */
/*
@@ -671,7 +671,9 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *d)
* corresponding routing entry, or
* - ignore the MTU change notification.
*/
- icmp6_mtudisc_update((struct ip6ctlparam *)d, inp != NULL);
+ icmp6_mtudisc_update((struct ip6ctlparam *)d,
+ inp != NULL);
+ in_pcbunref(inp);
return;
}
if (inp) {
@@ -686,6 +688,7 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *d)
inet6ctlerrmap[cmd] == EHOSTDOWN)
syn_cache_unreach((struct sockaddr *)sa6_src,
sa, &th, rdomain);
+ in_pcbunref(inp);
} else {
in6_pcbnotify(&tcbtable, sa6, 0,
sa6_src, 0, rdomain, cmd, NULL, notify);
@@ -746,8 +749,10 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v)
* ever sent, drop the message.
*/
mtu = (u_int)ntohs(icp->icmp_nextmtu);
- if (mtu >= tp->t_pmtud_mtu_sent)
+ if (mtu >= tp->t_pmtud_mtu_sent) {
+ in_pcbunref(inp);
return;
+ }
if (mtu >= tcp_hdrsz(tp) + tp->t_pmtud_mss_acked) {
/*
* Calculate new MTU, and create corresponding
@@ -764,20 +769,25 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v)
* refers to an older TCP segment
*/
if (tp->t_flags & TF_PMTUD_PEND) {
- if (SEQ_LT(tp->t_pmtud_th_seq, seq))
+ if (SEQ_LT(tp->t_pmtud_th_seq, seq)) {
+ in_pcbunref(inp);
return;
+ }
} else
tp->t_flags |= TF_PMTUD_PEND;
tp->t_pmtud_th_seq = seq;
tp->t_pmtud_nextmtu = icp->icmp_nextmtu;
tp->t_pmtud_ip_len = icp->icmp_ip.ip_len;
tp->t_pmtud_ip_hl = icp->icmp_ip.ip_hl;
+ in_pcbunref(inp);
return;
}
} else {
/* ignore if we don't have a matching connection */
+ in_pcbunref(inp);
return;
}
+ in_pcbunref(inp);
notify = tcp_mtudisc, ip = 0;
} else if (cmd == PRC_MTUINC)
notify = tcp_mtudisc_increase, ip = 0;
@@ -810,6 +820,7 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v)
sin.sin_addr = ip->ip_src;
syn_cache_unreach(sintosa(&sin), sa, th, rdomain);
}
+ in_pcbunref(inp);
} else
in_pcbnotifyall(&tcbtable, sa, rdomain, errno, notify);
}