Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 720286 - sys-apps/haveged-1.9.8c throws segfault when shutting down
Summary: sys-apps/haveged-1.9.8c throws segfault when shutting down
Status: RESOLVED FIXED
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: Current packages (show other bugs)
Hardware: All Linux
: Normal normal (vote)
Assignee: Anthony Basile
URL: https://github.com/jirka-h/haveged/pu...
Whiteboard:
Keywords:
Depends on: 762139
Blocks:
  Show dependency tree
 
Reported: 2020-05-01 13:59 UTC by Marcin Mirosław
Modified: 2021-12-24 08:07 UTC (History)
2 users (show)

See Also:
Package list:
Runtime testing required: ---


Attachments
haveged-1.9.8c-threaded-shutdown.patch (haveged-1.9.8c-threaded-shutdown.patch,3.57 KB, patch)
2020-05-01 20:05 UTC, Sergei Trofimovich (RETIRED)
Details | Diff
haveged-1.9.8c-threaded-shutdown.patch (haveged-1.9.8c-threaded-shutdown.patch,4.04 KB, patch)
2020-05-01 20:41 UTC, Sergei Trofimovich (RETIRED)
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Marcin Mirosław 2020-05-01 13:59:41 UTC
When I execute
/etc/init.d/haveged stop

then haveged throws segfault.
# gdb -q /usr/sbin/haveged 'core-1588341382-0-11-!usr!sbin!haveged-4584'
Reading symbols from /usr/sbin/haveged...
Reading symbols from /usr/lib64/debug//usr/sbin/haveged.debug...
[New LWP 4584]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Core was generated by `/usr/sbin/haveged -r 0 -w 1024 -v 1 -p /run/haveged.pid'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  __GI___libc_free (mem=0x7f630c066000) at malloc.c:3109
3109      p = mem2chunk (mem);
(gdb) bt
#0  __GI___libc_free (mem=0x7f630c066000) at malloc.c:3109
#1  0x00007f630c035f9e in havege_destroy (hptr=0x564b56b6b900) at havege.c:197
#2  0x0000564b561c3dca in error_exit (format=<optimized out>) at haveged.c:708
#3  0x0000564b561c33f1 in run_daemon (argv=0x7ffce7627758, path=0x564b56b6b2a0 "/usr/sbin/haveged", h=0x564b56b6b900) at haveged.c:573
#4  main (argc=<optimized out>, argv=0x7ffce7627758) at haveged.c:470
(gdb) bt full                                                                                                                                                                                         [13/1877]
#0  __GI___libc_free (mem=0x7f630c066000) at malloc.c:3109
        ar_ptr = <optimized out>
        p = <optimized out>
        hook = 0x0
#1  0x00007f630c035f9e in havege_destroy (hptr=0x564b56b6b900) at havege.c:197
        htemp = <optimized out>
        temp = <optimized out>
#2  0x0000564b561c3dca in error_exit (format=<optimized out>) at haveged.c:708
        buffer = "Stopping due to signal 15\n\000s/system/cpu/cpu4/cache", '\000' <repeats 1246 times>...
        ap = {{gp_offset = 16, fp_offset = 48, overflow_arg_area = 0x7ffce76261c0, reg_save_area = 0x7ffce7626100}}
#3  0x0000564b561c33f1 in run_daemon (argv=0x7ffce7627758, path=0x564b56b6b2a0 "/usr/sbin/haveged", h=0x564b56b6b900) at haveged.c:573
        current = 2
        write_fd = {fds_bits = {32, 0 <repeats 15 times>}}
        read_fd = {fds_bits = {8, 0 <repeats 15 times>}}
        nbytes = <optimized out>
        r = <optimized out>
        max = <optimized out>
        random_fd = 5
        conn_fd = <optimized out>
        output = 0x7f630c066000
        stat_buf = {st_dev = 6, st_ino = 1031, st_nlink = 1, st_mode = 8630, st_uid = 0, st_gid = 0, __pad0 = 0, st_rdev = 264, st_size = 0, st_blksize = 4096, st_blocks = 0, st_atim = {
            tv_sec = 1588235982, tv_nsec = 860000000}, st_mtim = {tv_sec = 1588235982, tv_nsec = 860000000}, st_ctim = {tv_sec = 1588235982, tv_nsec = 860000000}, __glibc_reserved = {0, 0, 0}}
        random_fd = <optimized out>
        conn_fd = <optimized out>
        output = <optimized out>
        stat_buf = <optimized out>
        current = <optimized out>
        nbytes = <optimized out>
        r = <optimized out>
        max = <optimized out>
        write_fd = <optimized out>
        read_fd = <optimized out>
        __d0 = <optimized out>
        __d1 = <optimized out>
        __d0 = <optimized out>
        __d1 = <optimized out>
        __d = <optimized out>
        __d = <optimized out>
        __d = <optimized out>
        two = <optimized out>
        rc = <optimized out>
        __d = <optimized out>
        __d = <optimized out>
        __d = <optimized out>
#4  main (argc=<optimized out>, argv=0x7ffce7627758) at haveged.c:470
        path = 0x564b56b6b2a0 "/usr/sbin/haveged"
        arg0 = <optimized out>
        cmds = {0x564b561c50c4 "b", 0x564b561c5243 "buffer", 0x564b561c524a "1", 0x564b561c5588 "Buffer size [KW], default: 128", 0x564b561c522b "d", 0x564b561c524c "data", 0x564b561c524a "1",
          0x564b561c55a8 "Data cache size [KB], with fallback to: 16", 0x564b561c5251 "c", 0x564b561c5253 "command", 0x564b561c524a "1", 0x564b561c55d8 "Send a command mode to an already running haveged",
          0x564b561c51db "i", 0x564b561c525b "inst", 0x564b561c524a "1", 0x564b561c5610 "Instruction cache size [KB], with fallback to: 16", 0x564b561c5260 "f", 0x564b561c52a5 "file", 0x564b561c524a "1",
          0x564b561c5648 "Sample output file,  default: 'sample', '-' for stdout", 0x564b561c5262 "F", 0x564b561c5264 "Foreground", 0x564b561c526f "0", 0x564b561c5271 "Run daemon in foreground",
          0x564b561c5293 "r", 0x564b561c528a "run", 0x564b561c524a "1", 0x564b561c5680 "0=daemon, 1=config info, >1=<r>KB sample", 0x564b561c5144 "n", 0x564b561c528e "number", 0x564b561c524a "1",
          0x564b561c56b0 "Output size in [k|m|g|t] bytes, 0 = unlimited to stdout", 0x564b561c5295 "o", 0x564b561c5297 "onlinetest", 0x564b561c524a "1",
          0x564b561c56e8 "[t<x>][c<x>] x=[a[n][w]][b[w]] 't'ot, 'c'ontinuous, default: ta8b", 0x564b561c52dd "p", 0x564b561c52a2 "pidfile", 0x564b561c524a "1",
          0x564b561c5730 "daemon pidfile, default: /var/run/haveged.pid", 0x564b561c50bf "s", 0x564b561c52aa "source", 0x564b561c524a "1",
          0x564b561c5760 "Injection source file, default: 'data', '-' for stdin", 0x564b561c52a0 "t", 0x564b561c52bb "threads", 0x564b561c524a "1", 0x564b561c52b1 "Number of threads", 0x564b561c52c3 "v",
          0x564b561c52c5 "verbose", 0x564b561c524a "1", 0x564b561c5798 "Verbose mask 0=none,1=summary,2=retries,4=timing,8=loop,16=code,32=test", 0x564b561c51d8 "w", 0x564b561c52cd "write",
          0x564b561c524a "1", 0x564b561c57e0 "Set write_wakeup_threshold [bits]", 0x564b561c52d3 "h", 0x564b561c52da "help", 0x564b561c526f "0", 0x564b561c52d5 "This help"}
        long_options = {{name = 0x564b561c5243 "buffer", has_arg = 1, flag = 0x0, val = 98}, {name = 0x564b561c524c "data", has_arg = 1, flag = 0x0, val = 100}, {name = 0x564b561c5253 "command",
            has_arg = 1, flag = 0x0, val = 99}, {name = 0x564b561c525b "inst", has_arg = 1, flag = 0x0, val = 105}, {name = 0x564b561c52a5 "file", has_arg = 1, flag = 0x0, val = 102}, {
            name = 0x564b561c5264 "Foreground", has_arg = 0, flag = 0x0, val = 70}, {name = 0x564b561c528a "run", has_arg = 1, flag = 0x0, val = 114}, {name = 0x564b561c528e "number", has_arg = 1,
            flag = 0x0, val = 110}, {name = 0x564b561c5297 "onlinetest", has_arg = 1, flag = 0x0, val = 111}, {name = 0x564b561c52a2 "pidfile", has_arg = 1, flag = 0x0, val = 112}, {
            name = 0x564b561c52bb "threads", has_arg = 1, flag = 0x0, val = 116}, {name = 0x564b561c52c5 "verbose", has_arg = 1, flag = 0x0, val = 118}, {name = 0x564b561c52cd "write", has_arg = 1,
            flag = 0x0, val = 119}, {name = 0x564b561c52da "help", has_arg = 0, flag = 0x0, val = 104}, {name = 0x0, has_arg = 0, flag = 0x0, val = 0}, {name = 0x0, has_arg = -412977552,
            flag = 0x564b561c3790 <_start>, val = 1444684948}}
        short_options = "b:d:c:i:f:Fr:n:o:p:t:v:w:h\000\000\000\000"
--Type <RET> for more, q to quit, c to continue without paging--
        c = <optimized out>
        i = <optimized out>
        j = <optimized out>
        bufct = <optimized out>
        bufrem = <optimized out>
        ierr = <optimized out>
        cmd = {ioSz = 8200, collectSize = 0, icacheSize = 0, dcacheSize = 0, options = 1, nCores = 0, metering = 0x0, msg_out = 0x564b561c3890 <print_msg>, injection = 0x0, procFs = 0x0, sysFs = 0x0,
          testSpec = 0x564b561c50c6 "ta8bcb"}
(gdb)


Reproducible: Always




 # emerge --info haveged
Portage 2.3.89 (python 3.6.10-final-0, default/linux/amd64/17.0/no-multilib/hardened, gcc-9.3.0, glibc-2.29-r7, 5.3.0-89600-gd7dbd2ce12c4 x86_64)
=================================================================
                         System Settings
=================================================================
System uname: Linux-5.3.0-89600-gd7dbd2ce12c4-x86_64-Intel-R-_Xeon-R-_CPU_E3-1230_v5_@_3.40GHz-with-gentoo-2.6
KiB Mem:     7618228 total,    567112 free
KiB Swap:    1548284 total,   1548284 free
Timestamp of repository gentoo: Fri, 01 May 2020 10:43:54 +0000
Head commit of repository gentoo: 52ce6865c875509367f6544136cc4ab699eafd86

sh bash 4.4_p23-r1
ld GNU ld (Gentoo 2.33.1 p2) 2.33.1
ccache version 3.7.7 [disabled]
app-shells/bash:          4.4_p23-r1::gentoo
dev-lang/perl:            5.30.1::gentoo
dev-lang/python:          2.7.17-r2::gentoo, 3.6.10-r1::gentoo, 3.7.7-r1::gentoo
dev-util/ccache:          3.7.7-r1::gentoo
dev-util/cmake:           3.16.5::gentoo
dev-util/pkgconfig:       0.29.2::gentoo
sys-apps/baselayout:      2.6-r1::gentoo
sys-apps/openrc:          0.42.1::gentoo                                                                                                                                                                       sys-apps/sandbox:         2.13::gentoo
sys-devel/autoconf:       2.69-r4::gentoo                                                                                                                                                                      sys-devel/automake:       1.15.1-r2::gentoo, 1.16.1-r1::gentoo
sys-devel/binutils:       2.33.1-r1::gentoo
sys-devel/gcc:            9.3.0::gentoo
sys-devel/gcc-config:     2.2.1::gentoo
sys-devel/libtool:        2.4.6-r6::gentoo
sys-devel/make:           4.2.1-r4::gentoo
sys-kernel/linux-headers: 5.4::gentoo (virtual/os-headers)
sys-libs/glibc:           2.29-r7::gentoo
Repositories:

gentoo
    location: /usr/portage
    sync-type: git
    sync-uri: https://github.com/gentoo-mirror/gentoo.git
    sync-user: portage:portage
    priority: -1000

Installed sets: @masscheck, @nagios-plugins, @sheepdog
ACCEPT_KEYWORDS="amd64"
ACCEPT_LICENSE="*"
CBUILD="x86_64-pc-linux-gnu"
CFLAGS="-O3 -pipe -march=westmere -mtune=native    -fno-unwind-tables -fuse-linker-plugin  -ftracer    -fuse-ld=gold -fvar-tracking-assignments"
CHOST="x86_64-pc-linux-gnu"
CONFIG_PROTECT="/etc /usr/share/easy-rsa /usr/share/gnupg/qualified.txt /var/bind"
CONFIG_PROTECT_MASK="/etc/ca-certificates.conf /etc/env.d /etc/fonts/fonts.conf /etc/gconf /etc/gentoo-release /etc/php/apache2-php7.2/ext-active/ /etc/php/apache2-php7.3/ext-active/ /etc/php/apache2-php7.4/
ext-active/ /etc/php/cgi-php7.2/ext-active/ /etc/php/cgi-php7.3/ext-active/ /etc/php/cgi-php7.4/ext-active/ /etc/php/cli-php7.2/ext-active/ /etc/php/cli-php7.3/ext-active/ /etc/php/cli-php7.4/ext-active/ /et
c/revdep-rebuild /etc/sandbox.d /etc/terminfo"
CXXFLAGS="-O3 -pipe -march=westmere -mtune=native    -fno-unwind-tables -fuse-linker-plugin  -ftracer    -fuse-ld=gold -fvar-tracking-assignments"
DISTDIR="/usr/portage/distfiles"
ENV_UNSET="DBUS_SESSION_BUS_ADDRESS DISPLAY GOBIN PERL5LIB PERL5OPT PERLPREFIX PERL_CORE PERL_MB_OPT PERL_MM_OPT XAUTHORITY XDG_CACHE_HOME XDG_CONFIG_HOME XDG_DATA_HOME XDG_RUNTIME_DIR"
FCFLAGS="-O3 -pipe -march=westmere -mtune=native    -fno-unwind-tables -fuse-linker-plugin  -ftracer    -fuse-ld=gold -fvar-tracking-assignments"
FEATURES="assume-digests binpkg-docompress binpkg-dostrip binpkg-logs cgroup collision-protect compressdebug config-protect-if-modified distlocks ebuild-locks fixlafiles ipc-sandbox multilib-strict network-s
andbox news parallel-fetch parallel-install pid-sandbox preserve-libs protect-owned qa-unresolved-soname-deps sandbox sfperms splitdebug strict unmerge-logs unmerge-orphans userfetch userpriv usersandbox use
rsync xattr"
FFLAGS="-O3 -pipe -march=westmere -mtune=native    -fno-unwind-tables -fuse-linker-plugin  -ftracer    -fuse-ld=gold -fvar-tracking-assignments"
GENTOO_MIRRORS="http://distfiles.gentoo.org"
LANG="pl_PL.utf8"
LDFLAGS="-Wl,-O1 -Wl,--as-needed -Wl,--sort-common"
LINGUAS="en"
MAKEOPTS="-j4 -l5"
PKGDIR="/var/cache/binpkgs"
PORTAGE_CONFIGROOT="/"
PORTAGE_RSYNC_OPTS="--recursive --links --safe-links --perms --times --omit-dir-times --compress --force --whole-file --delete --stats --human-readable --timeout=180 --exclude=/distfiles --exclude=/local --e
xclude=/packages --exclude=/.git"
PORTAGE_TMPDIR="/var/tmp"
USE="acl aio amd64 apache2 bash-completion bzip2 caps crypt hardened iconv idn ipv6 jit libtirpc lto modules nano-syntax ncurses nls nptl openmp pcre pie readline seccomp smp split-usr ssl ssp threads unicod
e vhosts vim-syntax xattr xtpax zlib" ABI_X86="64" ADA_TARGET="gnat_2018" APACHE2_MODULES="alias authn_core access_compat auth_basic authz_core authn_alias authn_anon auth_digest authn_dbm authn_default auth
n_file authz_dbm authz_default authz_groupfile authz_host authz_owner authz_user autoindex cgi dav dav_fs dav_lock dir env expires ext_filter filter headers hugepages include info log_config logio mime mime_
magic negotiation remoteip rewrite setenvif status unique_id unixd socache_shmcb usertrack vhost_alias" APACHE2_MPMS="itk" CALLIGRA_FEATURES="karbon sheets words" COLLECTD_PLUGINS="apache aggregation bind cg
roups conntrack contextswitch cpu curl curl_json df disk dns email entropy ethstat exec filecount hugepages interface iptables irq lvm match_regex mysql netlink load memory network nginx notify_email ntpd op
envpn ping postgresql processes protocols redis rrdcached rrdtool snmp statsd swap syslog tail tail_csv tcpconns unixsock uptime vmem" CPU_FLAGS_X86="aes mmx mmxext sse sse2 sse3 ssse3" ELIBC="glibc" GRUB_PL
ATFORMS="pc" KERNEL="linux" L10N="en" LIBREOFFICE_EXTENSIONS="presenter-console presenter-minimizer" NGINX_MODULES_HTTP="access autoindex browser charset fastcgi gzip map limit_zone proxy rewrite http2 stub_
status gzip_static" OFFICE_IMPLEMENTATION="libreoffice" PHP_TARGETS="php7-2" POSTGRES_TARGETS="postgres10 postgres11" PYTHON_SINGLE_TARGET="python3_6" PYTHON_TARGETS="python2_7 python3_6" RUBY_TARGETS="ruby2
4 ruby25" USERLAND="GNU" XTABLES_ADDONS="fuzzy geoip lscan psd Xsysrq tarpit"
Unset:  CC, CPPFLAGS, CTARGET, CXX, EMERGE_DEFAULT_OPTS, INSTALL_MASK, LC_ALL, PORTAGE_BINHOST, PORTAGE_BUNZIP2_COMMAND, PORTAGE_COMPRESS, PORTAGE_COMPRESS_FLAGS, PORTAGE_RSYNC_EXTRA_OPTS

=================================================================
                        Package Settings
=================================================================

sys-apps/haveged-1.9.8c::gentoo was built with the following:
USE="threads (-selinux) -static-libs"
CFLAGS="-O2 -march=westmere -mtune=native -ggdb3 -gdwarf-4 -fvar-tracking-assignments -ftracer -pipe"
CXXFLAGS="-O2 -march=westmere -mtune=native -ggdb3 -gdwarf-4 -fvar-tracking-assignments -ftracer -pipe"
FEATURES="assume-digests binpkg-docompress binpkg-dostrip binpkg-logs cgroup collision-protect compressdebug config-protect-if-modified distlocks ebuild-locks fixlafiles installsources ipc-sandbox multilib-s
trict network-sandbox news parallel-fetch parallel-install pid-sandbox preserve-libs protect-owned qa-unresolved-soname-deps sandbox sfperms splitdebug strict unmerge-logs unmerge-orphans userfetch userpriv
usersandbox usersync xattr"
Comment 1 Lars Wendler (Polynomial-C) (RETIRED) gentoo-dev 2020-05-01 15:00:42 UTC
I have the same issue...
Comment 2 Sergei Trofimovich (RETIRED) gentoo-dev 2020-05-01 16:04:11 UTC
My guess it's a memory corruption in haveged. Looking at the backtrace it's somehow related to signal handler itself. As it it was a double-free or similar.

If you run the daemon under valgrind (or build it with ASAN), can you get more detailed log where corruption initially happens?
Comment 3 Sergei Trofimovich (RETIRED) gentoo-dev 2020-05-01 16:23:53 UTC
Reproduced locally with sys-apps/haveged[threads]. Should be able to debug.
Comment 4 Sergei Trofimovich (RETIRED) gentoo-dev 2020-05-01 16:31:26 UTC
# valgrind --track-origins=yes --trace-children=yes --num-callers=50 --malloc-fill=0xE1 --free-fill=0xF1 --log-file=/tmp/lf /usr/sbin/haveged -w 1024 -v 1 -p /run/haveged.pid -r 0

# kill -TERM 2318700

The relevant output is:

==2318675== For lists of detected and suppressed errors, rerun with: -s
==2318675== ERROR SUMMARY: 14 errors from 2 contexts (suppressed: 0 from 0)
==2318700== Invalid free() / delete / delete[] / realloc()
==2318700==    at 0x48389CB: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==2318700==    by 0x48AED9F: havege_destroy (havege.c:197)
==2318700==    by 0x10BCA5: error_exit (haveged.c:708)
==2318700==    by 0x10B1B7: run_daemon (haveged.c:573)
==2318700==    by 0x10B1B7: main (haveged.c:470)
==2318700==  Address 0x4845000 is in a rw- anonymous segment

It's a mismatch in mmap/free().
Comment 5 Sergei Trofimovich (RETIRED) gentoo-dev 2020-05-01 17:12:41 UTC
(In reply to Sergei Trofimovich from comment #4)
> ==2318675== For lists of detected and suppressed errors, rerun with: -s
> ==2318675== ERROR SUMMARY: 14 errors from 2 contexts (suppressed: 0 from 0)
> ==2318700== Invalid free() / delete / delete[] / realloc()
> ==2318700==    at 0x48389CB: free (in
> /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==2318700==    by 0x48AED9F: havege_destroy (havege.c:197)
> ==2318700==    by 0x10BCA5: error_exit (haveged.c:708)
> ==2318700==    by 0x10B1B7: run_daemon (haveged.c:573)
> ==2318700==    by 0x10B1B7: main (haveged.c:470)
> ==2318700==  Address 0x4845000 is in a rw- anonymous segment
> 
> It's a mismatch in mmap/free().

Allocation/free rules of 'h_ptr->io_buf' are a bit tricky:

    https://github.com/jirka-h/haveged/blob/master/src/havege.c

  havege_create() {
  #if NUMBER_CORES>1
     havege_ipc(h, n, sz);
  #else
     h->io_buf  = malloc(sz);
  ...
  }

  void havege_destroy(       /* RETURN: none            */
    H_PTR hptr)              /* IN-OUT: app anchor      */
  {
    if (NULL != hptr) {
      H_COLLECT *htemp;
      void *temp;
  #if NUMBER_CORES>1
      if (!havege_exit(hptr))
         return;           /* only main thread continues  */
  #endif
      if (0 != (temp=hptr->io_buf)) {
         hptr->io_buf = 0;
         free(temp);
      }
  ...

This 'free(temp);' should not be called for '#if NUMBER_CORES>1' Either it belong in an '#else' branch, or 'havege_exit(hptr)' should do a cleanup and looks like it tries to do the cleanup.

It's not clear from the code how it can happen.
Comment 6 Sergei Trofimovich (RETIRED) gentoo-dev 2020-05-01 20:05:19 UTC
Created attachment 635554 [details, diff]
haveged-1.9.8c-threaded-shutdown.patch

I think I have a fix. daemonize() breaks the assumption that main process does not change the pid. That breaks the invariant of how main process should look like. Main process ended up thinking it's a shigle thread and used single-thread deallocation.

Can you try a workaround attached? It seems to work for me.
Comment 7 Sergei Trofimovich (RETIRED) gentoo-dev 2020-05-01 20:13:48 UTC
Also proposed fix upstream as https://github.com/jirka-h/haveged/pull/30
Comment 8 Sergei Trofimovich (RETIRED) gentoo-dev 2020-05-01 20:41:30 UTC
Created attachment 635556 [details, diff]
haveged-1.9.8c-threaded-shutdown.patch

Updated patch to handle --disable-threads case.
Comment 9 Sergei Trofimovich (RETIRED) gentoo-dev 2020-06-14 13:14:22 UTC
Merged upstream.