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)
|
||||
{
|
||||
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_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)) {
|
||||
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 {
|
||||
output += snprintf(output, end - output, "(none)");
|
||||
output = st_append(output, end, "(none)");
|
||||
}
|
||||
|
||||
bool in_sync = !sched_ctrl->ul_failure;
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
output = st_append(output,
|
||||
end,
|
||||
" %s PH %d dB PCMAX %d dBm",
|
||||
in_sync ? "in-sync" : "out-of-sync",
|
||||
sched_ctrl->ph,
|
||||
sched_ctrl->pcmax);
|
||||
|
||||
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) {
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
output = st_append(output,
|
||||
end,
|
||||
", average SINR %d.%d (%d meas)",
|
||||
avg_sinrx10 / 10,
|
||||
avg_sinrx10 % 10,
|
||||
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)
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
output = st_append(output,
|
||||
end,
|
||||
"UE %04x: CQI %d, RI %d, PMI (%d,%d)\n",
|
||||
UE->rnti,
|
||||
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);
|
||||
|
||||
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,
|
||||
end - output,
|
||||
output = st_append(output,
|
||||
end,
|
||||
"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++)
|
||||
output += snprintf(output, end - output, "/%"PRIu64, stats->dl.rounds[i]);
|
||||
output = st_append(output, end, "/%"PRIu64, stats->dl.rounds[i]);
|
||||
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
output = st_append(output,
|
||||
end,
|
||||
", dlsch_errors %"PRIu64", pucch0_DTX %d, BLER %.5f MCS (%d) %d CCE fail %d\n",
|
||||
stats->dl.errors,
|
||||
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->cumul_sinrx10 = 0;
|
||||
}
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
output = st_append(output,
|
||||
end,
|
||||
"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++)
|
||||
output += snprintf(output, end - output, "/%"PRIu64, stats->ul.rounds[i]);
|
||||
output = st_append(output, end, "/%"PRIu64, stats->ul.rounds[i]);
|
||||
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
output = st_append(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",
|
||||
stats->ul.errors,
|
||||
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->ul_cce_fail);
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
output = st_append(output,
|
||||
end,
|
||||
"UE %04x: MAC: TX %14"PRIu64" RX %14"PRIu64" bytes\n",
|
||||
UE->rnti, stats->dl.total_bytes, stats->ul.total_bytes);
|
||||
|
||||
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);
|
||||
output += snprintf(output,
|
||||
end - output,
|
||||
output = st_append(output,
|
||||
end,
|
||||
"UE %04x: LCID %d: TX %14"PRIu64" RX %14"PRIu64" bytes\n",
|
||||
UE->rnti,
|
||||
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]);
|
||||
}
|
||||
}
|
||||
DevAssert(output <= end);
|
||||
return output - begin;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user