Skip to content

Commit ac7b129

Browse files
pfalconjukkar
authored andcommitted
net: tcp: Validate incoming ACK number
Per RFC 793: A new acknowledgment (called an "acceptable ack"), is one for which the inequality below holds: SND.UNA < SEG.ACK =< SND.NXT If acknowledgement is received for sequence number which wasn't yet sent, log an error and ignore it. Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
1 parent 5d32b5c commit ac7b129

File tree

3 files changed

+20
-4
lines changed

3 files changed

+20
-4
lines changed

subsys/net/ip/net_context.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,11 +1192,14 @@ NET_CONN_CB(tcp_established)
11921192

11931193
/* Handle TCP state transition */
11941194
if (tcp_flags & NET_TCP_ACK) {
1195+
if (!net_tcp_ack_received(context,
1196+
sys_get_be32(tcp_hdr->ack))) {
1197+
return NET_DROP;
1198+
}
1199+
11951200
/* TCP state might be changed after maintaining the sent pkt
11961201
* list, e.g., an ack of FIN is received.
11971202
*/
1198-
net_tcp_ack_received(context,
1199-
sys_get_be32(tcp_hdr->ack));
12001203

12011204
if (net_tcp_get_state(context->tcp)
12021205
== NET_TCP_FIN_WAIT_1) {

subsys/net/ip/tcp.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -901,7 +901,7 @@ int net_tcp_send_data(struct net_context *context)
901901
return 0;
902902
}
903903

904-
void net_tcp_ack_received(struct net_context *ctx, u32_t ack)
904+
bool net_tcp_ack_received(struct net_context *ctx, u32_t ack)
905905
{
906906
struct net_tcp *tcp = ctx->tcp;
907907
sys_slist_t *list = &ctx->tcp->sent_list;
@@ -910,6 +910,16 @@ void net_tcp_ack_received(struct net_context *ctx, u32_t ack)
910910
u32_t seq;
911911
bool valid_ack = false;
912912

913+
if (net_tcp_seq_greater(ack, ctx->tcp->send_seq)) {
914+
NET_ERR("ctx %p: ACK for unsent data", ctx);
915+
net_stats_update_tcp_seg_ackerr();
916+
/* RFC 793 doesn't say that invalid ack sequence is an error
917+
* in the general case, but we implement tighter checking,
918+
* and consider entire packet invalid.
919+
*/
920+
return false;
921+
}
922+
913923
if (IS_ENABLED(CONFIG_NET_STATISTICS_TCP) &&
914924
sys_slist_is_empty(list)) {
915925
net_stats_update_tcp_seg_ackerr();
@@ -981,6 +991,8 @@ void net_tcp_ack_received(struct net_context *ctx, u32_t ack)
981991
net_tcp_send_data(ctx);
982992
}
983993
}
994+
995+
return true;
984996
}
985997

986998
void net_tcp_init(void)

subsys/net/ip/tcp.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,9 @@ int net_tcp_send_pkt(struct net_pkt *pkt);
356356
*
357357
* @param cts Context
358358
* @param seq Received ACK sequence number
359+
* @return False if ACK sequence number is invalid, true otherwise
359360
*/
360-
void net_tcp_ack_received(struct net_context *ctx, u32_t ack);
361+
bool net_tcp_ack_received(struct net_context *ctx, u32_t ack);
361362

362363
/**
363364
* @brief Calculates and returns the MSS for a given TCP context

0 commit comments

Comments
 (0)