lib: sbi: clamp sbi_ecall_get_extensions_str buffer offset

sbi_ecall_get_extensions_str() advanced offset by the nominal extension
name length without checking remaining capacity. When the caller buffer
was smaller than the concatenated extension list, offset could pass
exts_str_size, so (exts_str_size - offset) became negative and was
passed to sbi_snprintf() as a large u32, and the trailing NUL write
could step past the caller buffer.

The helper can write beyond a caller-provided destination when the
registered extension list exceeds the supplied capacity.

Mirror the guard already used by sbi_hart_get_extensions_str(): stop
appending when the next name would not fit. Add an SBIUNIT regression
that registers several extensions into a 16-byte buffer with a redzone
and verifies no out-of-bounds write.

Closes: https://github.com/riscv-software-src/opensbi/issues/416
Signed-off-by: Yudistira Putra <pyudistira519@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260719101125.190314-1-pyudistira519@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
Yudistira Putra
2026-08-31 18:08:50 +05:30
committed by Anup Patel
parent 4e79fd7de5
commit f95648d395
2 changed files with 61 additions and 0 deletions
+2
View File
@@ -66,6 +66,8 @@ void sbi_ecall_get_extensions_str(char *exts_str, int exts_str_size, bool experi
sbi_list_for_each_entry(t, &ecall_exts_list, head) {
if (experimental != t->experimental)
continue;
if (offset + sbi_strlen(t->name) + 1 > exts_str_size)
break;
sbi_snprintf(exts_str + offset, exts_str_size - offset,
"%s,", t->name);
offset = offset + sbi_strlen(t->name) + 1;