diff options
author | Alexander Couzens <lynxis@fe80.eu> | 2021-07-20 19:05:45 +0200 |
---|---|---|
committer | Alexander Couzens <lynxis@fe80.eu> | 2021-08-06 20:06:14 +0200 |
commit | 333b46193e39875528579508f7251570e3062a31 (patch) | |
tree | 7848e01d71341dfdc15d82190d12f54009143128 | |
parent | c66e348818d05496ae11c263ea8d021ef5a4e6ce (diff) |
gprs_ns2: dont use llist_for_each when freeing an element
The problem are recursive execution because a free generates an event which could
allow the use to free a nsvcs while the llist_for_each() is still running
Change-Id: I902557fb6e56e6588728a46e43a9cbe3215d5c68
-rw-r--r-- | src/gb/gprs_ns2.c | 31 | ||||
-rw-r--r-- | src/gb/gprs_ns2_sns.c | 5 |
2 files changed, 21 insertions, 15 deletions
diff --git a/src/gb/gprs_ns2.c b/src/gb/gprs_ns2.c index ca8de19b..9c126acb 100644 --- a/src/gb/gprs_ns2.c +++ b/src/gb/gprs_ns2.c @@ -669,7 +669,7 @@ void gprs_ns2_free_nsvc(struct gprs_ns2_vc *nsvc) */ void gprs_ns2_free_nsvcs(struct gprs_ns2_nse *nse) { - struct gprs_ns2_vc *nsvc, *tmp; + struct gprs_ns2_vc *nsvc; if (!nse || nse->freed) return; @@ -677,7 +677,8 @@ void gprs_ns2_free_nsvcs(struct gprs_ns2_nse *nse) if (nse->bss_sns_fi) { osmo_fsm_inst_dispatch(nse->bss_sns_fi, GPRS_SNS_EV_REQ_FREE_NSVCS, NULL); } else { - llist_for_each_entry_safe(nsvc, tmp, &nse->nsvc, list) { + while (!llist_empty(&nse->nsvc)) { + nsvc = llist_first_entry(&nse->nsvc, struct gprs_ns2_vc, list); gprs_ns2_free_nsvc(nsvc); } } @@ -893,7 +894,7 @@ uint16_t gprs_ns2_nse_nsei(struct gprs_ns2_nse *nse) * \param[in] nse NS Entity to destroy */ void gprs_ns2_free_nse(struct gprs_ns2_nse *nse) { - struct gprs_ns2_vc *nsvc, *nsvc2; + struct gprs_ns2_vc *nsvc; if (!nse || nse->freed) return; @@ -907,7 +908,8 @@ void gprs_ns2_free_nse(struct gprs_ns2_nse *nse) gprs_ns2_free_nsvcs(nse); ns2_prim_status_ind(nse, NULL, 0, GPRS_NS2_AFF_CAUSE_FAILURE); rate_ctr_group_free(nse->ctrg); - llist_for_each_entry_safe(nsvc, nsvc2, &nse->nsvc, list) { + while (!llist_empty(&nse->nsvc)) { + nsvc = llist_first_entry(&nse->nsvc, struct gprs_ns2_vc, list); gprs_ns2_free_nsvc(nsvc); } @@ -917,9 +919,10 @@ void gprs_ns2_free_nse(struct gprs_ns2_nse *nse) void gprs_ns2_free_nses(struct gprs_ns2_inst *nsi) { - struct gprs_ns2_nse *nse, *ntmp; + struct gprs_ns2_nse *nse; - llist_for_each_entry_safe(nse, ntmp, &nsi->nse, list) { + while (!llist_empty(&nsi->nse)) { + nse = llist_first_entry(&nsi->nse, struct gprs_ns2_nse, list); gprs_ns2_free_nse(nse); } } @@ -1473,22 +1476,23 @@ void gprs_ns2_start_alive_all_nsvcs(struct gprs_ns2_nse *nse) * \param[in] bind the bind we want to destroy */ void gprs_ns2_free_bind(struct gprs_ns2_vc_bind *bind) { - struct gprs_ns2_vc *nsvc, *tmp; + struct gprs_ns2_vc *nsvc; struct gprs_ns2_nse *nse; if (!bind || bind->freed) return; bind->freed = true; - llist_for_each_entry_safe(nsvc, tmp, &bind->nsvc, blist) { - gprs_ns2_free_nsvc(nsvc); - } - if (gprs_ns2_is_ip_bind(bind)) { llist_for_each_entry(nse, &bind->nsi->nse, list) { gprs_ns2_sns_del_bind(nse, bind); } } + while (!llist_empty(&bind->nsvc)) { + nsvc = llist_first_entry(&bind->nsvc, struct gprs_ns2_vc, blist); + gprs_ns2_free_nsvc(nsvc); + } + if (bind->driver->free_bind) bind->driver->free_bind(bind); @@ -1500,9 +1504,10 @@ void gprs_ns2_free_bind(struct gprs_ns2_vc_bind *bind) void gprs_ns2_free_binds(struct gprs_ns2_inst *nsi) { - struct gprs_ns2_vc_bind *bind, *tbind; + struct gprs_ns2_vc_bind *bind; - llist_for_each_entry_safe(bind, tbind, &nsi->binding, list) { + while (!llist_empty(&nsi->binding)) { + bind = llist_first_entry(&nsi->binding, struct gprs_ns2_vc_bind, list); gprs_ns2_free_bind(bind); } } diff --git a/src/gb/gprs_ns2_sns.c b/src/gb/gprs_ns2_sns.c index f38a60dd..a9964b4a 100644 --- a/src/gb/gprs_ns2_sns.c +++ b/src/gb/gprs_ns2_sns.c @@ -1565,7 +1565,7 @@ static void ns2_sns_st_all_action_bss(struct osmo_fsm_inst *fi, uint32_t event, { struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv; struct gprs_ns2_nse *nse = nse_inst_from_fi(fi); - struct gprs_ns2_vc *nsvc, *nsvc2; + struct gprs_ns2_vc *nsvc; /* reset when receiving GPRS_SNS_EV_REQ_NO_NSVC */ switch (event) { @@ -1581,7 +1581,8 @@ static void ns2_sns_st_all_action_bss(struct osmo_fsm_inst *fi, uint32_t event, /* tear down previous state * gprs_ns2_free_nsvcs() will trigger NO_NSVC, prevent this from triggering a reselection */ gss->reselection_running = true; - llist_for_each_entry_safe(nsvc, nsvc2, &nse->nsvc, list) { + while (!llist_empty(&nse->nsvc)) { + nsvc = llist_first_entry(&nse->nsvc, struct gprs_ns2_vc, list); gprs_ns2_free_nsvc(nsvc); } ns2_clear_elems(&gss->local); |