On Tue, Aug 01, 2023 at 01:43:36PM +0200, p...@delphinusdns.org wrote: > >Synopsis: non-terminated strings buffer in riscv64/cpu.c > >Category: kernel > >Environment: > System : OpenBSD 7.3 > Details : OpenBSD 7.3-current (GENERIC.MP) #376: Thu Jul 13 > 03:59:40 MDT 2023 > > dera...@riscv64.openbsd.org:/usr/src/sys/arch/riscv64/compile/GENERIC.MP > > Architecture: OpenBSD.riscv64 > Machine : riscv64 > >Description: > The cpu detect output is not NUL terminated, this causes *puke* to be > displayed on serial terminals. > >How-To-Repeat: > Using Qemu for riscv64 arch. > > from a eeprom -p | grep isa output: > > riscv,isa: > 'rv64imafdch_zicsr_zifencei_zihintpause_zba_zbb_zbc_zbs_sstc' > riscv,isa: > 'rv64imafdch_zicsr_zifencei_zihintpause_zba_zbb_zbc_zbs_sstc' > > I counted this as 60 bytes long. > >Fix: > > There is two approaches. One is to explicitly NUL terminate the 32 byte > buffer or make it bigger. I give an untested patch of the latter. > > Index: cpu.c > =================================================================== > RCS file: /cvs/src/sys/arch/riscv64/riscv64/cpu.c,v > retrieving revision 1.14 > diff -u -p -u -r1.14 cpu.c > --- cpu.c 15 Jun 2023 22:18:08 -0000 1.14 > +++ cpu.c 1 Aug 2023 11:35:28 -0000 > @@ -87,7 +87,7 @@ int cpu_errata_sifive_cip_1200; > void > cpu_identify(struct cpu_info *ci) > { > - char isa[32]; > + char isa[64]; > uint64_t marchid, mimpid; > uint32_t mvendorid; > const char *vendor_name = NULL; > >
[tying in tech@] This wasn't effective I just saw. On another QEMU host the cpu ISA string is larger than 80 characters. So I've made another patch. With this patch it looks like so: oceans$ dmesg|grep cpu cpu0 at mainbus0: vendor 0 arch 0 imp 0 rv64imafdch Zicbom Zicboz Zicsr Zifencei Zihintpause Zawrs Zfa Zca Zcd Zba Zbb Zbc Zbs Sstc Svadu intc0 at cpu0 cpu1 at mainbus0: vendor 0 arch 0 imp 0 rv64imafdch Zicbom Zicboz Zicsr Zifencei Zihintpause Zawrs Zfa Zca Zcd Zba Zbb Zbc Zbs Sstc Svadu oceans# grep zicboz /root/eeprom-p.out riscv,isa: 'rv64imafdch_zicbom_zicboz_zicsr_zifencei_zihintpause_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_sstc_svadu' riscv,isa: 'rv64imafdch_zicbom_zicboz_zicsr_zifencei_zihintpause_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_sstc_svadu' This is in convention with the cpu.c found in qemu: https://gitlab.com/qemu-project/qemu/-/blob/master/target/riscv/cpu.c lines 64 through 84 is the description of it. While I have no OpenBSD/riscv64 on true hardware it works on QEMU, and I googled for a dmesg online and the Hifive Unmatched should work as well. patch follows: Index: cpu.c =================================================================== RCS file: /cvs/src/sys/arch/riscv64/riscv64/cpu.c,v retrieving revision 1.14 diff -u -p -u -r1.14 cpu.c --- cpu.c 15 Jun 2023 22:18:08 -0000 1.14 +++ cpu.c 4 Aug 2023 11:15:16 -0000 @@ -84,15 +84,19 @@ struct cfdriver cpu_cd = { int cpu_errata_sifive_cip_1200; + void cpu_identify(struct cpu_info *ci) { - char isa[32]; + char isa[255]; + char szx_ext[255]; /* S, Z and X extension buffer */ + char *extensions = "imafdqlcbkjtpvh"; uint64_t marchid, mimpid; uint32_t mvendorid; const char *vendor_name = NULL; const char *arch_name = NULL; struct arch *archlist = cpu_arch_none; + char *p, *pe, *end; int i, len; mvendorid = sbi_get_mvendorid(); @@ -126,8 +130,70 @@ cpu_identify(struct cpu_info *ci) len = OF_getprop(ci->ci_node, "riscv,isa", isa, sizeof(isa)); if (len != -1) { + /* terminate it, it could be non-terminated */ + isa[sizeof(isa) - 1] = '\0'; + + /* PARSE the IMAFDQ... extensions */ + pe = extensions; + if ((p = strchr(isa, 'i')) != NULL || + (p = strchr(isa, 'I')) != NULL) { + for (; *pe != '\0'; pe++) { + if (((*p)|0x20) == *pe) { + if (p[1]) { + p++; + i++; + } else + break; + } + /* + * we've hit an underscore what follows + * may be an S or Z extension + */ + if (*p == '_') + break; + } + + szx_ext[0] = '\0'; + if (*p == '_') { + *p++ = '\0'; + for (; *p ;) { + end = strchr(p, '_'); + if (end != NULL) + *end++ = '\0'; + + switch (*p) { + case 'Z': + case 'z': + strlcat(szx_ext, "Z", sizeof(szx_ext)); + break; + case 'S': + case 's': + strlcat(szx_ext, "S", sizeof(szx_ext)); + break; + case 'X': + case 'x': + default: + strlcat(szx_ext, "?", sizeof(szx_ext)); + break; + } + p++; + i++; + strlcat(szx_ext, p, sizeof(szx_ext)); + if (end) { + strlcat(szx_ext, " ", sizeof(szx_ext)); + p = end; + } else + break; + } + } else + *p = '\0'; + } + printf(" %s", isa); strlcpy(cpu_model, isa, sizeof(cpu_model)); + + printf(" %s", szx_ext); + } printf("\n"); Best Regards, -peter