gbproxy: Check whether gbproxy_update_link_state_after() deletes the link_info

In case the link_info is deleted we have to stop handling the stored messages
inside link_info. Not doing so can lead to invalid memory being accessed.

Change-Id: Ieb8503e9e94e7a5ac450ad8aa1713ec4f21cdea5
Ticket: OW#3049
Sponsored-by: On-Waves ehf
This commit is contained in:
Daniel Willmann
2016-11-07 17:54:29 +01:00
committed by Harald Welte
parent 58273f4b88
commit beade314d0
3 changed files with 27 additions and 13 deletions

View File

@@ -208,7 +208,7 @@ struct gbproxy_link_info *gbproxy_update_link_state_ul(
struct gbproxy_link_info *gbproxy_update_link_state_dl( struct gbproxy_link_info *gbproxy_update_link_state_dl(
struct gbproxy_peer *peer, time_t now, struct gbproxy_peer *peer, time_t now,
struct gprs_gb_parse_context *parse_ctx); struct gprs_gb_parse_context *parse_ctx);
void gbproxy_update_link_state_after( int gbproxy_update_link_state_after(
struct gbproxy_peer *peer, struct gbproxy_link_info *link_info, struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
time_t now, struct gprs_gb_parse_context *parse_ctx); time_t now, struct gprs_gb_parse_context *parse_ctx);
int gbproxy_remove_stale_link_infos(struct gbproxy_peer *peer, time_t now); int gbproxy_remove_stale_link_infos(struct gbproxy_peer *peer, time_t now);

View File

@@ -318,7 +318,7 @@ static void gbproxy_reset_imsi_acquisition(struct gbproxy_link_info* link_info)
link_info->vu_gen_tx_bss = GBPROXY_INIT_VU_GEN_TX; link_info->vu_gen_tx_bss = GBPROXY_INIT_VU_GEN_TX;
} }
static void gbproxy_flush_stored_messages(struct gbproxy_peer *peer, static int gbproxy_flush_stored_messages(struct gbproxy_peer *peer,
struct msgb *msg, struct msgb *msg,
time_t now, time_t now,
struct gbproxy_link_info* link_info, struct gbproxy_link_info* link_info,
@@ -349,8 +349,13 @@ static void gbproxy_flush_stored_messages(struct gbproxy_peer *peer,
peer, link_info, &len_change, peer, link_info, &len_change,
&tmp_parse_ctx); &tmp_parse_ctx);
gbproxy_update_link_state_after(peer, link_info, now, rc = gbproxy_update_link_state_after(peer, link_info, now,
&tmp_parse_ctx); &tmp_parse_ctx);
if (rc == 1) {
LOGP(DLLC, LOGL_NOTICE, "link_info deleted while flushing stored messages\n");
msgb_free(stored_msg);
return -1;
}
rc = gbprox_relay2sgsn(peer->cfg, stored_msg, rc = gbprox_relay2sgsn(peer->cfg, stored_msg,
msgb_bvci(msg), link_info->sgsn_nsei); msgb_bvci(msg), link_info->sgsn_nsei);
@@ -364,6 +369,8 @@ static void gbproxy_flush_stored_messages(struct gbproxy_peer *peer,
parse_ctx->llc_msg_name : "BSSGP"); parse_ctx->llc_msg_name : "BSSGP");
msgb_free(stored_msg); msgb_free(stored_msg);
} }
return 0;
} }
static int gbproxy_gsm48_to_peer(struct gbproxy_peer *peer, static int gbproxy_gsm48_to_peer(struct gbproxy_peer *peer,
@@ -465,9 +472,12 @@ static int gbproxy_imsi_acquisition(struct gbproxy_peer *peer,
gsm48_hdr_pdisc(parse_ctx->g48_hdr) == GSM48_PDISC_MM_GPRS && gsm48_hdr_pdisc(parse_ctx->g48_hdr) == GSM48_PDISC_MM_GPRS &&
gsm48_hdr_msg_type(parse_ctx->g48_hdr) == GSM48_MT_GMM_ID_RESP; gsm48_hdr_msg_type(parse_ctx->g48_hdr) == GSM48_MT_GMM_ID_RESP;
/* The IMSI is now available */ /* The IMSI is now available. If flushing the messages fails,
gbproxy_flush_stored_messages(peer, msg, now, link_info, * then link_info has been deleted and we should return
parse_ctx); * immediately. */
if (gbproxy_flush_stored_messages(peer, msg, now, link_info,
parse_ctx) < 0)
return 0;
gbproxy_reset_imsi_acquisition(link_info); gbproxy_reset_imsi_acquisition(link_info);

View File

@@ -348,18 +348,18 @@ static void gbproxy_touch_link_info(struct gbproxy_peer *peer,
gbproxy_attach_link_info(peer, now, link_info); gbproxy_attach_link_info(peer, now, link_info);
} }
static void gbproxy_unregister_link_info(struct gbproxy_peer *peer, static int gbproxy_unregister_link_info(struct gbproxy_peer *peer,
struct gbproxy_link_info *link_info) struct gbproxy_link_info *link_info)
{ {
if (!link_info) if (!link_info)
return; return 1;
if (link_info->tlli.ptmsi == GSM_RESERVED_TMSI && !link_info->imsi_len) { if (link_info->tlli.ptmsi == GSM_RESERVED_TMSI && !link_info->imsi_len) {
LOGP(DGPRS, LOGL_INFO, LOGP(DGPRS, LOGL_INFO,
"Removing TLLI %08x from list (P-TMSI or IMSI are not set)\n", "Removing TLLI %08x from list (P-TMSI or IMSI are not set)\n",
link_info->tlli.current); link_info->tlli.current);
gbproxy_delete_link_info(peer, link_info); gbproxy_delete_link_info(peer, link_info);
return; return 1;
} }
link_info->tlli.current = 0; link_info->tlli.current = 0;
@@ -371,7 +371,7 @@ static void gbproxy_unregister_link_info(struct gbproxy_peer *peer,
gbproxy_reset_link(link_info); gbproxy_reset_link(link_info);
return; return 0;
} }
int gbproxy_imsi_matches(struct gbproxy_config *cfg, int gbproxy_imsi_matches(struct gbproxy_config *cfg,
@@ -668,12 +668,13 @@ struct gbproxy_link_info *gbproxy_update_link_state_dl(
return link_info; return link_info;
} }
void gbproxy_update_link_state_after( int gbproxy_update_link_state_after(
struct gbproxy_peer *peer, struct gbproxy_peer *peer,
struct gbproxy_link_info *link_info, struct gbproxy_link_info *link_info,
time_t now, time_t now,
struct gprs_gb_parse_context *parse_ctx) struct gprs_gb_parse_context *parse_ctx)
{ {
int rc = 0;
if (parse_ctx->invalidate_tlli && link_info) { if (parse_ctx->invalidate_tlli && link_info) {
int keep_info = int keep_info =
peer->cfg->keep_link_infos == GBPROX_KEEP_ALWAYS || peer->cfg->keep_link_infos == GBPROX_KEEP_ALWAYS ||
@@ -684,11 +685,12 @@ void gbproxy_update_link_state_after(
if (keep_info) { if (keep_info) {
LOGP(DGPRS, LOGL_INFO, "Unregistering TLLI %08x\n", LOGP(DGPRS, LOGL_INFO, "Unregistering TLLI %08x\n",
link_info->tlli.current); link_info->tlli.current);
gbproxy_unregister_link_info(peer, link_info); rc = gbproxy_unregister_link_info(peer, link_info);
} else { } else {
LOGP(DGPRS, LOGL_INFO, "Removing TLLI %08x from list\n", LOGP(DGPRS, LOGL_INFO, "Removing TLLI %08x from list\n",
link_info->tlli.current); link_info->tlli.current);
gbproxy_delete_link_info(peer, link_info); gbproxy_delete_link_info(peer, link_info);
rc = 1;
} }
} else if (parse_ctx->to_bss && parse_ctx->tlli_enc && } else if (parse_ctx->to_bss && parse_ctx->tlli_enc &&
parse_ctx->new_ptmsi_enc && link_info) { parse_ctx->new_ptmsi_enc && link_info) {
@@ -714,6 +716,8 @@ void gbproxy_update_link_state_after(
} }
gbproxy_remove_stale_link_infos(peer, now); gbproxy_remove_stale_link_infos(peer, now);
return rc;
} }