gpgme
gpgme copied to clipboard
Segmentation fault on x86_64-unknown-linux-musl
Creating a context segfaults when compiled on this target. I made a minimal repro to make sure it wasn't something else. Commenting the first line of main results in a binary that prints "Made it.", so the setup is sufficient to produce working binaries.
code/src/main.rs
use gpgme::{Context, Protocol};
pub fn main() {
let _ = Context::from_protocol(Protocol::OpenPgp)
.expect("Context::from_protocol() returned error");
print!("Made it.")
}
code/Cargo.toml
[package]
name = "repro"
version = "0.1.0"
edition = "2021"
[dependencies]
gpgme = { version = "0.10" }
Containerfile
FROM docker.io/rust:alpine
RUN apk add --no-cache musl-dev gpgme-dev
ADD code /usr/local/src
WORKDIR /usr/local/src
RUN cargo build
Console log:
$ podman build . --tag=repro && podman run --rm -it repro
STEP 1/5: FROM docker.io/rust:alpine
Trying to pull docker.io/library/rust:alpine...
Getting image source signatures
Copying blob 97518928ae5f done
Copying blob a95f12a5672f done
Copying blob 8087f14819d9 done
Copying config 9a5be7281d done
Writing manifest to image destination
Storing signatures
STEP 2/5: RUN apk add --no-cache musl-dev gpgme-dev
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz
(1/173) Installing dbus-libs (1.12.20-r2)
(2/173) Installing libffi (3.3-r2)
(3/173) Installing libintl (0.21-r0)
(4/173) Installing libblkid (2.37.2-r0)
(5/173) Installing libmount (2.37.2-r0)
(6/173) Installing pcre (8.44-r0)
(7/173) Installing glib (2.68.3-r0)
(8/173) Installing icu-libs (67.1-r2)
(9/173) Installing libpcre2-16 (10.36-r0)
(10/173) Installing zstd-libs (1.4.9-r1)
(11/173) Installing qt5-qtbase (5.15.3_git20210406-r0)
(12/173) Installing sqlite-libs (3.35.5-r0)
(13/173) Installing qt5-qtbase-sqlite (5.15.3_git20210406-r0)
(14/173) Installing ncurses-terminfo-base (6.2_p20210612-r0)
(15/173) Installing ncurses-libs (6.2_p20210612-r0)
(16/173) Installing readline (8.1.0-r0)
(17/173) Installing unixodbc (2.3.9-r1)
(18/173) Installing qt5-qtbase-odbc (5.15.3_git20210406-r0)
(19/173) Installing gdbm (1.19-r0)
(20/173) Installing libsasl (2.1.27-r12)
(21/173) Installing libldap (2.4.58-r0)
(22/173) Installing libpq (13.5-r0)
(23/173) Installing qt5-qtbase-postgresql (5.15.3_git20210406-r0)
(24/173) Installing mariadb-connector-c (3.1.13-r0)
(25/173) Installing qt5-qtbase-mysql (5.15.3_git20210406-r0)
(26/173) Installing freetds (1.2.21-r0)
(27/173) Installing qt5-qtbase-tds (5.15.3_git20210406-r0)
(28/173) Installing hicolor-icon-theme (0.17-r1)
(29/173) Installing mesa (21.1.2-r0)
(30/173) Installing libxau (1.0.9-r0)
(31/173) Installing libmd (1.0.3-r0)
(32/173) Installing libbsd (0.11.3-r0)
(33/173) Installing libxdmcp (1.1.3-r0)
(34/173) Installing libxcb (1.14-r2)
(35/173) Installing libx11 (1.7.2-r0)
(36/173) Installing libpciaccess (0.16-r0)
(37/173) Installing libdrm (2.4.106-r0)
(38/173) Installing expat (2.4.1-r0)
(39/173) Installing wayland-libs-server (1.19.0-r0)
(40/173) Installing mesa-gbm (21.1.2-r0)
(41/173) Installing mesa-glapi (21.1.2-r0)
(42/173) Installing wayland-libs-client (1.19.0-r0)
(43/173) Installing libxext (1.3.4-r0)
(44/173) Installing libxfixes (6.0.0-r0)
(45/173) Installing libxxf86vm (1.1.4-r2)
(46/173) Installing libxshmfence (1.3-r1)
(47/173) Installing mesa-gl (21.1.2-r0)
(48/173) Installing qt5-qtdeclarative (5.15.3_git20210531-r0)
(49/173) Installing libxcomposite (0.4.5-r0)
(50/173) Installing brotli-libs (1.0.9-r5)
(51/173) Installing libbz2 (1.0.8-r1)
(52/173) Installing libpng (1.6.37-r1)
(53/173) Installing freetype (2.10.4-r1)
(54/173) Installing libuuid (2.37.2-r0)
(55/173) Installing fontconfig (2.13.1-r4)
(56/173) Installing wayland-libs-cursor (1.19.0-r0)
(57/173) Installing wayland-libs-egl (1.19.0-r0)
(58/173) Installing pkgconf (1.7.4-r0)
(59/173) Installing xkeyboard-config (2.33-r0)
(60/173) Installing xz-libs (5.2.5-r0)
(61/173) Installing libxml2 (2.9.12-r1)
(62/173) Installing libxkbcommon (1.2.1-r0)
(63/173) Installing qt5-qtwayland (5.15.3_git20210510-r0)
(64/173) Installing mesa-egl (21.1.2-r0)
(65/173) Installing libice (1.0.10-r0)
(66/173) Installing libsm (1.2.3-r0)
(67/173) Installing avahi-libs (0.8-r5)
(68/173) Installing nettle (3.7.3-r0)
(69/173) Installing p11-kit (0.23.22-r0)
(70/173) Installing libtasn1 (4.17.0-r0)
(71/173) Installing libunistring (0.9.10-r1)
(72/173) Installing gnutls (3.7.1-r0)
(73/173) Installing cups-libs (2.3.3-r2)
(74/173) Installing graphite2 (1.3.14-r0)
(75/173) Installing harfbuzz (2.8.1-r0)
(76/173) Installing libevdev (1.11.0-r1)
(77/173) Installing mtdev (1.1.6-r0)
(78/173) Installing eudev-libs (3.2.10-r0)
(79/173) Installing libinput-libs (1.18.0-r0)
(80/173) Installing libjpeg-turbo (2.1.0-r0)
(81/173) Installing xcb-util-wm (0.4.1-r1)
(82/173) Installing xcb-util (0.4.0-r3)
(83/173) Installing xcb-util-image (0.4.0-r1)
(84/173) Installing xcb-util-keysyms (0.4.0-r1)
(85/173) Installing xcb-util-renderutil (0.3.9-r1)
(86/173) Installing libxkbcommon-x11 (1.2.1-r0)
(87/173) Installing qt5-qtbase-x11 (5.15.3_git20210406-r0)
(88/173) Installing qt5-qtbase-dbg (5.15.3_git20210406-r0)
(89/173) Installing blkid (2.37.2-r0)
(90/173) Installing libcap-ng (0.8.2-r0)
(91/173) Installing setpriv (2.37.2-r0)
(92/173) Installing libsmartcols (2.37.2-r0)
(93/173) Installing findmnt (2.37.2-r0)
(94/173) Installing mcookie (2.37.2-r0)
(95/173) Installing hexdump (2.37.2-r0)
(96/173) Installing lsblk (2.37.2-r0)
(97/173) Installing libfdisk (2.37.2-r0)
(98/173) Installing sfdisk (2.37.2-r0)
(99/173) Installing cfdisk (2.37.2-r0)
(100/173) Installing partx (2.37.2-r0)
(101/173) Installing flock (2.37.2-r0)
(102/173) Installing logger (2.37.2-r0)
(103/173) Installing uuidgen (2.37.2-r0)
(104/173) Installing libeconf (0.3.8-r1)
(105/173) Installing util-linux (2.37.2-r0)
(106/173) Installing util-linux-dev (2.37.2-r0)
(107/173) Installing dbus-dev (1.12.20-r2)
(108/173) Installing expat-dev (2.4.1-r0)
(109/173) Installing brotli-dev (1.0.9-r5)
(110/173) Installing zlib-dev (1.2.11-r3)
(111/173) Installing libpng-dev (1.6.37-r1)
(112/173) Installing freetype-dev (2.10.4-r1)
(113/173) Installing fontconfig-dev (2.13.1-r4)
(114/173) Installing mpdecimal (2.5.1-r1)
(115/173) Installing python3 (3.9.5-r1)
(116/173) Installing gettext-asprintf (0.21-r0)
(117/173) Installing gettext-libs (0.21-r0)
(118/173) Installing gettext (0.21-r0)
(119/173) Installing gettext-dev (0.21-r0)
(120/173) Installing bzip2-dev (1.0.8-r1)
(121/173) Installing libxml2-utils (2.9.12-r1)
(122/173) Installing libgpg-error (1.42-r0)
(123/173) Installing libgcrypt (1.9.4-r0)
(124/173) Installing libxslt (1.1.34-r1)
(125/173) Installing docbook-xml (4.5-r6)
Executing docbook-xml-4.5-r6.post-install
(126/173) Installing docbook-xsl (1.79.2-r2)
Executing docbook-xsl-1.79.2-r2.post-install
(127/173) Installing linux-headers (5.10.41-r0)
(128/173) Installing libffi-dev (3.3-r2)
(129/173) Installing libpcre16 (8.44-r0)
(130/173) Installing libpcre32 (8.44-r0)
(131/173) Installing libpcrecpp (8.44-r0)
(132/173) Installing pcre-dev (8.44-r0)
(133/173) Installing glib-dev (2.68.3-r0)
(134/173) Installing xorgproto (2021.4-r0)
(135/173) Installing libice-dev (1.0.10-r0)
(136/173) Installing libsm-dev (1.2.3-r0)
(137/173) Installing libxau-dev (1.0.9-r0)
(138/173) Installing xcb-proto (1.14.1-r2)
(139/173) Installing libxdmcp-dev (1.1.3-r0)
(140/173) Installing libxcb-dev (1.14-r2)
(141/173) Installing xtrans (1.4.0-r1)
(142/173) Installing libx11-dev (1.7.2-r0)
(143/173) Installing libxext-dev (1.3.4-r0)
(144/173) Installing libpciaccess-dev (0.16-r0)
(145/173) Installing libdrm-dev (2.4.106-r0)
(146/173) Installing libxdamage (1.1.5-r1)
(147/173) Installing libxfixes-dev (6.0.0-r0)
(148/173) Installing libxdamage-dev (1.1.5-r1)
(149/173) Installing libxshmfence-dev (1.3-r1)
(150/173) Installing mesa-gles (21.1.2-r0)
(151/173) Installing llvm11-libs (11.1.0-r2)
(152/173) Installing mesa-osmesa (21.1.2-r0)
(153/173) Installing mesa-xatracker (21.1.2-r0)
(154/173) Installing libxxf86vm-dev (1.1.4-r2)
(155/173) Installing mesa-dev (21.1.2-r0)
(156/173) Installing openssl-dev (1.1.1l-r0)
(157/173) Installing perl (5.32.1-r0)
(158/173) Installing sqlite-dev (3.35.5-r0)
(159/173) Installing qt5-qtbase-dev (5.15.3_git20210406-r0)
(160/173) Installing libassuan (2.5.5-r0)
(161/173) Installing libcap (2.50-r0)
(162/173) Installing libsecret (0.20.4-r1)
(163/173) Installing pinentry (1.1.1-r0)
Executing pinentry-1.1.1-r0.post-install
(164/173) Installing libksba (1.5.1-r0)
(165/173) Installing npth (1.6-r0)
(166/173) Installing gnupg (2.2.31-r0)
(167/173) Installing gpgme (1.15.1-r2)
(168/173) Installing gpgmepp (1.15.1-r2)
(169/173) Installing libgpg-error-dev (1.42-r0)
(170/173) Installing libassuan-dev (2.5.5-r0)
(171/173) Installing qgpgme (1.15.1-r2)
(172/173) Installing gpgme-dev (1.15.1-r2)
(173/173) Installing musl-dev (1.2.2-r3)
Executing busybox-1.33.1-r6.trigger
Executing glib-2.68.3-r0.trigger
No schema files found: doing nothing.
OK: 678 MiB in 199 packages
--> 53f3ffe4843
STEP 3/5: ADD code /usr/local/src
--> ae2c01cc392
STEP 4/5: WORKDIR /usr/local/src
--> 1cd2da187ee
STEP 5/5: RUN cargo build
Updating crates.io index
Downloading crates ...
Downloaded conv v0.3.3
Downloaded custom_derive v0.1.7
Downloaded gpg-error v0.5.2
Downloaded gpgme v0.10.0
Downloaded cfg-if v1.0.0
Downloaded bitflags v1.3.2
Downloaded libgpg-error-sys v0.5.2
Downloaded gpgme-sys v0.10.0
Downloaded smallvec v1.7.0
Downloaded static_assertions v1.1.0
Downloaded memchr v2.4.1
Downloaded once_cell v1.8.0
Downloaded cstr-argument v0.1.2
Downloaded libc v0.2.108
Compiling libgpg-error-sys v0.5.2
Compiling libc v0.2.108
Compiling memchr v2.4.1
Compiling gpg-error v0.5.2
Compiling gpgme-sys v0.10.0
Compiling cfg-if v1.0.0
Compiling custom_derive v0.1.7
Compiling once_cell v1.8.0
Compiling bitflags v1.3.2
Compiling static_assertions v1.1.0
Compiling smallvec v1.7.0
Compiling conv v0.3.3
Compiling cstr-argument v0.1.2
Compiling gpgme v0.10.0
Compiling repro v0.1.0 (/usr/local/src)
Finished dev [unoptimized + debuginfo] target(s) in 42.54s
COMMIT repro
--> 810199c328b
Successfully tagged localhost/repro:latest
810199c328b67593723180052720dfb5e458be9bb0b98985944e391986d757f9
/usr/local/src # target/debug/repro
Segmentation fault
I can reproduce this issue. It happens because of the gpgme_check_version_internal call while initializing the gpgme library:
gpgme::init (lib.rs:158)
└─gpgme::context::Context::new (context.rs:47)
└─gpgme::context::Context::from_protocol (context.rs:63)
└─repro::main (main.rs:5)
Core dump
/usr/local/src # valgrind -v target/debug/repro
==18== Memcheck, a memory error detector
==18== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==18== Using Valgrind-3.17.0-07f0cdcbb4-20210319X and LibVEX; rerun with -h for copyright info
==18== Command: target/debug/repro
==18==
--18-- Valgrind options:
--18-- -v
--18-- Contents of /proc/version:
--18-- Linux version 5.15.4-arch1-1 (linux@archlinux) (gcc (GCC) 11.1.0, GNU ld (GNU Binutils) 2.36.1) #1 SMP PREEMPT Sun, 21 Nov 2021 21:34:33 +0000
--18--
--18-- Arch and hwcaps: AMD64, LittleEndian, amd64-cx16-lzcnt-rdtscp-sse3-ssse3-avx-avx2-bmi-f16c-rdrand-rdseed
--18-- Page sizes: currently 4096, max supported 4096
--18-- Valgrind library directory: /usr/libexec/valgrind
--18-- Reading syms from /usr/local/src/target/debug/repro
--18-- Reading syms from /usr/libexec/valgrind/memcheck-amd64-linux
--18-- object doesn't have a dynamic symbol table
--18-- Scheduler: using generic scheduler lock implementation.
--18-- Reading suppressions file: /usr/libexec/valgrind/default.supp
==18== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-18-by-???-on-316c3d58276c
==18== embedded gdbserver: writing to /tmp/vgdb-pipe-to-vgdb-from-18-by-???-on-316c3d58276c
==18== embedded gdbserver: shared mem /tmp/vgdb-pipe-shared-mem-vgdb-18-by-???-on-316c3d58276c
==18==
==18== TO CONTROL THIS PROCESS USING vgdb (which you probably
==18== don't want to do, unless you know exactly what you're doing,
==18== or are doing some strange experiment):
==18== /usr/libexec/valgrind/../../bin/vgdb --pid=18 ...command...
==18==
==18== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==18== /path/to/gdb target/debug/repro
==18== and then give GDB the following command
==18== target remote | /usr/libexec/valgrind/../../bin/vgdb --pid=18
==18== --pid is optional if only one valgrind process is running
==18==
==18== Jump to the invalid address stated on the next line
==18== at 0x0: ???
==18== by 0x117097: gpgme::init::TOKEN::{{closure}} (lib.rs:158)
==18== by 0x1156D4: core::ops::function::FnOnce::call_once (function.rs:227)
==18== by 0x115711: core::ops::function::FnOnce::call_once (function.rs:227)
==18== by 0x116C5B: once_cell::sync::Lazy<T,F>::force::{{closure}} (lib.rs:1115)
==18== by 0x116CCC: once_cell::sync::OnceCell<T>::get_or_init::{{closure}} (lib.rs:938)
==18== by 0x115319: once_cell::imp::OnceCell<T>::initialize::{{closure}} (imp_std.rs:95)
==18== by 0x11A532: once_cell::imp::initialize_inner (imp_std.rs:171)
==18== by 0x1152A8: once_cell::imp::OnceCell<T>::initialize (imp_std.rs:93)
==18== by 0x116DC3: once_cell::sync::OnceCell<T>::get_or_try_init (lib.rs:978)
==18== by 0x116C8D: once_cell::sync::OnceCell<T>::get_or_init (lib.rs:938)
==18== by 0x116BE2: once_cell::sync::Lazy<T,F>::force (lib.rs:1114)
==18== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==18==
==18==
==18== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==18== Bad permissions for mapped region at address 0x0
==18== at 0x0: ???
==18== by 0x117097: gpgme::init::TOKEN::{{closure}} (lib.rs:158)
==18== by 0x1156D4: core::ops::function::FnOnce::call_once (function.rs:227)
==18== by 0x115711: core::ops::function::FnOnce::call_once (function.rs:227)
==18== by 0x116C5B: once_cell::sync::Lazy<T,F>::force::{{closure}} (lib.rs:1115)
==18== by 0x116CCC: once_cell::sync::OnceCell<T>::get_or_init::{{closure}} (lib.rs:938)
==18== by 0x115319: once_cell::imp::OnceCell<T>::initialize::{{closure}} (imp_std.rs:95)
==18== by 0x11A532: once_cell::imp::initialize_inner (imp_std.rs:171)
==18== by 0x1152A8: once_cell::imp::OnceCell<T>::initialize (imp_std.rs:93)
==18== by 0x116DC3: once_cell::sync::OnceCell<T>::get_or_try_init (lib.rs:978)
==18== by 0x116C8D: once_cell::sync::OnceCell<T>::get_or_init (lib.rs:938)
==18== by 0x116BE2: once_cell::sync::Lazy<T,F>::force (lib.rs:1114)
==18==
==18== HEAP SUMMARY:
==18== in use at exit: 0 bytes in 0 blocks
==18== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==18==
==18== All heap blocks were freed -- no leaks are possible
==18==
==18== ERROR SUMMARY: 2 errors from 1 contexts (suppressed: 0 from 0)
==18==
==18== 2 errors in context 1 of 1:
==18== Jump to the invalid address stated on the next line
==18== at 0x0: ???
==18== by 0x117097: gpgme::init::TOKEN::{{closure}} (lib.rs:158)
==18== by 0x1156D4: core::ops::function::FnOnce::call_once (function.rs:227)
==18== by 0x115711: core::ops::function::FnOnce::call_once (function.rs:227)
==18== by 0x116C5B: once_cell::sync::Lazy<T,F>::force::{{closure}} (lib.rs:1115)
==18== by 0x116CCC: once_cell::sync::OnceCell<T>::get_or_init::{{closure}} (lib.rs:938)
==18== by 0x115319: once_cell::imp::OnceCell<T>::initialize::{{closure}} (imp_std.rs:95)
==18== by 0x11A532: once_cell::imp::initialize_inner (imp_std.rs:171)
==18== by 0x1152A8: once_cell::imp::OnceCell<T>::initialize (imp_std.rs:93)
==18== by 0x116DC3: once_cell::sync::OnceCell<T>::get_or_try_init (lib.rs:978)
==18== by 0x116C8D: once_cell::sync::OnceCell<T>::get_or_init (lib.rs:938)
==18== by 0x116BE2: once_cell::sync::Lazy<T,F>::force (lib.rs:1114)
==18== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==18==
==18== ERROR SUMMARY: 2 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
Scope of interest:
==18== Process terminating with default action of signal 11 (SIGSEGV): dumping core ==18== Bad permissions for mapped region at address 0x0 ==18== at 0x0: ??? ==18== by 0x117097: gpgme::init::TOKEN::{{closure}} (lib.rs:158) ==18== by 0x1156D4: core::ops::function::FnOnce::call_once (function.rs:227) ==18== by 0x115711: core::ops::function::FnOnce::call_once (function.rs:227) ==18== by 0x116C5B: once_cell::sync::Lazy<T,F>::force::{{closure}} (lib.rs:1115) ==18== by 0x116CCC: once_cell::sync::OnceCell<T>::get_or_init::{{closure}} (lib.rs:938) ==18== by 0x115319: once_cell::imp::OnceCell<T>::initialize::{{closure}} (imp_std.rs:95) ==18== by 0x11A532: once_cell::imp::initialize_inner (imp_std.rs:171) ==18== by 0x1152A8: once_cell::imp::OnceCell<T>::initialize (imp_std.rs:93) ==18== by 0x116DC3: once_cell::sync::OnceCell<T>::get_or_try_init (lib.rs:978) ==18== by 0x116C8D: once_cell::sync::OnceCell<T>::get_or_init (lib.rs:938) ==18== by 0x116BE2: once_cell::sync::Lazy<T,F>::force (lib.rs:1114)
It is apparent that it is caused by the this line:
https://github.com/gpg-rs/gpgme/blob/5a2e5ef3c47d0487a29d9f93832b160079f0b5f8/src/lib.rs#L158
This is a FFI binding for the following function in gpgme:
https://github.com/gpg/gpgme/blob/3ffd7bd4039d90cd15fbf76f8c116814bffdab7c/src/version.c#L219-L245
This cannot be skipped since GPG_ERR_NOT_OPERATIONAL is returned if gpgme_check_version* was not called to initialize GPGME. However, in this case, I think the problem is musl / static linking because it might cause undefined behaviour (thus segmentation fault) in the gpgme_check_version_internal function (in gpgme itself) which was previously mentioned.