dump_mac_stats(): avoid overflow
The call to snprintf() as was used is wrong: we use the return value to
advance output, but the man page says
> The functions snprintf() and vsnprintf() do not write more than size
> bytes (including the terminating null byte ('\0')). If the output was
> truncated due to this limit, then the return value is the number of
> characters (excluding the terminating null byte) which would have been
> written to the final string if enough space had been available.
> Thus, a return value of size or more means that the output was
> truncated.
Thus, output could go beyond end, and we get a stack overflow. Instead,
encapsulate the call to snprintf() checking this condition, and only
advancing output as intended, limiting to 0 if we are at the end of the
buffer. This avoids this error:
==964825==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7be799f51988 at pc 0x7fe7d66b0d39 bp 0x7be79b825ef0 sp 0x7be79b8256c0
WRITE of size 3 at 0x7be799f51988 thread T24
#0 0x7fe7d66b0d38 in vsnprintf (/lib64/libasan.so.8+0xb0d38) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
#1 0x7fe7d66b2d44 in snprintf (/lib64/libasan.so.8+0xb2d44) (BuildId: 10b8ccd49f75c21babf1d7abe51bb63589d8471f)
#2 0x0000008fe7c6 in dump_mac_stats /home/richie/w/refactor-dlsch/openair2/LAYER2/NR_MAC_gNB/main.c:183
#3 0x00000092071a in gNB_dlsch_ulsch_scheduler /home/richie/w/refactor-dlsch/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c:200
#4 0x0000008f8f78 in run_scheduler_monolithic /home/richie/w/refactor-dlsch/openair2/NR_PHY_INTERFACE/NR_IF_Module.c:399
This commit is contained in:
@@ -118,6 +118,19 @@ void clear_mac_stats(gNB_MAC_INST *gNB) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *st_append(char *start, const char *end, const char *format, ...)
|
||||||
|
{
|
||||||
|
size_t space = end - start;
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
size_t written = vsnprintf(start, space, format, args);
|
||||||
|
va_end(args);
|
||||||
|
if (written <= space)
|
||||||
|
return start + written;
|
||||||
|
else
|
||||||
|
return (char *)end;
|
||||||
|
}
|
||||||
|
|
||||||
size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset_rsrp)
|
size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset_rsrp)
|
||||||
{
|
{
|
||||||
const char *begin = output;
|
const char *begin = output;
|
||||||
@@ -133,39 +146,39 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
|
|||||||
const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0;
|
const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0;
|
||||||
const int avg_sinrx10 = stats->num_sinr_meas > 0 ? stats->cumul_sinrx10 / stats->num_sinr_meas : 0;
|
const int avg_sinrx10 = stats->num_sinr_meas > 0 ? stats->cumul_sinrx10 / stats->num_sinr_meas : 0;
|
||||||
|
|
||||||
output += snprintf(output, end - output, "UE RNTI %04x CU-UE-ID ", UE->rnti);
|
output = st_append(output, end, "UE RNTI %04x CU-UE-ID ", UE->rnti);
|
||||||
if (du_exists_f1_ue_data(UE->rnti)) {
|
if (du_exists_f1_ue_data(UE->rnti)) {
|
||||||
f1_ue_data_t ued = du_get_f1_ue_data(UE->rnti);
|
f1_ue_data_t ued = du_get_f1_ue_data(UE->rnti);
|
||||||
output += snprintf(output, end - output, "%d", ued.secondary_ue);
|
output = st_append(output, end, "%d", ued.secondary_ue);
|
||||||
} else {
|
} else {
|
||||||
output += snprintf(output, end - output, "(none)");
|
output = st_append(output, end, "(none)");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool in_sync = !sched_ctrl->ul_failure;
|
bool in_sync = !sched_ctrl->ul_failure;
|
||||||
output += snprintf(output,
|
output = st_append(output,
|
||||||
end - output,
|
end,
|
||||||
" %s PH %d dB PCMAX %d dBm",
|
" %s PH %d dB PCMAX %d dBm",
|
||||||
in_sync ? "in-sync" : "out-of-sync",
|
in_sync ? "in-sync" : "out-of-sync",
|
||||||
sched_ctrl->ph,
|
sched_ctrl->ph,
|
||||||
sched_ctrl->pcmax);
|
sched_ctrl->pcmax);
|
||||||
|
|
||||||
if (stats->num_rsrp_meas)
|
if (stats->num_rsrp_meas)
|
||||||
output += snprintf(output, end - output, ", average RSRP %d (%d meas)", avg_rsrp, stats->num_rsrp_meas);
|
output = st_append(output, end, ", average RSRP %d (%d meas)", avg_rsrp, stats->num_rsrp_meas);
|
||||||
|
|
||||||
if (stats->num_sinr_meas) {
|
if (stats->num_sinr_meas) {
|
||||||
output += snprintf(output,
|
output = st_append(output,
|
||||||
end - output,
|
end,
|
||||||
", average SINR %d.%d (%d meas)",
|
", average SINR %d.%d (%d meas)",
|
||||||
avg_sinrx10 / 10,
|
avg_sinrx10 / 10,
|
||||||
avg_sinrx10 % 10,
|
avg_sinrx10 % 10,
|
||||||
stats->num_sinr_meas);
|
stats->num_sinr_meas);
|
||||||
}
|
}
|
||||||
|
|
||||||
output += snprintf(output, end - output, "\n");
|
output = st_append(output, end, "\n");
|
||||||
|
|
||||||
if(sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.print_report)
|
if(sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.print_report)
|
||||||
output += snprintf(output,
|
output = st_append(output,
|
||||||
end - output,
|
end,
|
||||||
"UE %04x: CQI %d, RI %d, PMI (%d,%d)\n",
|
"UE %04x: CQI %d, RI %d, PMI (%d,%d)\n",
|
||||||
UE->rnti,
|
UE->rnti,
|
||||||
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb,
|
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb,
|
||||||
@@ -174,18 +187,18 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
|
|||||||
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.pmi_x2);
|
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.pmi_x2);
|
||||||
|
|
||||||
if (stats->srs_stats[0] != '\0') {
|
if (stats->srs_stats[0] != '\0') {
|
||||||
output += snprintf(output, end - output, "UE %04x: %s\n", UE->rnti, stats->srs_stats);
|
output = st_append(output, end, "UE %04x: %s\n", UE->rnti, stats->srs_stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
output += snprintf(output,
|
output = st_append(output,
|
||||||
end - output,
|
end,
|
||||||
"UE %04x: dlsch_rounds ", UE->rnti);
|
"UE %04x: dlsch_rounds ", UE->rnti);
|
||||||
output += snprintf(output, end - output, "%"PRIu64, stats->dl.rounds[0]);
|
output = st_append(output, end, "%"PRIu64, stats->dl.rounds[0]);
|
||||||
for (int i = 1; i < gNB->dl_bler.harq_round_max; i++)
|
for (int i = 1; i < gNB->dl_bler.harq_round_max; i++)
|
||||||
output += snprintf(output, end - output, "/%"PRIu64, stats->dl.rounds[i]);
|
output = st_append(output, end, "/%"PRIu64, stats->dl.rounds[i]);
|
||||||
|
|
||||||
output += snprintf(output,
|
output = st_append(output,
|
||||||
end - output,
|
end,
|
||||||
", dlsch_errors %"PRIu64", pucch0_DTX %d, BLER %.5f MCS (%d) %d CCE fail %d\n",
|
", dlsch_errors %"PRIu64", pucch0_DTX %d, BLER %.5f MCS (%d) %d CCE fail %d\n",
|
||||||
stats->dl.errors,
|
stats->dl.errors,
|
||||||
stats->pucch0_DTX,
|
stats->pucch0_DTX,
|
||||||
@@ -199,15 +212,15 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
|
|||||||
stats->num_sinr_meas = 0;
|
stats->num_sinr_meas = 0;
|
||||||
stats->cumul_sinrx10 = 0;
|
stats->cumul_sinrx10 = 0;
|
||||||
}
|
}
|
||||||
output += snprintf(output,
|
output = st_append(output,
|
||||||
end - output,
|
end,
|
||||||
"UE %04x: ulsch_rounds ", UE->rnti);
|
"UE %04x: ulsch_rounds ", UE->rnti);
|
||||||
output += snprintf(output, end - output, "%"PRIu64, stats->ul.rounds[0]);
|
output = st_append(output, end, "%"PRIu64, stats->ul.rounds[0]);
|
||||||
for (int i = 1; i < gNB->ul_bler.harq_round_max; i++)
|
for (int i = 1; i < gNB->ul_bler.harq_round_max; i++)
|
||||||
output += snprintf(output, end - output, "/%"PRIu64, stats->ul.rounds[i]);
|
output = st_append(output, end, "/%"PRIu64, stats->ul.rounds[i]);
|
||||||
|
|
||||||
output += snprintf(output,
|
output = st_append(output,
|
||||||
end - output,
|
end,
|
||||||
", ulsch_errors %"PRIu64", ulsch_DTX %d, BLER %.5f MCS (%d) %d (Qm %d deltaMCS %d dB) NPRB %d SNR %d.%d dB CCE fail %d\n",
|
", ulsch_errors %"PRIu64", ulsch_DTX %d, BLER %.5f MCS (%d) %d (Qm %d deltaMCS %d dB) NPRB %d SNR %d.%d dB CCE fail %d\n",
|
||||||
stats->ul.errors,
|
stats->ul.errors,
|
||||||
stats->ulsch_DTX,
|
stats->ulsch_DTX,
|
||||||
@@ -220,15 +233,15 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
|
|||||||
sched_ctrl->pusch_snrx10 / 10,
|
sched_ctrl->pusch_snrx10 / 10,
|
||||||
sched_ctrl->pusch_snrx10 % 10,
|
sched_ctrl->pusch_snrx10 % 10,
|
||||||
sched_ctrl->ul_cce_fail);
|
sched_ctrl->ul_cce_fail);
|
||||||
output += snprintf(output,
|
output = st_append(output,
|
||||||
end - output,
|
end,
|
||||||
"UE %04x: MAC: TX %14"PRIu64" RX %14"PRIu64" bytes\n",
|
"UE %04x: MAC: TX %14"PRIu64" RX %14"PRIu64" bytes\n",
|
||||||
UE->rnti, stats->dl.total_bytes, stats->ul.total_bytes);
|
UE->rnti, stats->dl.total_bytes, stats->ul.total_bytes);
|
||||||
|
|
||||||
for (int i = 0; i < seq_arr_size(&sched_ctrl->lc_config); i++) {
|
for (int i = 0; i < seq_arr_size(&sched_ctrl->lc_config); i++) {
|
||||||
const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, i);
|
const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, i);
|
||||||
output += snprintf(output,
|
output = st_append(output,
|
||||||
end - output,
|
end,
|
||||||
"UE %04x: LCID %d: TX %14"PRIu64" RX %14"PRIu64" bytes\n",
|
"UE %04x: LCID %d: TX %14"PRIu64" RX %14"PRIu64" bytes\n",
|
||||||
UE->rnti,
|
UE->rnti,
|
||||||
c->lcid,
|
c->lcid,
|
||||||
@@ -236,6 +249,7 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
|
|||||||
stats->ul.lc_bytes[c->lcid]);
|
stats->ul.lc_bytes[c->lcid]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DevAssert(output <= end);
|
||||||
return output - begin;
|
return output - begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user