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.
This commit is contained in:
Holger Hans Peter Freyther 2010-11-03 19:01:58 +01:00
parent 85334f1309
commit 05c68841a8
5 changed files with 10 additions and 6 deletions

View File

@ -21,7 +21,7 @@ struct bsc_api {
uint16_t rr_cause); uint16_t rr_cause);
void (*assign_fail)(struct gsm_subscriber_connection *conn, void (*assign_fail)(struct gsm_subscriber_connection *conn,
uint16_t rr_cause); uint16_t rr_cause);
void (*clear_request)(struct gsm_subscriber_connection *conn, int (*clear_request)(struct gsm_subscriber_connection *conn,
uint32_t cause); uint32_t cause);
void (*clear_compl)(struct gsm_subscriber_connection *conn); void (*clear_compl)(struct gsm_subscriber_connection *conn);
}; };

View File

@ -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) static void bsc_clear_compl(struct gsm_subscriber_connection *conn)

View File

@ -241,6 +241,7 @@ static int bsc_handle_lchan_signal(unsigned int subsys, unsigned int signal,
struct bsc_api *bsc; struct bsc_api *bsc;
struct gsm_lchan *lchan; struct gsm_lchan *lchan;
struct gsm_subscriber_connection *conn; struct gsm_subscriber_connection *conn;
int destruct = 1;
if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE) if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
return 0; return 0;
@ -255,7 +256,7 @@ static int bsc_handle_lchan_signal(unsigned int subsys, unsigned int signal,
conn = lchan->conn; conn = lchan->conn;
if (bsc->clear_request) if (bsc->clear_request)
bsc->clear_request(conn, 0); destruct = bsc->clear_request(conn, 0);
/* now give up all channels */ /* now give up all channels */
if (conn->lchan == lchan) if (conn->lchan == lchan)
@ -264,6 +265,9 @@ static int bsc_handle_lchan_signal(unsigned int subsys, unsigned int signal,
conn->ho_lchan = NULL; conn->ho_lchan = NULL;
gsm0808_clear(conn); gsm0808_clear(conn);
if (destruct)
subscr_con_free(conn);
return 0; return 0;
} }

View File

@ -328,8 +328,6 @@ void gsm0408_clear_request(struct gsm_subscriber_connection *conn, uint32_t caus
if (trans->conn == conn) if (trans->conn == conn)
trans_free(trans); trans_free(trans);
} }
subscr_con_free(conn);
} }
/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */ /* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */

View File

@ -36,9 +36,10 @@ static void msc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
gsm411_sapi_n_reject(conn); 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); gsm0408_clear_request(conn, cause);
return 1;
} }
static int msc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg, static int msc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg,