aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet/tcp_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/tcp_input.c')
-rw-r--r--sys/netinet/tcp_input.c127
1 files changed, 94 insertions, 33 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 3fda6e903738..b64a71837ab4 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -202,6 +202,11 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, insecure_rst, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_insecure_rst), 0,
"Follow RFC793 instead of RFC5961 criteria for accepting RST packets");
+VNET_DEFINE(int, tcp_insecure_ack) = 0;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, insecure_ack, CTLFLAG_VNET | CTLFLAG_RW,
+ &VNET_NAME(tcp_insecure_ack), 0,
+ "Follow RFC793 criteria for validating SEG.ACK");
+
VNET_DEFINE(int, tcp_recvspace) = 1024*64;
#define V_tcp_recvspace VNET(tcp_recvspace)
SYSCTL_INT(_net_inet_tcp, TCPCTL_RECVSPACE, recvspace, CTLFLAG_VNET | CTLFLAG_RW,
@@ -833,6 +838,7 @@ tcp_input_with_port(struct mbuf **mp, int *offp, int proto, uint16_t port)
((thflags & (TH_ACK|TH_SYN)) == TH_SYN ?
INPLOOKUP_RLOCKPCB : INPLOOKUP_WLOCKPCB);
findpcb:
+ tp = NULL;
#ifdef INET6
if (isipv6 && fwd_tag != NULL) {
struct sockaddr_in6 *next_hop6;
@@ -915,23 +921,6 @@ findpcb:
log(LOG_INFO, "%s; %s: Connection attempt "
"to closed port\n", s, __func__);
}
- /*
- * When blackholing do not respond with a RST but
- * completely ignore the segment and drop it.
- */
- if (((V_blackhole == 1 && (thflags & TH_SYN)) ||
- V_blackhole == 2) && (V_blackhole_local || (
-#ifdef INET6
- isipv6 ? !in6_localaddr(&ip6->ip6_src) :
-#endif
-#ifdef INET
- !in_localip(ip->ip_src)
-#else
- true
-#endif
- )))
- goto dropunlock;
-
rstreason = BANDLIM_RST_CLOSEDPORT;
goto dropwithreset;
}
@@ -1410,15 +1399,27 @@ tfo_socket_result:
return (IPPROTO_DONE);
dropwithreset:
+ /*
+ * When blackholing do not respond with a RST but
+ * completely ignore the segment and drop it.
+ */
+ if (((rstreason == BANDLIM_RST_OPENPORT && V_blackhole == 3) ||
+ (rstreason == BANDLIM_RST_CLOSEDPORT &&
+ ((V_blackhole == 1 && (thflags & TH_SYN)) || V_blackhole > 1))) &&
+ (V_blackhole_local || (
+#ifdef INET6
+ isipv6 ? !in6_localaddr(&ip6->ip6_src) :
+#endif
+#ifdef INET
+ !in_localip(ip->ip_src)
+#else
+ true
+#endif
+ )))
+ goto dropunlock;
TCP_PROBE5(receive, NULL, tp, m, tp, th);
-
- if (inp != NULL) {
- tcp_dropwithreset(m, th, tp, tlen, rstreason);
- INP_UNLOCK(inp);
- } else
- tcp_dropwithreset(m, th, NULL, tlen, rstreason);
+ tcp_dropwithreset(m, th, tp, tlen, rstreason);
m = NULL; /* mbuf chain got consumed. */
- goto drop;
dropunlock:
if (m != NULL)
@@ -1615,7 +1616,14 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
tcp_dooptions(&to, (u_char *)(th + 1),
(th->th_off << 2) - sizeof(struct tcphdr),
(thflags & TH_SYN) ? TO_SYN : 0);
-
+ if (tp->t_flags2 & TF2_PROC_SACK_PROHIBIT) {
+ /*
+ * We don't look at sack's from the
+ * peer because the MSS is too small which
+ * can subject us to an attack.
+ */
+ to.to_flags &= ~TOF_SACK;
+ }
#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
if ((tp->t_flags & TF_SIGNATURE) != 0 &&
(to.to_flags & TOF_SIGNATURE) == 0) {
@@ -2200,10 +2208,7 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
}
} else {
TCPSTAT_INC(tcps_badrst);
- /* Send challenge ACK. */
- tcp_respond(tp, mtod(m, void *), th, m,
- tp->rcv_nxt, tp->snd_nxt, TH_ACK);
- tp->last_ack_sent = tp->rcv_nxt;
+ tcp_send_challenge_ack(tp, th, m);
m = NULL;
}
}
@@ -2225,10 +2230,7 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
rstreason = BANDLIM_UNLIMITED;
} else {
tcp_ecn_input_syn_sent(tp, thflags, iptos);
- /* Send challenge ACK. */
- tcp_respond(tp, mtod(m, void *), th, m, tp->rcv_nxt,
- tp->snd_nxt, TH_ACK);
- tp->last_ack_sent = tp->rcv_nxt;
+ tcp_send_challenge_ack(tp, th, m);
m = NULL;
}
goto drop;
@@ -2435,6 +2437,42 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
/*
* Ack processing.
*/
+ if (SEQ_GEQ(tp->snd_una, tp->iss + (TCP_MAXWIN << tp->snd_scale))) {
+ /* Checking SEG.ACK against ISS is definitely redundant. */
+ tp->t_flags2 |= TF2_NO_ISS_CHECK;
+ }
+ if (!V_tcp_insecure_ack) {
+ tcp_seq seq_min;
+ bool ghost_ack_check;
+
+ if (tp->t_flags2 & TF2_NO_ISS_CHECK) {
+ /* Check for too old ACKs (RFC 5961, Section 5.2). */
+ seq_min = tp->snd_una - tp->max_sndwnd;
+ ghost_ack_check = false;
+ } else {
+ if (SEQ_GT(tp->iss + 1, tp->snd_una - tp->max_sndwnd)) {
+ /* Checking for ghost ACKs is stricter. */
+ seq_min = tp->iss + 1;
+ ghost_ack_check = true;
+ } else {
+ /*
+ * Checking for too old ACKs (RFC 5961,
+ * Section 5.2) is stricter.
+ */
+ seq_min = tp->snd_una - tp->max_sndwnd;
+ ghost_ack_check = false;
+ }
+ }
+ if (SEQ_LT(th->th_ack, seq_min)) {
+ if (ghost_ack_check)
+ TCPSTAT_INC(tcps_rcvghostack);
+ else
+ TCPSTAT_INC(tcps_rcvacktooold);
+ tcp_send_challenge_ack(tp, th, m);
+ m = NULL;
+ goto drop;
+ }
+ }
switch (tp->t_state) {
/*
* In SYN_RECEIVED state, the ack ACKs our SYN, so enter
@@ -3883,6 +3921,17 @@ tcp_mss_update(struct tcpcb *tp, int offer, int mtuoffer,
mss = max(mss, 64);
tp->t_maxseg = mss;
+ if (tp->t_maxseg < V_tcp_mssdflt) {
+ /*
+ * The MSS is so small we should not process incoming
+ * SACK's since we are subject to attack in such a
+ * case.
+ */
+ tp->t_flags2 |= TF2_PROC_SACK_PROHIBIT;
+ } else {
+ tp->t_flags2 &= ~TF2_PROC_SACK_PROHIBIT;
+ }
+
}
void
@@ -3934,6 +3983,16 @@ tcp_mss(struct tcpcb *tp, int offer)
* XXXGL: shouldn't we reserve space for IP/IPv6 options?
*/
tp->t_maxseg = max(mss, 64);
+ if (tp->t_maxseg < V_tcp_mssdflt) {
+ /*
+ * The MSS is so small we should not process incoming
+ * SACK's since we are subject to attack in such a
+ * case.
+ */
+ tp->t_flags2 |= TF2_PROC_SACK_PROHIBIT;
+ } else {
+ tp->t_flags2 &= ~TF2_PROC_SACK_PROHIBIT;
+ }
SOCKBUF_LOCK(&so->so_rcv);
if ((so->so_rcv.sb_hiwat == V_tcp_recvspace) && metrics.rmx_recvpipe)
@@ -3955,6 +4014,8 @@ tcp_mss(struct tcpcb *tp, int offer)
tp->t_tsomax = cap.tsomax;
tp->t_tsomaxsegcount = cap.tsomaxsegcount;
tp->t_tsomaxsegsize = cap.tsomaxsegsize;
+ if (cap.ipsec_tso)
+ tp->t_flags2 |= TF2_IPSEC_TSO;
}
}