ggsn: Fix heap-use-after-free during Recovery without associated PDP

Related: OS#4641
Change-Id: Ib4dca2e30e723a196084b0fa0040fbceca835359
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 @@
 {
 	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 @@
 			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;