[ruby-core:123209] [Ruby Bug#21569] [armv7, musl] SIGBUS in ibf_load_object_float due to unaligned VFP double load when reading IBF

Issue #21569 has been reported by amacxz (Aleksey Maximov). ---------------------------------------- Bug #21569: [armv7, musl] SIGBUS in ibf_load_object_float due to unaligned VFP double load when reading IBF https://bugs.ruby-lang.org/issues/21569 * Author: amacxz (Aleksey Maximov) * Status: Open * ruby -v: ruby 3.3.8 (2025-04-09 revision b200bad6cd) [armv7a-linux-musleabihf] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- 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: ``` shell ./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: ``` 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. -- https://bugs.ruby-lang.org/

Issue #21569 has been updated by nobu (Nobuyoshi Nakada). Thank you for the report. amacxz (Aleksey Maximov) wrote:
``` + memcpy(&d, IBF_OBJBODY(void, offset), sizeof(d)); ```
I think `void` should be `double` since `IBF_OBJBODY` won't work on `void`. At least the fallback definition, `offsetof(struct { char _; T t; }, t)`, is invalid where `T` is `void`. ---------------------------------------- Bug #21569: [armv7, musl] SIGBUS in ibf_load_object_float due to unaligned VFP double load when reading IBF https://bugs.ruby-lang.org/issues/21569#change-114549 * Author: amacxz (Aleksey Maximov) * Status: Open * ruby -v: ruby 3.3.8 (2025-04-09 revision b200bad6cd) [armv7a-linux-musleabihf] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- 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: ``` shell ./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: ``` 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-------------------------------- compile_and_debug_log.txt (31.3 KB) -- https://bugs.ruby-lang.org/

Issue #21569 has been updated by amacxz (Aleksey Maximov). hmmm Good catch — you’re right that IBF_OBJBODY(void,) is invalid with the fallback definition. I’ve updated the patch. I’ll test it today and report back. ``` --- 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); + const double *dblp = IBF_OBJBODY(double, offset); + /* IBF buffer may be unaligned; loading a double directly (VFP vldr) + * from an unaligned address causes SIGBUS on armv7. */ + double d; + memcpy(&d, dblp, sizeof d); + return DBL2NUM(d); } ``` ---------------------------------------- Bug #21569: [armv7, musl] SIGBUS in ibf_load_object_float due to unaligned VFP double load when reading IBF https://bugs.ruby-lang.org/issues/21569#change-114560 * Author: amacxz (Aleksey Maximov) * Status: Open * ruby -v: ruby 3.3.8 (2025-04-09 revision b200bad6cd) [armv7a-linux-musleabihf] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- 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: ``` shell ./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: ``` 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-------------------------------- compile_and_debug_log.txt (31.3 KB) -- https://bugs.ruby-lang.org/

Issue #21569 has been updated by alanwu (Alan Wu).
`+ const double *dblp = IBF_OBJBODY(double, offset);`
This should probably be `const void *dblp = ...`. [Merely creating an unaligned pointer triggers undefined behavior](https://port70.net/~nsz/c/c99/n1256.html#6.3.2.3p7). ---------------------------------------- Bug #21569: [armv7, musl] SIGBUS in ibf_load_object_float due to unaligned VFP double load when reading IBF https://bugs.ruby-lang.org/issues/21569#change-114561 * Author: amacxz (Aleksey Maximov) * Status: Open * ruby -v: ruby 3.3.8 (2025-04-09 revision b200bad6cd) [armv7a-linux-musleabihf] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- 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: ``` shell ./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: ``` 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-------------------------------- compile_and_debug_log.txt (31.3 KB) -- https://bugs.ruby-lang.org/

Issue #21569 has been updated by nobu (Nobuyoshi Nakada). Simply it can be: ```c memcpy(&d, IBF_OBJBODY(double, offset), sizeof(d)); ``` amacxz: Would you send PR at github, or post the formatted-patch? Otherwise we can just add "patched by" comment to the commit log. ---------------------------------------- Bug #21569: [armv7, musl] SIGBUS in ibf_load_object_float due to unaligned VFP double load when reading IBF https://bugs.ruby-lang.org/issues/21569#change-114583 * Author: amacxz (Aleksey Maximov) * Status: Open * ruby -v: ruby 3.3.8 (2025-04-09 revision b200bad6cd) [armv7a-linux-musleabihf] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- 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: ``` shell ./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: ``` 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-------------------------------- compile_and_debug_log.txt (31.3 KB) -- https://bugs.ruby-lang.org/

Issue #21569 has been updated by amacxz (Aleksey Maximov). File 030-ibf-fix-unaligned-float-load-on-armv7.patch added Successfully compiled on ARMv7 with this patch (right now); no crash occurred during the project build. ruby 3.3.8 (2025-04-09 revision b200bad6cd) [armv7a-linux-musleabihf] Adding a ‘Patched-by: Aleksey Maximov <amaxcz@gmail.com>’ tag will be perfectly sufficient. Thanks for the help. :) ---------------------------------------- Bug #21569: [armv7, musl] SIGBUS in ibf_load_object_float due to unaligned VFP double load when reading IBF https://bugs.ruby-lang.org/issues/21569#change-114584 * Author: amacxz (Aleksey Maximov) * Status: Open * ruby -v: ruby 3.3.8 (2025-04-09 revision b200bad6cd) [armv7a-linux-musleabihf] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- 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: ``` shell ./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: ``` 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-------------------------------- compile_and_debug_log.txt (31.3 KB) 030-ibf-fix-unaligned-float-load-on-armv7.patch (644 Bytes) -- https://bugs.ruby-lang.org/
participants (3)
-
alanwu (Alan Wu)
-
amacxz (Aleksey Maximov)
-
nobu (Nobuyoshi Nakada)