diff options
author | Pau Espin Pedrol <pespin@sysmocom.de> | 2021-06-10 19:40:48 +0200 |
---|---|---|
committer | Pau Espin Pedrol <pespin@sysmocom.de> | 2021-06-10 19:41:00 +0200 |
commit | b6a0e3fd2e5b518332a6dbb3443f1733d8a89cd2 (patch) | |
tree | b6eedb20e58b8541e997c4b3b033abbce7eb6518 | |
parent | bd2b55679e897b8f2ef14bf24e4e17967098c03f (diff) |
ggsn: Fix heap-use-after-free during Recovery without associated PDP
Related: OS#4641
Change-Id: Ib4dca2e30e723a196084b0fa0040fbceca835359
-rw-r--r-- | ggsn/sgsn.c | 12 |
1 files 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; |