From ff7cb4cb45f0311e2b198d0833e1af520b7e7c4e Mon Sep 17 00:00:00 2001
From: Libor Peltan <libor.peltan@nic.cz>
Date: Mon, 15 Nov 2021 15:24:06 +0100
Subject: [PATCH] xdp-tcp: bugfix: crash when two packets for same conn...

...and one of them is closing it
---
 src/libknot/xdp/tcp.c        | 6 ++----
 src/libknot/xdp/tcp.h        | 2 +-
 tests/libknot/test_xdp_tcp.c | 1 +
 3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/src/libknot/xdp/tcp.c b/src/libknot/xdp/tcp.c
index fed16e554f..c6c10ec3c6 100644
--- a/src/libknot/xdp/tcp.c
+++ b/src/libknot/xdp/tcp.c
@@ -381,8 +381,7 @@ int knot_tcp_recv(knot_tcp_relay_t *relays, knot_xdp_msg_t *msgs, uint32_t count
 				case XDP_TCP_CLOSING2:
 					if (msg->payload.iov_len == 0) { // otherwise ignore close
 						tcp_table_remove(pconn, tcp_table);
-						del_conn(conn);
-						relay->conn = NULL;
+						relay->answer = XDP_TCP_FREE;
 					}
 					break;
 				}
@@ -414,8 +413,7 @@ int knot_tcp_recv(knot_tcp_relay_t *relays, knot_xdp_msg_t *msgs, uint32_t count
 			if (conn != NULL && msg->seqno == conn->seqno) {
 				relay->action = XDP_TCP_RESET;
 				tcp_table_remove(pconn, tcp_table);
-				del_conn(conn);
-				relay->conn = NULL;
+				relay->answer = XDP_TCP_FREE;
 			} else if (conn != NULL) {
 				relay->auto_answer = KNOT_XDP_MSG_ACK;
 			}
diff --git a/src/libknot/xdp/tcp.h b/src/libknot/xdp/tcp.h
index cefd96780e..2cde210bed 100644
--- a/src/libknot/xdp/tcp.h
+++ b/src/libknot/xdp/tcp.h
@@ -125,7 +125,7 @@ inline static uint32_t knot_tcp_next_seqno(const knot_xdp_msg_t *msg)
 
 inline static bool knot_tcp_relay_empty(const knot_tcp_relay_t *r)
 {
-	return r->action == XDP_TCP_NOOP && r->auto_answer == 0 && r->inbufs_count == 0;
+	return r->action == XDP_TCP_NOOP && r->answer == XDP_TCP_NOOP && r->auto_answer == 0 && r->inbufs_count == 0;
 }
 
 /*!
diff --git a/tests/libknot/test_xdp_tcp.c b/tests/libknot/test_xdp_tcp.c
index d0299af25e..b88bee7785 100644
--- a/tests/libknot/test_xdp_tcp.c
+++ b/tests/libknot/test_xdp_tcp.c
@@ -380,6 +380,7 @@ void test_close(void)
 	check_sent(0, 0, 0, 0);
 	is_int(conns_pre - 1, test_table->usage, "close: connection removed");
 	is_int(conns_pre - 1, tcp_table_timeout_length(test_table), "close: timeout list size");
+	knot_tcp_cleanup(test_table, &rl, 1);
 }
 
 void test_many(void)
-- 
GitLab