Skip to content

Commit 687df40

Browse files
committed
BUG/MINOR: connection: streamline conn detach from lists
Over their lifetime, connections are attached to different list. These lists depends on whether connection is on frontend or backend side. Attach point members are stored via a union in struct connection. The next commit reorganizes them so that a proper frontend/backend separation is performed : commit a96f128 BUG/MINOR: connection: rearrange union list members On conn_free(), connection instance must be removed from these lists to ensure there is no use-after-free case. However code was still shaky there, despite no real issue. Indeed, <toremove_list> was detached for all connections, despite being only used on backend side only. This patch streamlines the freeing of connection. Now, <toremove_list> detach is performed in conn_backend_deinit(). Moreover, a new helper conn_frontend_deinit() is defined. It ensures that <stopping_list> detach is done. Prior it was performed individually by muxes. Note that a similar procedure is performed when the connection is reversed. Hence, conn_frontend_deinit() is now used here as well, rendering reversal from FE to BE or vice versa symmetrical. As mentionned above, no crash occured prior to this patch, but the code was fragile, in particular access to <toremove_list> for frontend connections. Thus this patch is considered as a bug fix worthy of a backport along with above mentionned patch, currently up to 3.0.
1 parent 27ff7ff commit 687df40

4 files changed

Lines changed: 15 additions & 17 deletions

File tree

src/connection.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,18 @@ static void conn_backend_deinit(struct connection *conn)
555555
pool_free(pool_head_conn_hash_node, conn->hash_node);
556556
conn->hash_node = NULL;
557557

558+
/* Remove from BE purge list. Necessary if conn already scheduled for
559+
* purge but finally freed before by another code path.
560+
*/
561+
MT_LIST_DELETE(&conn->toremove_list);
562+
}
563+
564+
/* Ensure <conn> frontend connection is removed from its lists. This must be
565+
* performed before freeing or reversing a connection.
566+
*/
567+
static void conn_frontend_deinit(struct connection *conn)
568+
{
569+
LIST_DEL_INIT(&conn->stopping_list);
558570
}
559571

560572
/* Tries to allocate a new connection and initialized its main fields. The
@@ -594,14 +606,8 @@ void conn_free(struct connection *conn)
594606

595607
if (conn_is_back(conn))
596608
conn_backend_deinit(conn);
597-
598-
/* Remove the conn from toremove_list.
599-
*
600-
* This is needed to prevent a double-free in case the connection was
601-
* already scheduled from cleaning but is freed before via another
602-
* call.
603-
*/
604-
MT_LIST_DELETE(&conn->toremove_list);
609+
else
610+
conn_frontend_deinit(conn);
605611

606612
sockaddr_free(&conn->src);
607613
sockaddr_free(&conn->dst);
@@ -2961,7 +2967,7 @@ int conn_reverse(struct connection *conn)
29612967
struct server *srv = objt_server(conn->reverse.target);
29622968
BUG_ON(!srv);
29632969

2964-
LIST_DEL_INIT(&conn->stopping_list);
2970+
conn_frontend_deinit(conn);
29652971

29662972
if (conn_backend_init(conn))
29672973
return 1;

src/mux_h1.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,9 +1412,6 @@ static void h1_release(struct h1c *h1c)
14121412
pool_free(pool_head_h1c, h1c);
14131413

14141414
if (conn) {
1415-
if (!conn_is_back(conn))
1416-
LIST_DEL_INIT(&conn->stopping_list);
1417-
14181415
conn->mux = NULL;
14191416
conn->ctx = NULL;
14201417
TRACE_DEVEL("freeing conn", H1_EV_H1C_END, conn);

src/mux_h2.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,9 +1516,6 @@ static void h2_release(struct h2c *h2c)
15161516
pool_free(pool_head_h2c, h2c);
15171517

15181518
if (conn) {
1519-
if (!conn_is_back(conn))
1520-
LIST_DEL_INIT(&conn->stopping_list);
1521-
15221519
conn->mux = NULL;
15231520
conn->ctx = NULL;
15241521
TRACE_DEVEL("freeing conn", H2_EV_H2C_END, conn);

src/mux_quic.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3360,8 +3360,6 @@ static void qcc_release(struct qcc *qcc)
33603360
pool_free(pool_head_qcc, qcc);
33613361

33623362
if (conn) {
3363-
LIST_DEL_INIT(&conn->stopping_list);
3364-
33653363
conn->mux = NULL;
33663364
conn->ctx = NULL;
33673365

0 commit comments

Comments
 (0)