Skip to content

Commit

Permalink
tcp: implement RFC 5961 4.2
Browse files Browse the repository at this point in the history
Implement the RFC 5691 mitigation against Blind
Reset attack using SYN bit.

Section 4.2 of RFC 5961 advises to send a Challenge ACK and drop
incoming packet, instead of resetting the session.

Add a new SNMP counter to count number of challenge acks sent
in response to SYN packets.
(netstat -s | grep TCPSYNChallenge)

Remove obsolete TCPAbortOnSyn, since we no longer abort a TCP session
because of a SYN flag.

Signed-off-by: Eric Dumazet <[email protected]>
Cc: Kiran Kumar Kella <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Eric Dumazet authored and davem330 committed Jul 17, 2012
1 parent 5f3600e commit 0c24604
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 19 deletions.
2 changes: 1 addition & 1 deletion include/linux/snmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,6 @@ enum
LINUX_MIB_TCPDSACKOFOSENT, /* TCPDSACKOfoSent */
LINUX_MIB_TCPDSACKRECV, /* TCPDSACKRecv */
LINUX_MIB_TCPDSACKOFORECV, /* TCPDSACKOfoRecv */
LINUX_MIB_TCPABORTONSYN, /* TCPAbortOnSyn */
LINUX_MIB_TCPABORTONDATA, /* TCPAbortOnData */
LINUX_MIB_TCPABORTONCLOSE, /* TCPAbortOnClose */
LINUX_MIB_TCPABORTONMEMORY, /* TCPAbortOnMemory */
Expand Down Expand Up @@ -238,6 +237,7 @@ enum
LINUX_MIB_TCPOFODROP, /* TCPOFODrop */
LINUX_MIB_TCPOFOMERGE, /* TCPOFOMerge */
LINUX_MIB_TCPCHALLENGEACK, /* TCPChallengeACK */
LINUX_MIB_TCPSYNCHALLENGE, /* TCPSYNChallenge */
__LINUX_MIB_MAX
};

Expand Down
2 changes: 1 addition & 1 deletion net/ipv4/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,6 @@ static const struct snmp_mib snmp4_net_list[] = {
SNMP_MIB_ITEM("TCPDSACKOfoSent", LINUX_MIB_TCPDSACKOFOSENT),
SNMP_MIB_ITEM("TCPDSACKRecv", LINUX_MIB_TCPDSACKRECV),
SNMP_MIB_ITEM("TCPDSACKOfoRecv", LINUX_MIB_TCPDSACKOFORECV),
SNMP_MIB_ITEM("TCPAbortOnSyn", LINUX_MIB_TCPABORTONSYN),
SNMP_MIB_ITEM("TCPAbortOnData", LINUX_MIB_TCPABORTONDATA),
SNMP_MIB_ITEM("TCPAbortOnClose", LINUX_MIB_TCPABORTONCLOSE),
SNMP_MIB_ITEM("TCPAbortOnMemory", LINUX_MIB_TCPABORTONMEMORY),
Expand Down Expand Up @@ -262,6 +261,7 @@ static const struct snmp_mib snmp4_net_list[] = {
SNMP_MIB_ITEM("TCPOFODrop", LINUX_MIB_TCPOFODROP),
SNMP_MIB_ITEM("TCPOFOMerge", LINUX_MIB_TCPOFOMERGE),
SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK),
SNMP_MIB_ITEM("TCPSYNChallenge", LINUX_MIB_TCPSYNCHALLENGE),
SNMP_MIB_SENTINEL
};

Expand Down
32 changes: 15 additions & 17 deletions net/ipv4/tcp_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -5270,8 +5270,8 @@ static void tcp_send_challenge_ack(struct sock *sk)
/* Does PAWS and seqno based validation of an incoming segment, flags will
* play significant role here.
*/
static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
const struct tcphdr *th, int syn_inerr)
static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
const struct tcphdr *th, int syn_inerr)
{
const u8 *hash_location;
struct tcp_sock *tp = tcp_sk(sk);
Expand Down Expand Up @@ -5323,20 +5323,22 @@ static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,

/* step 3: check security and precedence [ignored] */

/* step 4: Check for a SYN in window. */
if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
/* step 4: Check for a SYN
* RFC 5691 4.2 : Send a challenge ack
*/
if (th->syn) {
if (syn_inerr)
TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONSYN);
tcp_reset(sk);
return -1;
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE);
tcp_send_challenge_ack(sk);
goto discard;
}

return 1;
return true;

discard:
__kfree_skb(skb);
return 0;
return false;
}

/*
Expand Down Expand Up @@ -5366,7 +5368,6 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
const struct tcphdr *th, unsigned int len)
{
struct tcp_sock *tp = tcp_sk(sk);
int res;

if (sk->sk_rx_dst) {
struct dst_entry *dst = sk->sk_rx_dst;
Expand Down Expand Up @@ -5555,9 +5556,8 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
* Standard slow path.
*/

res = tcp_validate_incoming(sk, skb, th, 1);
if (res <= 0)
return -res;
if (!tcp_validate_incoming(sk, skb, th, 1))
return 0;

step5:
if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
Expand Down Expand Up @@ -5877,7 +5877,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
struct tcp_sock *tp = tcp_sk(sk);
struct inet_connection_sock *icsk = inet_csk(sk);
int queued = 0;
int res;

tp->rx_opt.saw_tstamp = 0;

Expand Down Expand Up @@ -5932,9 +5931,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
return 0;
}

res = tcp_validate_incoming(sk, skb, th, 0);
if (res <= 0)
return -res;
if (!tcp_validate_incoming(sk, skb, th, 0))
return 0;

/* step 5: check the ACK field */
if (th->ack) {
Expand Down

0 comments on commit 0c24604

Please sign in to comment.