mirror of https://gerrit.osmocom.org/libosmocore
gprs_ns2: add recursive anchor to protect against double free
When free'ing a NSE/NSVC/BIND ensure there can't be a double free by using a free anchor in the struct. Recursive free's can happen when the NS user reacts on an event (e.g. GPRS_NS2_AFF_CAUSE_VC_FAILURE) and calls the free(). Or when the user free's a NSVC when the NSE uses SNS as configuration, the fsm tries to free it again. Change-Id: If9823aadaa936e136aa43e88cee925ddd5974841
This commit is contained in:
parent
1c40525f44
commit
41589a3e7a
|
@ -639,9 +639,9 @@ err:
|
|||
* \param[in] nsvc NS-VC to destroy */
|
||||
void gprs_ns2_free_nsvc(struct gprs_ns2_vc *nsvc)
|
||||
{
|
||||
if (!nsvc)
|
||||
if (!nsvc || nsvc->freed)
|
||||
return;
|
||||
|
||||
nsvc->freed = true;
|
||||
ns2_prim_status_ind(nsvc->nse, nsvc, 0, GPRS_NS2_AFF_CAUSE_VC_FAILURE);
|
||||
|
||||
llist_del(&nsvc->list);
|
||||
|
@ -671,7 +671,7 @@ void gprs_ns2_free_nsvcs(struct gprs_ns2_nse *nse)
|
|||
{
|
||||
struct gprs_ns2_vc *nsvc, *tmp;
|
||||
|
||||
if (!nse)
|
||||
if (!nse || nse->freed)
|
||||
return;
|
||||
|
||||
llist_for_each_entry_safe(nsvc, tmp, &nse->nsvc, list) {
|
||||
|
@ -889,9 +889,11 @@ 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)
|
||||
{
|
||||
if (!nse)
|
||||
struct gprs_ns2_vc *nsvc, *nsvc2;
|
||||
if (!nse || nse->freed)
|
||||
return;
|
||||
|
||||
nse->freed = true;
|
||||
nse->alive = false;
|
||||
if (nse->bss_sns_fi) {
|
||||
osmo_fsm_inst_term(nse->bss_sns_fi, OSMO_FSM_TERM_REQUEST, NULL);
|
||||
|
@ -901,6 +903,9 @@ 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) {
|
||||
gprs_ns2_free_nsvc(nsvc);
|
||||
}
|
||||
|
||||
llist_del(&nse->list);
|
||||
talloc_free(nse);
|
||||
|
@ -1466,9 +1471,10 @@ void gprs_ns2_free_bind(struct gprs_ns2_vc_bind *bind)
|
|||
{
|
||||
struct gprs_ns2_vc *nsvc, *tmp;
|
||||
struct gprs_ns2_nse *nse;
|
||||
if (!bind)
|
||||
if (!bind || bind->freed)
|
||||
return;
|
||||
|
||||
bind->freed = true;
|
||||
llist_for_each_entry_safe(nsvc, tmp, &bind->nsvc, blist) {
|
||||
gprs_ns2_free_nsvc(nsvc);
|
||||
}
|
||||
|
|
|
@ -215,6 +215,9 @@ struct gprs_ns2_nse {
|
|||
|
||||
/*! NSE-wide statistics */
|
||||
struct rate_ctr_group *ctrg;
|
||||
|
||||
/*! recursive anchor */
|
||||
bool freed;
|
||||
};
|
||||
|
||||
/*! Structure representing a single NS-VC */
|
||||
|
@ -259,6 +262,9 @@ struct gprs_ns2_vc {
|
|||
enum gprs_ns2_vc_mode mode;
|
||||
|
||||
struct osmo_fsm_inst *fi;
|
||||
|
||||
/*! recursive anchor */
|
||||
bool freed;
|
||||
};
|
||||
|
||||
/*! Structure repesenting a bind instance. E.g. IPv4 listen port. */
|
||||
|
@ -303,6 +309,9 @@ struct gprs_ns2_vc_bind {
|
|||
uint8_t sns_data_weight;
|
||||
|
||||
struct osmo_stat_item_group *statg;
|
||||
|
||||
/*! recursive anchor */
|
||||
bool freed;
|
||||
};
|
||||
|
||||
struct gprs_ns2_vc_driver {
|
||||
|
|
Loading…
Reference in New Issue