Compare commits

...

3 Commits

Author SHA1 Message Date
francescomani
269955aa7c assertion in case sn_FieldLength is absent at setup 2026-01-27 11:47:35 +01:00
francescomani
89ba38bcb7 improve handling of integrityProtAlgorithm, including rejecting the scenario where it is not present 2026-01-27 09:45:48 +01:00
francescomani
3c5f3a9076 fix potential segfaults according to issue #1049 2026-01-26 17:43:35 +01:00
3 changed files with 86 additions and 66 deletions

View File

@@ -4690,7 +4690,7 @@ void compute_csi_bitlen(const NR_CSI_MeasConfig_t *csi_MeasConfig, nr_csi_report
NR_CSI_ResourceConfigId_t csi_ResourceConfigId;
NR_CSI_ResourceConfig_t *csi_resourceconfig;
if (!csi_MeasConfig->csi_ReportConfigToAddModList) {
if (!csi_MeasConfig || !csi_MeasConfig->csi_ReportConfigToAddModList) {
LOG_E(NR_MAC, "csi_ReportConfigToAddModList is NULL, not expected\n");
return;
}

View File

@@ -756,17 +756,17 @@ static void add_drb_am(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_B
case NR_RLC_Config_PR_am: {
struct NR_RLC_Config__am *am;
am = r->choice.am;
t_reassembly = decode_t_reassembly(am->dl_AM_RLC.t_Reassembly);
t_status_prohibit = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit);
t_poll_retransmit = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit);
poll_pdu = decode_poll_pdu(am->ul_AM_RLC.pollPDU);
poll_byte = decode_poll_byte(am->ul_AM_RLC.pollByte);
t_reassembly = decode_t_reassembly(am->dl_AM_RLC.t_Reassembly);
t_status_prohibit = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit);
t_poll_retransmit = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit);
poll_pdu = decode_poll_pdu(am->ul_AM_RLC.pollPDU);
poll_byte = decode_poll_byte(am->ul_AM_RLC.pollByte);
max_retx_threshold = decode_max_retx_threshold(am->ul_AM_RLC.maxRetxThreshold);
if (*am->dl_AM_RLC.sn_FieldLength != *am->ul_AM_RLC.sn_FieldLength) {
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
sn_field_length = decode_sn_field_length_am(*am->dl_AM_RLC.sn_FieldLength);
AssertFatal(am->dl_AM_RLC.sn_FieldLength
&& am->ul_AM_RLC.sn_FieldLength
&& *am->dl_AM_RLC.sn_FieldLength == *am->ul_AM_RLC.sn_FieldLength,
"sn_FieldLength mandatory present at setup and not handled if different between DL and UL\n");
sn_field_length = decode_sn_field_length_am(*am->dl_AM_RLC.sn_FieldLength);
break;
}
default:
@@ -817,10 +817,10 @@ static void add_drb_um(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_B
struct NR_RLC_Config__um_Bi_Directional *um;
um = r->choice.um_Bi_Directional;
t_reassembly = decode_t_reassembly(um->dl_UM_RLC.t_Reassembly);
if (*um->dl_UM_RLC.sn_FieldLength != *um->ul_UM_RLC.sn_FieldLength) {
LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
AssertFatal(um->dl_UM_RLC.sn_FieldLength
&& um->ul_UM_RLC.sn_FieldLength
&& *um->dl_UM_RLC.sn_FieldLength == *um->ul_UM_RLC.sn_FieldLength,
"sn_FieldLength mandatory present at setup and not handled if different between DL and UL\n");
sn_field_length = decode_sn_field_length_um(*um->dl_UM_RLC.sn_FieldLength);
break;
}

View File

@@ -271,7 +271,7 @@ static void nr_rrc_process_ntnconfig(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *S
// Check if Epochtime is sent or not
int diff_frames = eval_epoch_time(SI_info, ntncfg, frame, is_targetcell);
if (ntncfg->ntn_UlSyncValidityDuration_r17) { // ulsyncvalidity duration configured
if (ntncfg && ntncfg->ntn_UlSyncValidityDuration_r17) { // ulsyncvalidity duration configured
int val430_ms = 0, sib19_timer_ms = 0;
sib19_timer_ms = get_ntn_timervalues(SI_info, ntncfg, diff_frames, &val430_ms);
// T430 should be started only in connected mode.
@@ -757,7 +757,7 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, NR_Rad
nr_pdcp_entity_security_keys_and_algos_t security_up_parameters = {0};
if (ue_rrc->as_security_activated) {
if (radioBearerConfig->securityConfig != NULL) {
if (radioBearerConfig->securityConfig) {
// When the field is not included, continue to use the currently configured keyToUse
if (radioBearerConfig->securityConfig->keyToUse) {
AssertFatal(*radioBearerConfig->securityConfig->keyToUse == NR_SecurityConfig__keyToUse_master,
@@ -767,6 +767,11 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, NR_Rad
// When the field is not included, continue to use the currently configured security algorithm
if (radioBearerConfig->securityConfig->securityAlgorithmConfig) {
ue_rrc->cipheringAlgorithm = radioBearerConfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm;
if (!radioBearerConfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm) {
LOG_E(NR_RRC, "integrityProtAlgorithm to be released not handled, we remove AS security and declare RLF\n");
ue_rrc->as_security_activated = false;
handle_rlf_detection(ue_rrc);
}
ue_rrc->integrityProtAlgorithm = *radioBearerConfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm;
}
}
@@ -1238,15 +1243,19 @@ static void update_nr_measobj(NR_MeasObjectNR_t *source, NR_MeasObjectNR_t *targ
UPDATE_IE(target->ssbSubcarrierSpacing, source->ssbSubcarrierSpacing, NR_SubcarrierSpacing_t);
UPDATE_IE(target->smtc1, source->smtc1, NR_SSB_MTC_t);
if (source->smtc2) {
if (!target->smtc2)
target->smtc2 = calloc(1, sizeof(*target->smtc2));
target->smtc2->periodicity = source->smtc2->periodicity;
if (source->smtc2->pci_List)
UPDATE_IE(target->smtc2->pci_List, source->smtc2->pci_List, struct NR_SSB_MTC2__pci_List);
}
else
} else
asn1cFreeStruc(asn_DEF_NR_SSB_MTC2, target->smtc2);
UPDATE_IE(target->refFreqCSI_RS, source->refFreqCSI_RS, NR_ARFCN_ValueNR_t);
if (source->referenceSignalConfig.ssb_ConfigMobility)
if (source->referenceSignalConfig.ssb_ConfigMobility) {
if (!target->referenceSignalConfig.ssb_ConfigMobility)
target->referenceSignalConfig.ssb_ConfigMobility = calloc(1, sizeof(*target->referenceSignalConfig.ssb_ConfigMobility));
update_ssb_configmob(source->referenceSignalConfig.ssb_ConfigMobility, target->referenceSignalConfig.ssb_ConfigMobility);
}
UPDATE_IE(target->absThreshSS_BlocksConsolidation, source->absThreshSS_BlocksConsolidation, NR_ThresholdNR_t);
UPDATE_IE(target->absThreshCSI_RS_Consolidation, source->absThreshCSI_RS_Consolidation, NR_ThresholdNR_t);
UPDATE_IE(target->nrofSS_BlocksToAverage, source->nrofSS_BlocksToAverage, long);
@@ -1278,6 +1287,8 @@ static void update_nr_measobj(NR_MeasObjectNR_t *source, NR_MeasObjectNR_t *targ
ADDMOD_IE_FROMLIST(source->allowedCellsToAddModList, target->allowedCellsToAddModList, pci_RangeIndex, NR_PCI_RangeElement_t);
}
if (source->ext1) {
if (!target->ext1)
target->ext1 = calloc(1, sizeof(*target->ext1));
UPDATE_IE(target->ext1->freqBandIndicatorNR, source->ext1->freqBandIndicatorNR, NR_FreqBandIndicatorNR_t);
UPDATE_IE(target->ext1->measCycleSCell, source->ext1->measCycleSCell, long);
}
@@ -2277,6 +2288,39 @@ static int8_t nr_rrc_ue_decode_ccch(NR_UE_RRC_INST_t *rrc, const NRRrcMacCcchDat
return rval;
}
static void send_security_failure(NR_UE_RRC_INST_t *rrc, NR_RRC_TransactionIdentifier_t id)
{
/* - continue using the configuration used prior to the reception of the SecurityModeCommand message, i.e.
* neither apply integrity protection nor ciphering.
* - submit the SecurityModeFailure message to lower layers for transmission, upon which the procedure ends.
*/
NR_UL_DCCH_Message_t ul_dcch_msg = {0};
ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1;
asn1cCalloc(ul_dcch_msg.message.choice.c1, c1);
c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeFailure;
asn1cCalloc(c1->choice.securityModeFailure, modeFailure);
modeFailure->rrc_TransactionIdentifier = id;
modeFailure->criticalExtensions.present = NR_SecurityModeFailure__criticalExtensions_PR_securityModeFailure;
asn1cCalloc(modeFailure->criticalExtensions.choice.securityModeFailure, ext);
ext->nonCriticalExtension = NULL;
uint8_t buffer[200];
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, sizeof(buffer));
AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded);
if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_UL_DCCH_Message, &ul_dcch_msg);
/* disable both ciphering and integrity */
nr_pdcp_entity_security_keys_and_algos_t null_security_parameters = {0};
for (int i = 1; i < NR_NUM_SRB; i++) {
if (rrc->Srb[i] == RB_ESTABLISHED)
nr_pdcp_config_set_security(rrc->ue_id, i, true, &null_security_parameters);
}
int srb_id = 1; // SecurityModeFailure in SRB1
nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL);
}
static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc,
NR_SecurityModeCommand_t *const securityModeCommand,
int srb_id,
@@ -2306,19 +2350,25 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc,
}
ue_rrc->cipheringAlgorithm = securityConfigSMC->securityAlgorithmConfig.cipheringAlgorithm;
ue_rrc->integrityProtAlgorithm = 0;
if (securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm != NULL) {
switch (*securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm) {
case NR_IntegrityProtAlgorithm_nia0:
case NR_IntegrityProtAlgorithm_nia1:
case NR_IntegrityProtAlgorithm_nia2:
LOG_I(NR_RRC, "Integrity protection algorithm is set to nia%ld\n", *securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm);
break;
default:
AssertFatal(0, "Integrity algorithm not known/supported\n");
}
ue_rrc->integrityProtAlgorithm = *securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm;
if (!securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm) {
LOG_E(NR_RRC, "received NULL integrityProtAlgorithm, can't send SecurityModeComplete, reply with SecurityModeFailure\n");
send_security_failure(ue_rrc, securityModeCommand->rrc_TransactionIdentifier);
return;
}
switch (*securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm) {
case NR_IntegrityProtAlgorithm_nia0:
case NR_IntegrityProtAlgorithm_nia1:
case NR_IntegrityProtAlgorithm_nia2:
LOG_I(NR_RRC,
"Integrity protection algorithm is set to nia%ld\n",
*securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm);
break;
default:
LOG_E(NR_RRC, "Integrity algorithm not known/supported, reply with SecurityModeFailure\n");
send_security_failure(ue_rrc, securityModeCommand->rrc_TransactionIdentifier);
return;
}
ue_rrc->integrityProtAlgorithm = *securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm;
nr_pdcp_entity_security_keys_and_algos_t security_parameters;
nr_derive_key(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, security_parameters.ciphering_key);
@@ -2335,48 +2385,18 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc,
nr_pdcp_config_set_security(ue_rrc->ue_id, i, true, &security_parameters);
}
NR_UL_DCCH_Message_t ul_dcch_msg = {0};
ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1;
asn1cCalloc(ul_dcch_msg.message.choice.c1, c1);
// the SecurityModeCommand message needs to pass the integrity protection check
// for the UE to declare AS security to be activated
bool integrity_pass = nr_pdcp_check_integrity_srb(ue_rrc->ue_id, srb_id, msg, msg_size, msg_integrity);
if (!integrity_pass) {
/* - continue using the configuration used prior to the reception of the SecurityModeCommand message, i.e.
* neither apply integrity protection nor ciphering.
* - submit the SecurityModeFailure message to lower layers for transmission, upon which the procedure ends.
*/
LOG_E(NR_RRC, "integrity of SecurityModeCommand failed, reply with SecurityModeFailure\n");
c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeFailure;
asn1cCalloc(c1->choice.securityModeFailure, modeFailure);
modeFailure->rrc_TransactionIdentifier = securityModeCommand->rrc_TransactionIdentifier;
modeFailure->criticalExtensions.present = NR_SecurityModeFailure__criticalExtensions_PR_securityModeFailure;
asn1cCalloc(modeFailure->criticalExtensions.choice.securityModeFailure, ext);
ext->nonCriticalExtension = NULL;
uint8_t buffer[200];
asn_enc_rval_t enc_rval =
uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, sizeof(buffer));
AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded);
if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_UL_DCCH_Message, &ul_dcch_msg);
/* disable both ciphering and integrity */
nr_pdcp_entity_security_keys_and_algos_t null_security_parameters = {0};
for (int i = 1; i < NR_NUM_SRB; i++) {
if (ue_rrc->Srb[i] == RB_ESTABLISHED)
nr_pdcp_config_set_security(ue_rrc->ue_id, i, true, &null_security_parameters);
}
srb_id = 1; // SecurityModeFailure in SRB1
nr_pdcp_data_req_srb(ue_rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL);
send_security_failure(ue_rrc, securityModeCommand->rrc_TransactionIdentifier);
return;
}
NR_UL_DCCH_Message_t ul_dcch_msg = {0};
ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1;
asn1cCalloc(ul_dcch_msg.message.choice.c1, c1);
/* integrity passed, send SecurityModeComplete */
c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete;