aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-11-03 19:01:58 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-11-15 20:06:46 +0100
commit05c68841a835b3bbc5a95fa809e136e4e376154c (patch)
tree6bd4764672fc26a77ad1cfdf66c110fcb4a11aa6 /openbsc/src
parent85334f1309c89cf99e6ea55ea119c5b0d143cb5f (diff)
bsc_api: Fix a use after free error in the Clear Request path
The implementation of bsc_hack would call subscr_con_free before the BSC API has had the chance to call gsm0808_clear to try to release other channels. Fix that by adding a return value.
Diffstat (limited to 'openbsc/src')
-rw-r--r--openbsc/src/bsc/osmo_bsc_api.c3
-rw-r--r--openbsc/src/bsc_api.c6
-rw-r--r--openbsc/src/gsm_04_08.c2
-rw-r--r--openbsc/src/osmo_msc.c3
4 files changed, 9 insertions, 5 deletions
diff --git a/openbsc/src/bsc/osmo_bsc_api.c b/openbsc/src/bsc/osmo_bsc_api.c
index eed58be06..7b9f77844 100644
--- a/openbsc/src/bsc/osmo_bsc_api.c
+++ b/openbsc/src/bsc/osmo_bsc_api.c
@@ -52,8 +52,9 @@ static void bsc_assign_fail(struct gsm_subscriber_connection *conn, uint32_t cau
{
}
-static void bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
+static int bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
{
+ return 0;
}
static void bsc_clear_compl(struct gsm_subscriber_connection *conn)
diff --git a/openbsc/src/bsc_api.c b/openbsc/src/bsc_api.c
index 21d0ae7a3..e8f42d275 100644
--- a/openbsc/src/bsc_api.c
+++ b/openbsc/src/bsc_api.c
@@ -241,6 +241,7 @@ static int bsc_handle_lchan_signal(unsigned int subsys, unsigned int signal,
struct bsc_api *bsc;
struct gsm_lchan *lchan;
struct gsm_subscriber_connection *conn;
+ int destruct = 1;
if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
return 0;
@@ -255,7 +256,7 @@ static int bsc_handle_lchan_signal(unsigned int subsys, unsigned int signal,
conn = lchan->conn;
if (bsc->clear_request)
- bsc->clear_request(conn, 0);
+ destruct = bsc->clear_request(conn, 0);
/* now give up all channels */
if (conn->lchan == lchan)
@@ -264,6 +265,9 @@ static int bsc_handle_lchan_signal(unsigned int subsys, unsigned int signal,
conn->ho_lchan = NULL;
gsm0808_clear(conn);
+ if (destruct)
+ subscr_con_free(conn);
+
return 0;
}
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index ddda19b75..0bd6de225 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -328,8 +328,6 @@ void gsm0408_clear_request(struct gsm_subscriber_connection *conn, uint32_t caus
if (trans->conn == conn)
trans_free(trans);
}
-
- subscr_con_free(conn);
}
/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
diff --git a/openbsc/src/osmo_msc.c b/openbsc/src/osmo_msc.c
index 1fad510fe..0ed973b10 100644
--- a/openbsc/src/osmo_msc.c
+++ b/openbsc/src/osmo_msc.c
@@ -36,9 +36,10 @@ static void msc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
gsm411_sapi_n_reject(conn);
}
-static void msc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
+static int msc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
{
gsm0408_clear_request(conn, cause);
+ return 1;
}
static int msc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg,