From b6a0e3fd2e5b518332a6dbb3443f1733d8a89cd2 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Thu, 10 Jun 2021 19:40:48 +0200 Subject: [PATCH] ggsn: Fix heap-use-after-free during Recovery without associated PDP Related: OS#4641 Change-Id: Ib4dca2e30e723a196084b0fa0040fbceca835359 --- ggsn/sgsn.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ggsn/sgsn.c b/ggsn/sgsn.c index 8360439..15548ef 100644 --- a/ggsn/sgsn.c +++ b/ggsn/sgsn.c @@ -116,6 +116,7 @@ static unsigned int sgsn_peer_drop_all_pdp_except(struct sgsn_peer *sgsn, struct { unsigned int num = 0; char buf[INET_ADDRSTRLEN]; + unsigned int count = llist_count(&sgsn->pdp_list); inet_ntop(AF_INET, &sgsn->addr, buf, sizeof(buf)); @@ -125,10 +126,17 @@ static unsigned int sgsn_peer_drop_all_pdp_except(struct sgsn_peer *sgsn, struct continue; ggsn_close_one_pdp(pdp->lib); num++; + if (num == count) { + /* Note: if except is NULL, all pdp contexts are freed and sgsn + * is most probably already freed at this point. + * As a result, last access to sgsn->pdp_list before exiting + * loop would access already freed memory. Avoid it by exiting + * the loop without the last check, and make sure sgsn is not + * accessed after this loop. */ + break; + } } - /* Note: if except is NULL, all pdp contexts are freed and sgsn is - already freed at this point */ LOGP(DGGSN, LOGL_INFO, "SGSN(%s) Dropped %u PDP contexts\n", buf, num); return num;