aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2021-06-10 19:40:48 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2021-06-10 19:41:00 +0200
commitb6a0e3fd2e5b518332a6dbb3443f1733d8a89cd2 (patch)
treeb6eedb20e58b8541e997c4b3b033abbce7eb6518
parentbd2b55679e897b8f2ef14bf24e4e17967098c03f (diff)
ggsn: Fix heap-use-after-free during Recovery without associated PDP
-rw-r--r--ggsn/sgsn.c12
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;