Bug #21569
open[armv7, musl] SIGBUS in ibf_load_object_float due to unaligned VFP double load when reading IBF
Description
Environment:
CPU: ARMv7-A (NVIDIA Tegra 2), VFPv3-D16, no NEON
OS/libc: Linux, musl (ld-musl-armhf.so.1)
Compiler: GCC 14.3.0
Ruby: 3.3.8 (built from source via Gentoo ebuild)
CFLAGS actually used by system: "-Os -pipe -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard"
During make install (or Gentoo’s ebuild install phase) Ruby runs:
./miniruby -I./lib -I. -I.ext/common ./tool/runruby.rb --extout=.ext -- \
--disable-gems -r./armv7a-linux-musleabihf-fake ./tool/rbinstall.rb \
--make=make --dest-dir="$D" --extout=.ext --ext-build-dir=./ext \
--mflags="-j1" --make-flags=" V=1" --gnumake --install=all --exclude=doc
This reliably triggers a SIGBUS on armv7 hard-float.
Observed crash:
Thread "ruby33" received signal SIGBUS (Bus error).
#0 ibf_load_object_float () from libruby33.so.3.3
(gdb) bt
#0 ibf_load_object_float
#1 ibf_load_object
#2 rb_ibf_load_iseq_complete
#3 ibf_load_iseq
#4 ...
(gdb) info reg
r0 = 0xb6f508b6 (not 8-byte aligned)
pc = 0xb6cacf78 <ibf_load_object_float+32>
(gdb) x/6i $pc-8
...
0xb6cacf74: vldr d0, [r0] <-- VFP double load from unaligned addr → SIGBUS
Root cause
In compile.c:
static VALUE
ibf_load_object_float(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
{
const double *dblp = IBF_OBJBODY(double, offset);
return DBL2NUM(*dblp);
}
IBF_OBJBODY(double, ...) may return an unaligned pointer. On ARMv7, VFP vldr with an unaligned double address raises SIGBUS (no kernel fixup). Hence the crash while loading IBF.
Proposed fix
Read into an aligned local with memcpy:
--- a/compile.c
+++ b/compile.c
@@ -12921,10 +12921,12 @@ static VALUE
ibf_load_object_float(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
{
- const double *dblp = IBF_OBJBODY(double, offset);
- return DBL2NUM(*dblp);
+ /* IBF buffer may be unaligned on some platforms. On ARMv7, a VFP
+ * double load from an unaligned address causes SIGBUS. */
+ double d;
+ memcpy(&d, IBF_OBJBODY(void, offset), sizeof(d));
+ return DBL2NUM(d);
}
Notes:
The issue reproduces consistently on Tegra2 (armv7a, vfpv3-d16, no NEON) with musl, but (IMO) conceptually applies to any strict-alignment ARMv7 platform.
A similar audit may be required for other IBF loaders reading 8-byte types.
Please review and merge the fix (or implement an equivalent alignment-safe read for IBF floats).
I can test any proposed patch on this hardware.
Files