From 9001ad2d7c84d08796a96df278f6241c63ac326e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 27 Oct 2023 10:08:04 +0200 Subject: [PATCH 01/12] Correct calloc_or_fail() signature --- common/utils/ocp_itti/intertask_interface.h | 2 -- common/utils/utils.h | 13 +++++++------ openair3/NAS/UE/EMM/IdleMode.c | 2 +- openair3/NAS/UE/EMM/emm_main.c | 8 ++++---- openair3/NAS/UE/ESM/esm_ebr.c | 2 +- openair3/NAS/UE/ESM/esm_main.c | 2 +- openair3/NAS/UE/ESM/esm_pt.c | 2 +- openair3/NAS/UE/nas_proc.c | 4 ++-- openair3/NAS/UE/nas_ue_task.c | 14 +++++++------- openair3/NAS/UE/nas_user.c | 4 ++-- 10 files changed, 26 insertions(+), 27 deletions(-) diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h index 131606f6fe..9a60f95ba9 100644 --- a/common/utils/ocp_itti/intertask_interface.h +++ b/common/utils/ocp_itti/intertask_interface.h @@ -568,8 +568,6 @@ void itti_set_task_real_time(task_id_t task_id); void itti_send_terminate_message(task_id_t task_id); void *itti_malloc(task_id_t origin_task_id, task_id_t destination_task_id, ssize_t size); -void *calloc_or_fail(size_t size); -void *malloc_or_fail(size_t size); int memory_read(const char *datafile, void *data, size_t size); int itti_free(task_id_t task_id, void *ptr); diff --git a/common/utils/utils.h b/common/utils/utils.h index 3f618b61f6..52f94fb3ce 100644 --- a/common/utils/utils.h +++ b/common/utils/utils.h @@ -56,23 +56,24 @@ static inline void *malloc16_clear( size_t size ) { return ptr; } - -static inline void *calloc_or_fail(size_t size) { - void *ptr = calloc(1, size); +static inline void *calloc_or_fail(size_t nmemb, size_t size) +{ + void *ptr = calloc(nmemb, size); if (ptr == NULL) { - fprintf(stderr, "[UE] Failed to calloc %zu bytes", size); + fprintf(stderr, "Failed to calloc() %zu elements of %zu bytes: out of memory", nmemb, size); exit(EXIT_FAILURE); } return ptr; } -static inline void *malloc_or_fail(size_t size) { +static inline void *malloc_or_fail(size_t size) +{ void *ptr = malloc(size); if (ptr == NULL) { - fprintf(stderr, "[UE] Failed to malloc %zu bytes", size); + fprintf(stderr, "Failed to malloc() %zu bytes: out of memory", size); exit(EXIT_FAILURE); } diff --git a/openair3/NAS/UE/EMM/IdleMode.c b/openair3/NAS/UE/EMM/IdleMode.c index 50a318355c..33e291931f 100644 --- a/openair3/NAS/UE/EMM/IdleMode.c +++ b/openair3/NAS/UE/EMM/IdleMode.c @@ -107,7 +107,7 @@ static IdleMode_callback_t _emm_indication_notify; ***************************************************************************/ void IdleMode_initialize(nas_user_t *user, IdleMode_callback_t cb) { - emm_plmn_list_t *emm_plmn_list = calloc_or_fail( sizeof(emm_plmn_list_t)); + emm_plmn_list_t *emm_plmn_list = calloc_or_fail(1, sizeof(emm_plmn_list_t)); user->emm_plmn_list = emm_plmn_list; /* Initialize the list of available PLMNs */ emm_plmn_list->n_plmns = 0; diff --git a/openair3/NAS/UE/EMM/emm_main.c b/openair3/NAS/UE/EMM/emm_main.c index 74676c8b36..ec5babc540 100644 --- a/openair3/NAS/UE/EMM/emm_main.c +++ b/openair3/NAS/UE/EMM/emm_main.c @@ -135,7 +135,7 @@ void _emm_detach_initialize(emm_detach_data_t *emm_detach) { void emm_main_initialize(nas_user_t *user, emm_indication_callback_t cb, const char *imei) { LOG_FUNC_IN; - user->emm_data = calloc_or_fail(sizeof(emm_data_t)); + user->emm_data = calloc_or_fail(1, sizeof(emm_data_t)); /* USIM validity indicator */ user->emm_data->usim_is_valid = false; /* The IMEI read from the UE's non-volatile memory */ @@ -433,19 +433,19 @@ void emm_main_initialize(nas_user_t *user, emm_indication_callback_t cb, const c /* * Initialize EMM timers */ - user->emm_data->emm_timers = calloc_or_fail(sizeof(emm_timers_t)); + user->emm_data->emm_timers = calloc_or_fail(1, sizeof(emm_timers_t)); _emm_timers_initialize(user->emm_data->emm_timers); /* * Initialize Internal data used for detach procedure */ - user->emm_data->emm_detach_data = calloc_or_fail(sizeof(emm_detach_data_t)); + user->emm_data->emm_detach_data = calloc_or_fail(1, sizeof(emm_detach_data_t)); _emm_detach_initialize(user->emm_data->emm_detach_data); /* * Initialize Internal data used for attach procedure */ - user->emm_data->emm_attach_data = calloc_or_fail(sizeof(emm_attach_data_t)); + user->emm_data->emm_attach_data = calloc_or_fail(1, sizeof(emm_attach_data_t)); _emm_attach_initialize(user->emm_data->emm_attach_data); /* diff --git a/openair3/NAS/UE/ESM/esm_ebr.c b/openair3/NAS/UE/ESM/esm_ebr.c index 4c6b56cec9..58cd4a4056 100644 --- a/openair3/NAS/UE/ESM/esm_ebr.c +++ b/openair3/NAS/UE/ESM/esm_ebr.c @@ -119,7 +119,7 @@ esm_ebr_data_t *esm_ebr_initialize(void) LOG_FUNC_IN; int i; - esm_ebr_data_t *esm_ebr_data = calloc_or_fail(sizeof(esm_ebr_data_t)); + esm_ebr_data_t *esm_ebr_data = calloc_or_fail(1, sizeof(esm_ebr_data_t)); esm_ebr_data->index = 0; diff --git a/openair3/NAS/UE/ESM/esm_main.c b/openair3/NAS/UE/ESM/esm_main.c index 895e463726..92b8075f24 100644 --- a/openair3/NAS/UE/ESM/esm_main.c +++ b/openair3/NAS/UE/ESM/esm_main.c @@ -79,7 +79,7 @@ void esm_main_initialize(nas_user_t *user, esm_indication_callback_t cb) int i; - esm_data_t *esm_data = calloc_or_fail(sizeof(esm_data_t)); + esm_data_t *esm_data = calloc_or_fail(1, sizeof(esm_data_t)); user->esm_data = esm_data; default_eps_bearer_context_data_t *default_eps_bearer_context = calloc(1, sizeof(default_eps_bearer_context_data_t)); diff --git a/openair3/NAS/UE/ESM/esm_pt.c b/openair3/NAS/UE/ESM/esm_pt.c index d9f593fb57..4c76850c94 100644 --- a/openair3/NAS/UE/ESM/esm_pt.c +++ b/openair3/NAS/UE/ESM/esm_pt.c @@ -88,7 +88,7 @@ static int _esm_pt_get_available_entry(esm_pt_data_t *esm_pt_data); esm_pt_data_t *esm_pt_initialize(void) { LOG_FUNC_IN; - esm_pt_data_t *esm_pt_data = calloc_or_fail(sizeof(esm_pt_data_t)); + esm_pt_data_t *esm_pt_data = calloc_or_fail(1, sizeof(esm_pt_data_t)); int i; esm_pt_data->index = 0; diff --git a/openair3/NAS/UE/nas_proc.c b/openair3/NAS/UE/nas_proc.c index 41230696a4..81e11c87ec 100644 --- a/openair3/NAS/UE/nas_proc.c +++ b/openair3/NAS/UE/nas_proc.c @@ -97,8 +97,8 @@ void nas_proc_initialize(nas_user_t *user, emm_indication_callback_t emm_cb, user->proc.rsrq = NAS_PROC_RSRQ_UNKNOWN; user->proc.rsrp = NAS_PROC_RSRP_UNKNOWN; - user->authentication_data = calloc_or_fail(sizeof(authentication_data_t)); - user->security_data = calloc_or_fail( sizeof(security_data_t)); + user->authentication_data = calloc_or_fail(1, sizeof(authentication_data_t)); + user->security_data = calloc_or_fail(1, sizeof(security_data_t)); /* Initialize the EMM procedure manager */ emm_main_initialize(user, emm_cb, imei); diff --git a/openair3/NAS/UE/nas_ue_task.c b/openair3/NAS/UE/nas_ue_task.c index 308d5b1f7f..fbd7a1365e 100644 --- a/openair3/NAS/UE/nas_ue_task.c +++ b/openair3/NAS/UE/nas_ue_task.c @@ -67,7 +67,7 @@ static bool nas_ue_process_events(nas_user_container_t *users, struct epoll_even // Initialize user api id and port number void nas_user_api_id_initialize(nas_user_t *user) { - user_api_id_t *user_api_id = calloc_or_fail(sizeof(user_api_id_t)); + user_api_id_t *user_api_id = calloc_or_fail(1, sizeof(user_api_id_t)); user->user_api_id = user_api_id; char *port = make_port_str_from_ueid(NAS_PARSER_DEFAULT_USER_PORT_NUMBER, user->ueid); if ( port == NULL ) { @@ -130,9 +130,9 @@ void *nas_ue_task(void *args_p) /* Initialize user interface (to exchange AT commands with user process) */ nas_user_api_id_initialize(user); /* allocate needed structures */ - user->user_at_commands = calloc_or_fail(sizeof(user_at_commands_t)); - user->at_response = calloc_or_fail(sizeof(at_response_t)); - user->lowerlayer_data = calloc_or_fail(sizeof(lowerlayer_data_t)); + user->user_at_commands = calloc_or_fail(1, sizeof(user_at_commands_t)); + user->at_response = calloc_or_fail(1, sizeof(at_response_t)); + user->lowerlayer_data = calloc_or_fail(1, sizeof(lowerlayer_data_t)); /* Initialize NAS user */ nas_user_initialize(user, &user_api_emm_callback, &user_api_esm_callback, FIRMWARE_VERSION); } @@ -170,9 +170,9 @@ void *nas_ue_task(void *args_p) /* Initialize user interface (to exchange AT commands with user process) */ nas_user_api_id_initialize(user); /* allocate needed structures */ - user->user_at_commands = calloc_or_fail(sizeof(user_at_commands_t)); - user->at_response = calloc_or_fail(sizeof(at_response_t)); - user->lowerlayer_data = calloc_or_fail(sizeof(lowerlayer_data_t)); + user->user_at_commands = calloc_or_fail(1, sizeof(user_at_commands_t)); + user->at_response = calloc_or_fail(1, sizeof(at_response_t)); + user->lowerlayer_data = calloc_or_fail(1, sizeof(lowerlayer_data_t)); /* Initialize NAS user */ nas_user_initialize(user, &user_api_emm_callback, &user_api_esm_callback, FIRMWARE_VERSION); user->ueid = 0; diff --git a/openair3/NAS/UE/nas_user.c b/openair3/NAS/UE/nas_user.c index ab32c216e5..fba70e1db4 100644 --- a/openair3/NAS/UE/nas_user.c +++ b/openair3/NAS/UE/nas_user.c @@ -154,7 +154,7 @@ void nas_user_initialize(nas_user_t *user, emm_indication_callback_t emm_cb, { LOG_FUNC_IN; - user->nas_user_nvdata = calloc_or_fail(sizeof(user_nvdata_t)); + user->nas_user_nvdata = calloc_or_fail(1, sizeof(user_nvdata_t)); /* Get UE data stored in the non-volatile memory device */ int rc = memory_read(user->user_nvdata_store, user->nas_user_nvdata, sizeof(user_nvdata_t)); @@ -163,7 +163,7 @@ void nas_user_initialize(nas_user_t *user, emm_indication_callback_t emm_cb, abort(); } - user->nas_user_context = calloc_or_fail(sizeof(nas_user_context_t)); + user->nas_user_context = calloc_or_fail(1, sizeof(nas_user_context_t)); _nas_user_context_initialize(user->nas_user_context, version); /* Initialize the internal NAS processing data */ From 2dc36ffcf7f1d5285eb45c37c5c6e658546aeabf Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Oct 2023 01:16:27 +0200 Subject: [PATCH 02/12] Initialize struct on stack Not initalizing this struct makes asn1c free the memory incorrectly, leading to a segfault. --- openair2/RRC/NR/nr_rrc_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 5eaaf7eeac..22cf5beeb4 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -224,7 +224,7 @@ static void config_csirs(const NR_ServingCellConfigCommon_t *servingcellconfigco csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList = calloc(1,sizeof(*csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList)); NR_NZP_CSI_RS_Resource_t *nzpcsi0 = calloc(1,sizeof(*nzpcsi0)); nzpcsi0->nzp_CSI_RS_ResourceId = id; - NR_CSI_RS_ResourceMapping_t resourceMapping; + NR_CSI_RS_ResourceMapping_t resourceMapping = {0}; switch (num_dl_antenna_ports) { case 1: resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2; From d4cc2c8597c4561b9571c88aa34686cbb44c968d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 23 Oct 2023 15:43:05 +0200 Subject: [PATCH 03/12] Deep-copy asn1c structures to prevent double free --- openair2/RRC/NR/nr_rrc_config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 22cf5beeb4..ce1749a85c 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -1280,8 +1280,8 @@ static void config_uplinkBWP(NR_BWP_Uplink_t *ubwp, struct NR_PUCCH_ConfigCommon *pucch_ConfigCommon = ubwp->bwp_Common->pucch_ConfigCommon->choice.setup; pucch_ConfigCommon->pucch_ResourceCommon = NULL; // for BWP != 0 as per 38.213 section 9.2.1 pucch_ConfigCommon->pucch_GroupHopping = scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_GroupHopping; - pucch_ConfigCommon->hoppingId = scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->hoppingId; - pucch_ConfigCommon->p0_nominal = scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->p0_nominal; + asn1cCallocOne(pucch_ConfigCommon->hoppingId, *scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->hoppingId); + asn1cCallocOne(pucch_ConfigCommon->p0_nominal, *scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->p0_nominal); if (!ubwp->bwp_Dedicated) { ubwp->bwp_Dedicated = calloc(1,sizeof(*ubwp->bwp_Dedicated)); From 38a6e92fdfe5f32652dcfac42ca260d8c4fba313 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 23 Oct 2023 17:50:20 +0200 Subject: [PATCH 04/12] Deep-copy genericParameters to prevent double-free --- openair2/RRC/NR/nr_rrc_config.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index ce1749a85c..3248d80a49 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -41,6 +41,17 @@ const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160}; +static NR_BWP_t clone_generic_parameters(const NR_BWP_t *gp) +{ + NR_BWP_t clone = {0}; + clone.locationAndBandwidth = gp->locationAndBandwidth; + clone.subcarrierSpacing = gp->subcarrierSpacing; + if (gp->cyclicPrefix) { + asn1cCallocOne(clone.cyclicPrefix, *gp->cyclicPrefix); + } + return clone; +} + static NR_SearchSpace_t *rrc_searchspace_config(bool is_common, int searchspaceid, int coresetid) { @@ -1811,7 +1822,7 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, c // servingCellConfigCommon asn1cCalloc(sib1->servingCellConfigCommon, ServCellCom); NR_BWP_DownlinkCommon_t *initialDownlinkBWP = &ServCellCom->downlinkConfigCommon.initialDownlinkBWP; - initialDownlinkBWP->genericParameters = scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; + initialDownlinkBWP->genericParameters = clone_generic_parameters(&scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters); const NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; for (int i = 0; i < frequencyInfoDL->frequencyBandList.list.count; i++) { @@ -1897,7 +1908,7 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, c } } - UL->initialUplinkBWP.genericParameters = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; + UL->initialUplinkBWP.genericParameters = clone_generic_parameters(&scc->uplinkConfigCommon->initialUplinkBWP->genericParameters); UL->initialUplinkBWP.rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon; UL->initialUplinkBWP.pusch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon; UL->initialUplinkBWP.pusch_ConfigCommon->choice.setup->groupHoppingEnabledTransformPrecoding = NULL; From d442e21f3c48471e7187d6d2618f27adfa5688f7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 23 Oct 2023 17:55:29 +0200 Subject: [PATCH 05/12] Deep-copy PUSCH&PUCCH_ConfigCommon to prevent double-free --- openair2/RRC/NR/nr_rrc_config.c | 41 ++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 3248d80a49..ef27dbac02 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -52,6 +52,40 @@ static NR_BWP_t clone_generic_parameters(const NR_BWP_t *gp) return clone; } +static NR_SetupRelease_PUSCH_ConfigCommon_t *clone_pusch_configcommon(const NR_SetupRelease_PUSCH_ConfigCommon_t *pcc) +{ + if (pcc == NULL || pcc->present == NR_SetupRelease_PUSCH_ConfigCommon_PR_NOTHING) + return NULL; + NR_SetupRelease_PUSCH_ConfigCommon_t *clone = calloc_or_fail(1, sizeof(*clone)); + clone->present = pcc->present; + if (clone->present == NR_SetupRelease_PUSCH_ConfigCommon_PR_release) + return clone; + + uint8_t buf[1024]; + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_PUSCH_ConfigCommon, NULL, pcc->choice.setup, buf, sizeof(buf)); + AssertFatal(enc_rval.encoded > 0 && enc_rval.encoded < sizeof(buf), "could not clone NR_PUSCH_ConfigCommon: problem while encoding\n"); + asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_PUSCH_ConfigCommon, (void **)&clone->choice.setup, buf, enc_rval.encoded, 0, 0); + AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed == enc_rval.encoded, "could not clone NR_PUSCH_ConfigCommon: problem while decoding\n"); + return clone; +} + +static NR_SetupRelease_PUCCH_ConfigCommon_t *clone_pucch_configcommon(const NR_SetupRelease_PUCCH_ConfigCommon_t *pcc) +{ + if (pcc == NULL || pcc->present == NR_SetupRelease_PUCCH_ConfigCommon_PR_NOTHING) + return NULL; + NR_SetupRelease_PUCCH_ConfigCommon_t *clone = calloc_or_fail(1, sizeof(*clone)); + clone->present = pcc->present; + if (clone->present == NR_SetupRelease_PUCCH_ConfigCommon_PR_release) + return clone; + + uint8_t buf[1024]; + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_PUCCH_ConfigCommon, NULL, pcc->choice.setup, buf, sizeof(buf)); + AssertFatal(enc_rval.encoded > 0 && enc_rval.encoded < sizeof(buf), "could not clone NR_PUCCH_ConfigCommon: problem while encoding\n"); + asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_PUCCH_ConfigCommon, (void **)&clone->choice.setup, buf, enc_rval.encoded, 0, 0); + AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed == enc_rval.encoded, "could not clone NR_PUCCH_ConfigCommon: problem while decoding\n"); + return clone; +} + static NR_SearchSpace_t *rrc_searchspace_config(bool is_common, int searchspaceid, int coresetid) { @@ -1284,7 +1318,7 @@ static void config_uplinkBWP(NR_BWP_Uplink_t *ubwp, int curr_bwp = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,MAX_BWP_SIZE); ubwp->bwp_Common->rach_ConfigCommon = is_SA ? NULL : scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon; - ubwp->bwp_Common->pusch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon; + ubwp->bwp_Common->pusch_ConfigCommon = clone_pusch_configcommon(scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon); ubwp->bwp_Common->pucch_ConfigCommon = CALLOC(1,sizeof(struct NR_SetupRelease_PUCCH_ConfigCommon)); ubwp->bwp_Common->pucch_ConfigCommon->present= NR_SetupRelease_PUCCH_ConfigCommon_PR_setup; ubwp->bwp_Common->pucch_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_PUCCH_ConfigCommon)); @@ -1910,10 +1944,11 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, c UL->initialUplinkBWP.genericParameters = clone_generic_parameters(&scc->uplinkConfigCommon->initialUplinkBWP->genericParameters); UL->initialUplinkBWP.rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon; - UL->initialUplinkBWP.pusch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon; + UL->initialUplinkBWP.pusch_ConfigCommon = clone_pusch_configcommon(scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon); + free(UL->initialUplinkBWP.pusch_ConfigCommon->choice.setup->groupHoppingEnabledTransformPrecoding); UL->initialUplinkBWP.pusch_ConfigCommon->choice.setup->groupHoppingEnabledTransformPrecoding = NULL; - UL->initialUplinkBWP.pucch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon; + UL->initialUplinkBWP.pucch_ConfigCommon = clone_pucch_configcommon(scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon); UL->timeAlignmentTimerCommon = NR_TimeAlignmentTimer_infinity; From 8062af94b57266d9e4110936622ac9d10815c7cc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 23 Oct 2023 19:29:23 +0200 Subject: [PATCH 06/12] Deep-copy RACH_ConfigCommont to prevent double-free --- openair2/RRC/NR/nr_rrc_config.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index ef27dbac02..91b4ffcc2a 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -52,6 +52,23 @@ static NR_BWP_t clone_generic_parameters(const NR_BWP_t *gp) return clone; } +static NR_SetupRelease_RACH_ConfigCommon_t *clone_rach_configcommon(const NR_SetupRelease_RACH_ConfigCommon_t *rcc) +{ + if (rcc == NULL || rcc->present == NR_SetupRelease_RACH_ConfigCommon_PR_NOTHING) + return NULL; + NR_SetupRelease_RACH_ConfigCommon_t *clone = calloc_or_fail(1, sizeof(*clone)); + clone->present = rcc->present; + if (clone->present == NR_SetupRelease_RACH_ConfigCommon_PR_release) + return clone; + + uint8_t buf[1024]; + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_RACH_ConfigCommon, NULL, rcc->choice.setup, buf, sizeof(buf)); + AssertFatal(enc_rval.encoded > 0 && enc_rval.encoded < sizeof(buf), "could not clone NR_RACH_ConfigCommon: problem while encoding\n"); + asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_RACH_ConfigCommon, (void **)&clone->choice.setup, buf, enc_rval.encoded, 0, 0); + AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed == enc_rval.encoded, "could not clone NR_RACH_ConfigCommon: problem while decoding\n"); + return clone; +} + static NR_SetupRelease_PUSCH_ConfigCommon_t *clone_pusch_configcommon(const NR_SetupRelease_PUSCH_ConfigCommon_t *pcc) { if (pcc == NULL || pcc->present == NR_SetupRelease_PUSCH_ConfigCommon_PR_NOTHING) @@ -1316,8 +1333,7 @@ static void config_uplinkBWP(NR_BWP_Uplink_t *ubwp, } int curr_bwp = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,MAX_BWP_SIZE); - - ubwp->bwp_Common->rach_ConfigCommon = is_SA ? NULL : scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon; + ubwp->bwp_Common->rach_ConfigCommon = is_SA ? NULL : clone_rach_configcommon(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon); ubwp->bwp_Common->pusch_ConfigCommon = clone_pusch_configcommon(scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon); ubwp->bwp_Common->pucch_ConfigCommon = CALLOC(1,sizeof(struct NR_SetupRelease_PUCCH_ConfigCommon)); ubwp->bwp_Common->pucch_ConfigCommon->present= NR_SetupRelease_PUCCH_ConfigCommon_PR_setup; @@ -1943,7 +1959,7 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, c } UL->initialUplinkBWP.genericParameters = clone_generic_parameters(&scc->uplinkConfigCommon->initialUplinkBWP->genericParameters); - UL->initialUplinkBWP.rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon; + UL->initialUplinkBWP.rach_ConfigCommon = clone_rach_configcommon(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon); UL->initialUplinkBWP.pusch_ConfigCommon = clone_pusch_configcommon(scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon); free(UL->initialUplinkBWP.pusch_ConfigCommon->choice.setup->groupHoppingEnabledTransformPrecoding); UL->initialUplinkBWP.pusch_ConfigCommon->choice.setup->groupHoppingEnabledTransformPrecoding = NULL; From d1740c9d8efcc1ba210020f509051fce31178444 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 23 Oct 2023 19:31:08 +0200 Subject: [PATCH 07/12] Deep-copy PDSCH_ConfigCommon to prevent double-free --- openair2/RRC/NR/nr_rrc_config.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 91b4ffcc2a..831ebd097d 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -103,6 +103,23 @@ static NR_SetupRelease_PUCCH_ConfigCommon_t *clone_pucch_configcommon(const NR_S return clone; } +static NR_SetupRelease_PDSCH_ConfigCommon_t *clone_pdsch_configcommon(const NR_SetupRelease_PDSCH_ConfigCommon_t *pcc) +{ + if (pcc == NULL || pcc->present == NR_SetupRelease_PDSCH_ConfigCommon_PR_NOTHING) + return NULL; + NR_SetupRelease_PDSCH_ConfigCommon_t *clone = calloc_or_fail(1, sizeof(*clone)); + clone->present = pcc->present; + if (clone->present == NR_SetupRelease_PDSCH_ConfigCommon_PR_release) + return clone; + + uint8_t buf[1024]; + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_PDSCH_ConfigCommon, NULL, pcc->choice.setup, buf, sizeof(buf)); + AssertFatal(enc_rval.encoded > 0 && enc_rval.encoded < sizeof(buf), "could not clone NR_PDSCH_ConfigCommon: problem while encoding\n"); + asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_PDSCH_ConfigCommon, (void **)&clone->choice.setup, buf, enc_rval.encoded, 0, 0); + AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed == enc_rval.encoded, "could not clone NR_PDSCH_ConfigCommon: problem while decoding\n"); + return clone; +} + static NR_SearchSpace_t *rrc_searchspace_config(bool is_common, int searchspaceid, int coresetid) { @@ -1918,7 +1935,7 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, c asn1cCallocOne(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->pagingSearchSpace, 2); asn1cCallocOne(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->ra_SearchSpace, 1); - initialDownlinkBWP->pdsch_ConfigCommon = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon; + initialDownlinkBWP->pdsch_ConfigCommon = clone_pdsch_configcommon(scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon); ServCellCom->downlinkConfigCommon.bcch_Config.modificationPeriodCoeff = NR_BCCH_Config__modificationPeriodCoeff_n2; ServCellCom->downlinkConfigCommon.pcch_Config.defaultPagingCycle = NR_PagingCycle_rf256; ServCellCom->downlinkConfigCommon.pcch_Config.nAndPagingFrameOffset.present = NR_PCCH_Config__nAndPagingFrameOffset_PR_quarterT; From 90bb405e0d0de3fee71e1d3d851f6419b34b28fe Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 24 Oct 2023 10:51:27 +0200 Subject: [PATCH 08/12] Deep-copy PDCCH ConfigCommon for SIB1 Until this commit, the SIB1's PDCCH_configCommon was set (via a pointer, i.e., an indirection) to the one of the ServingCellConfigCommon (SCC). Afterwards, the SIB1 code further populated this PDCCH configCommon, indirectly populating the one of the the SCC, on which code later depends. Not only did this create possibilities for double-frees (since freeing the memory of SIB1, then SCC would free the PDCCH configcommon twice), but also it makes it harder to track where certain structures are populated. Hence, this commit solves both issues: - The SCC is correctly populated on initialization of the SCC - The SIB1 makes a deep copy of the SCC' PDCCH configCommon This resolves the two issues above. --- openair2/GNB_APP/gnb_config.c | 22 +++++++++++++++ openair2/RRC/NR/nr_rrc_config.c | 48 ++++++++++++++++++++------------- openair2/RRC/NR/nr_rrc_config.h | 1 + 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index e190b21748..b2ae0039b7 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -970,6 +970,28 @@ static NR_ServingCellConfigCommon_t *get_scc_config(int minRXTXTIME) fix_scc(scc, ssb_bitmap); } nr_rrc_config_ul_tda(scc, minRXTXTIME); + + // the gNB uses the servingCellConfigCommon everywhere, even when it should use the servingCellConfigCommonSIB. + // previously (before this commit), the following fields were indirectly populated through get_SIB1_NR(). + // since this might lead to memory problems (e.g., double frees), it has been moved here. + // note that the "right solution" would be to not populate the servingCellConfigCommon here, and use + // an "abstraction struct" that contains the corresponding values, from which SCC/SIB1/... is generated. + NR_PDCCH_ConfigCommon_t *pcc = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup; + AssertFatal(pcc != NULL && pcc->commonSearchSpaceList == NULL, "memory leak\n"); + pcc->commonSearchSpaceList = calloc_or_fail(1, sizeof(*pcc->commonSearchSpaceList)); + + NR_SearchSpace_t *ss1 = rrc_searchspace_config(true, 1, 0); + asn1cSeqAdd(&pcc->commonSearchSpaceList->list, ss1); + NR_SearchSpace_t *ss2 = rrc_searchspace_config(true, 2, 0); + asn1cSeqAdd(&pcc->commonSearchSpaceList->list, ss2); + NR_SearchSpace_t *ss3 = rrc_searchspace_config(true, 3, 0); + asn1cSeqAdd(&pcc->commonSearchSpaceList->list, ss3); + + asn1cCallocOne(pcc->searchSpaceSIB1, 0); + asn1cCallocOne(pcc->ra_SearchSpace, 1); + asn1cCallocOne(pcc->pagingSearchSpace, 2); + asn1cCallocOne(pcc->searchSpaceOtherSystemInformation, 3); + return scc; } diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 831ebd097d..6c940fb21a 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -103,6 +103,23 @@ static NR_SetupRelease_PUCCH_ConfigCommon_t *clone_pucch_configcommon(const NR_S return clone; } +static NR_SetupRelease_PDCCH_ConfigCommon_t *clone_pdcch_configcommon(const NR_SetupRelease_PDCCH_ConfigCommon_t *pcc) +{ + if (pcc == NULL || pcc->present == NR_SetupRelease_PDCCH_ConfigCommon_PR_NOTHING) + return NULL; + NR_SetupRelease_PDCCH_ConfigCommon_t *clone = calloc(1, sizeof(*clone)); + clone->present = pcc->present; + if (clone->present == NR_SetupRelease_PDCCH_ConfigCommon_PR_release) + return clone; + + uint8_t buf[1024]; + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_PDCCH_ConfigCommon, NULL, pcc->choice.setup, buf, sizeof(buf)); + AssertFatal(enc_rval.encoded > 0 && enc_rval.encoded < sizeof(buf), "could not clone NR_PDCCH_ConfigCommon: problem while encoding\n"); + asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_PDCCH_ConfigCommon, (void **)&clone->choice.setup, buf, enc_rval.encoded, 0, 0); + AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed == enc_rval.encoded, "could not clone NR_PDCCH_ConfigCommon: problem while decoding\n"); + return clone; +} + static NR_SetupRelease_PDSCH_ConfigCommon_t *clone_pdsch_configcommon(const NR_SetupRelease_PDSCH_ConfigCommon_t *pcc) { if (pcc == NULL || pcc->present == NR_SetupRelease_PDSCH_ConfigCommon_PR_NOTHING) @@ -120,7 +137,7 @@ static NR_SetupRelease_PDSCH_ConfigCommon_t *clone_pdsch_configcommon(const NR_S return clone; } -static NR_SearchSpace_t *rrc_searchspace_config(bool is_common, int searchspaceid, int coresetid) +NR_SearchSpace_t *rrc_searchspace_config(bool is_common, int searchspaceid, int coresetid) { NR_SearchSpace_t *ss = calloc(1,sizeof(*ss)); @@ -1916,25 +1933,18 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, c frequencyInfoDL->scs_SpecificCarrierList.list.array[i]); } - initialDownlinkBWP->pdcch_ConfigCommon = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon; - initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList = - CALLOC(1, sizeof(struct NR_PDCCH_ConfigCommon__commonSearchSpaceList)); - AssertFatal(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList != NULL, "out of memory\n"); + initialDownlinkBWP->pdcch_ConfigCommon = clone_pdcch_configcommon(scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon); + AssertFatal(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList != NULL, + "expected commonSearchSpaceList to be populated through SCC\n"); + AssertFatal(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1 != NULL, + "expected searchSpaceSIB1 to be populated through SCC\n"); + AssertFatal(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->ra_SearchSpace != NULL, + "expected ra_SearchSpace to be populated through SCC\n"); + AssertFatal(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->pagingSearchSpace != NULL, + "expected pagingSearchSpace to be populated through SCC\n"); + AssertFatal(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation != NULL, + "expected searchSpaceOtherSystemInformation to be populated through SCC\n"); - NR_SearchSpace_t *ss1 = rrc_searchspace_config(true, 1, 0); - asn1cSeqAdd(&initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list, ss1); - - NR_SearchSpace_t *ss2 = rrc_searchspace_config(true, 2, 0); - asn1cSeqAdd(&initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list, ss2); - - NR_SearchSpace_t *ss3 = rrc_searchspace_config(true, 3, 0); - asn1cSeqAdd(&initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list, ss3); - - asn1cCallocOne(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1, 0); - asn1cCallocOne(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation, 3); - asn1cCallocOne(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->pagingSearchSpace, 2); - asn1cCallocOne(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->ra_SearchSpace, 1); - initialDownlinkBWP->pdsch_ConfigCommon = clone_pdsch_configcommon(scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon); ServCellCom->downlinkConfigCommon.bcch_Config.modificationPeriodCoeff = NR_BCCH_Config__modificationPeriodCoeff_n2; ServCellCom->downlinkConfigCommon.pcch_Config.defaultPagingCycle = NR_PagingCycle_rf256; diff --git a/openair2/RRC/NR/nr_rrc_config.h b/openair2/RRC/NR/nr_rrc_config.h index 802d57428c..1db2d4a2f1 100644 --- a/openair2/RRC/NR/nr_rrc_config.h +++ b/openair2/RRC/NR/nr_rrc_config.h @@ -43,6 +43,7 @@ void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsc NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, int curr_bwp); void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay); +NR_SearchSpace_t *rrc_searchspace_config(bool is_common, int searchspaceid, int coresetid); void prepare_sim_uecap(NR_UE_NR_Capability_t *cap, NR_ServingCellConfigCommon_t *scc, From dc88ca3b6d56ab16cd221dec6849464f7cedf479 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 24 Oct 2023 12:02:49 +0200 Subject: [PATCH 09/12] Read DMRS_UplinkConfig from BWP info when needed Before this commit, the DMRS_UplinkConfig was stored in a separate DMRS-related structure, although it is always referenced in the PUSCHConfig of the current UL BWP. Through certain code paths (e.g., retransmission), it could happen that an old DMRS_UplinkConfig was accessed that was freed (through new CellGroupConfig). In this commit, we always look up the DMRS_UplinkConfig in the current PUSCH config, which should always be up to date. --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 11 +++++++++-- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 ++ openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 - 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 1e5de41ab3..e76773961c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -586,6 +586,15 @@ bool nr_find_nb_rb(uint16_t Qm, return *tbs >= bytes && *nb_rb <= nb_rb_max; } +const NR_DMRS_UplinkConfig_t *get_DMRS_UplinkConfig(const NR_PUSCH_Config_t *pusch_Config, const NR_tda_info_t *tda_info) +{ + if (pusch_Config == NULL) + return NULL; + + return tda_info->mapping_type == typeA ? pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup + : pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; +} + NR_pusch_dmrs_t get_ul_dmrs_params(const NR_ServingCellConfigCommon_t *scc, const NR_UE_UL_BWP_t *ul_bwp, const NR_tda_info_t *tda_info, @@ -623,8 +632,6 @@ NR_pusch_dmrs_t get_ul_dmrs_params(const NR_ServingCellConfigCommon_t *scc, num_dmrs_symb += (dmrs.ul_dmrs_symb_pos >> i) & 1; dmrs.num_dmrs_symb = num_dmrs_symb; dmrs.N_PRB_DMRS = dmrs.num_dmrs_cdm_grps_no_data * (dmrs.dmrs_config_type == 0 ? 6 : 4); - - dmrs.NR_DMRS_UplinkConfig = NR_DMRS_UplinkConfig; return dmrs; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 2dc0bc89db..761bbf6535 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -2234,7 +2234,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, n /* FAPI: DMRS */ pusch_pdu->ul_dmrs_symb_pos = sched_pusch->dmrs_info.ul_dmrs_symb_pos; pusch_pdu->dmrs_config_type = sched_pusch->dmrs_info.dmrs_config_type; - const NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = sched_pusch->dmrs_info.NR_DMRS_UplinkConfig; + const NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = get_DMRS_UplinkConfig(current_BWP->pusch_Config, &sched_pusch->tda_info); if (pusch_pdu->transform_precoding) { // transform precoding disabled long *scramblingid=NULL; if (NR_DMRS_UplinkConfig && pusch_pdu->scid == 0) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index cc649a28f3..9f96a0d106 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -269,6 +269,8 @@ long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList, int time_domain_assignment, int mu); +const NR_DMRS_UplinkConfig_t *get_DMRS_UplinkConfig(const NR_PUSCH_Config_t *pusch_Config, const NR_tda_info_t *tda_info); + NR_pusch_dmrs_t get_ul_dmrs_params(const NR_ServingCellConfigCommon_t *scc, const NR_UE_UL_BWP_t *ul_bwp, const NR_tda_info_t *tda_info, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index d051d93528..c73c566374 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -378,7 +378,6 @@ typedef struct NR_pusch_dmrs { uint16_t ul_dmrs_symb_pos; uint8_t num_dmrs_cdm_grps_no_data; nfapi_nr_dmrs_type_e dmrs_config_type; - NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig; } NR_pusch_dmrs_t; typedef struct NR_sched_pusch { From 10a0a52604d1001e7ef97ea72de261b437f02beb Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 24 Oct 2023 12:31:47 +0200 Subject: [PATCH 10/12] Allocate second but same coreset to prevent double-free --- openair2/RRC/NR/nr_rrc_config.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 6c940fb21a..637914d2dc 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -1328,10 +1328,13 @@ static void config_downlinkBWP(NR_BWP_Downlink_t *bwp, bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList = calloc(1,sizeof(*bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList)); bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList = calloc(1,sizeof(*bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList)); - asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list, coreset); + // coreset2 is identical to coreset above, but reallocated to prevent double + // frees + NR_ControlResourceSet_t *coreset2 = get_coreset_config(bwp->bwp_Id, curr_bwp, ssb_bitmap); + asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list, coreset2); bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList = calloc(1,sizeof(*bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList)); - NR_SearchSpace_t *ss2 = rrc_searchspace_config(false, 10+bwp->bwp_Id, coreset->controlResourceSetId); + NR_SearchSpace_t *ss2 = rrc_searchspace_config(false, 10+bwp->bwp_Id, coreset2->controlResourceSetId); asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss2); bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToReleaseList = NULL; From 7317efea001258cfffcdf434616494ce72e8fb80 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 24 Oct 2023 14:36:05 +0200 Subject: [PATCH 11/12] Clone pusch_Config to prevent double free --- openair2/RRC/NR/nr_rrc_config.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 637914d2dc..5c3f44bd7e 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -137,6 +137,20 @@ static NR_SetupRelease_PDSCH_ConfigCommon_t *clone_pdsch_configcommon(const NR_S return clone; } +static NR_PUSCH_Config_t *clone_pusch_config(const NR_PUSCH_Config_t *pc) +{ + if (pc == NULL) + return NULL; + + uint8_t buf[1024]; + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_PUSCH_Config, NULL, pc, buf, sizeof(buf)); + AssertFatal(enc_rval.encoded > 0 && enc_rval.encoded < sizeof(buf), "could not clone NR_PUSCH_Config: problem while encoding\n"); + NR_PUSCH_Config_t *clone = NULL; + asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_PUSCH_Config, (void **)&clone, buf, enc_rval.encoded, 0, 0); + AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed == enc_rval.encoded, "could not clone NR_PUSCH_Config: problem while decoding\n"); + return clone; +} + NR_SearchSpace_t *rrc_searchspace_config(bool is_common, int searchspaceid, int coresetid) { @@ -1402,7 +1416,8 @@ static void config_uplinkBWP(NR_BWP_Uplink_t *ubwp, NR_PUSCH_Config_t *pusch_Config = NULL; if(servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList && bwp_loop < servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count) { - pusch_Config = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_loop]->bwp_Dedicated->pusch_Config->choice.setup; + pusch_Config = clone_pusch_config(servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_loop] + ->bwp_Dedicated->pusch_Config->choice.setup); } ubwp->bwp_Dedicated->pusch_Config = config_pusch(pusch_Config, scc, configuration->force_256qam_off ? NULL : uecap); @@ -2727,8 +2742,8 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC NR_PUSCH_Config_t *pusch_Config = NULL; if (servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList) { - pusch_Config = - servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup; + pusch_Config = clone_pusch_config( + servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup); } initialUplinkBWP->pusch_Config = config_pusch(pusch_Config, servingcellconfigcommon, uecap); From 60d867a978d167d17c59ec58fc70a36a4c4027a0 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Fri, 29 Sep 2023 16:05:34 +0100 Subject: [PATCH 12/12] Fix read servingCellConfigDedicated from config file --- openair2/GNB_APP/gnb_config.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index b2ae0039b7..c142462404 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -997,11 +997,13 @@ static NR_ServingCellConfigCommon_t *get_scc_config(int minRXTXTIME) static NR_ServingCellConfig_t *get_scd_config(void) { - char aprefix[MAX_OPTNAME_SIZE*2 + 8]; NR_ServingCellConfig_t *scd = calloc(1, sizeof(*scd)); prepare_scd(scd); paramdef_t SCDsParams[] = SCDPARAMS_DESC(scd); paramlist_def_t SCDsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, NULL, 0}; + + char aprefix[MAX_OPTNAME_SIZE * 2 + 8]; + snprintf(aprefix, sizeof(aprefix), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); config_getlist(&SCDsParamList, NULL, 0, aprefix); if (SCDsParamList.numelt > 0) { sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, 0);