[Bug 224503] rpcbind: Broken in the face of signal termination

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Thu Dec 21 18:35:47 UTC 2017


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=224503

            Bug ID: 224503
           Summary: rpcbind: Broken in the face of signal termination
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: bin
          Assignee: freebsd-bugs at FreeBSD.org
          Reporter: cem at freebsd.org

Rpcbind may crash in signal-induced termination.

E.g.:

> (gdb) bt
> ...
> #12 __free (ptr=0x8006f8140) at jemalloc_jemalloc.c:1277
> #13 0x0000000800d4c8e7 in vector_free (esize=<optimized out>, vec=<optimized out>, count=<optimized out>, esize=<optimized out>, free_elem=<optimized out>)
>     at /b/mnt/src/lib/libc/net/nsdispatch.c:250
> #14 nss_atexit () at /b/mnt/src/lib/libc/net/nsdispatch.c:577
> #15 0x0000000800d4d5b9 in __cxa_finalize (dso=0x0) at /b/mnt/src/lib/libc/stdlib/atexit.c:200
> #16 0x0000000800cfe1ac in exit (status=2) at /b/mnt/src/lib/libc/stdlib/exit.c:67
> #17 0x0000000000404df5 in terminate (signum=-26832) at /b/mnt/src/usr.sbin/rpcbind/rpcbind.c:860
> #18 0x000000080337f67b in handle_signal (actp=<optimized out>, sig=15, info=0x7fffffffa9f0, ucp=0x7fffffffa680) at /b/mnt/src/lib/libthr/thread/thr_sig.c:240
> #19 0x000000080337f263 in thr_sighandler (sig=15, info=0x7fffffffa9f0, _ucp=0x800700210) at /b/mnt/src/lib/libthr/thread/thr_sig.c:183

rpcbind got a sig 15 (TERM) and attempted to call exit(3) from a signal
handler.  But, exit(3) is not an async-signal safe function.  Probably these
crashes are the result of the program manipulating jemalloc internal structures
at the time the SIGTERM is delivered and handled unsafely.

The cause can be explained:

195         /* catch the usual termination signals for graceful exit */
196         (void) signal(SIGCHLD, reap);
197         (void) signal(SIGINT, terminate);
198         (void) signal(SIGTERM, terminate);
199         (void) signal(SIGQUIT, terminate);
...

758 /*
759  * Catch the signal and die
760  */
761 static void
762 terminate(int signum __unused)
763 {
764         close(rpcbindlockfd);
765 #ifdef WARMSTART
766         syslog(LOG_ERR,
767             "rpcbind terminating on signal %d. Restart with \"rpcbind
-w\"",
768             signum);
769         write_warmstart();      /* Dump yourself */
770 #endif
771         exit(2);
772 }
...

// close(2) is async-safe -- rpcbindlockfd must be initalized before the signal
is
// delivered, though.
//
// syslog() is definitely not safe.
//
// write_warmstart() uses fopen(3), syslog(3), ... definitely not safe.
//
// Finally, exit(3) itself is not safe either.

857 void
858 reap(int dummy __unused)
859 {
860         int save_errno = errno;
861
862         while (wait3(NULL, WNOHANG, NULL) > 0)
863                 ;
864         errno = save_errno;
865 }

// wait(2) and waitpid(2) are allowed, but wait3() is not documented as allowed
in
// sigaction(2).  It likely is allowed, though, given it is implemented
identically
// to wait(2) (in terms of wait4(2)).  So `reap` for SIGCHLD is probably ok.

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list