Page MenuHomeFreeBSD

D19058.id53521.diff
No OneTemporary

D19058.id53521.diff

Index: lib/libc/gen/posix_spawn.c
===================================================================
--- lib/libc/gen/posix_spawn.c
+++ lib/libc/gen/posix_spawn.c
@@ -200,10 +200,22 @@
const posix_spawnattr_t *sa,
char * const argv[], char * const envp[], int use_env_path)
{
+ sigset_t oset, set;
pid_t p;
volatile int error = 0;
+ /*
+ * Block all signals going into the vfork. The child should then
+ * reset all signals with handlers back to SIG_DFL so that some signal
+ * handler can't corrupt parent state in the brief period between
+ * entering the child and exec.
+ */
+ sigfillset(&set);
+ __libc_sigprocmask(SIG_BLOCK, &set, &oset);
p = vfork();
+ if (p == 0)
+ __libc_used_signal_reset();
+ __libc_sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
switch (p) {
case -1:
return (errno);
Index: lib/libc/include/libc_private.h
===================================================================
--- lib/libc/include/libc_private.h
+++ lib/libc/include/libc_private.h
@@ -390,6 +390,7 @@
__ssize_t __sys_write(int, const void *, __size_t);
__ssize_t __sys_writev(int, const struct iovec *, int);
+void __libc_used_signal_reset(void);
int __libc_sigaction(int, const struct sigaction *,
struct sigaction *) __hidden;
int __libc_sigprocmask(int, const __sigset_t *, __sigset_t *)
Index: lib/libc/sys/sigaction.c
===================================================================
--- lib/libc/sys/sigaction.c
+++ lib/libc/sys/sigaction.c
@@ -34,17 +34,47 @@
__FBSDID("$FreeBSD$");
#include <sys/types.h>
+#include <machine/atomic.h>
#include <signal.h>
+#include <stdlib.h>
#include "libc_private.h"
__weak_reference(__sys_sigaction, __sigaction);
__weak_reference(sigaction, __libc_sigaction);
+/*
+ * Used to track signals that are given a non-ignored handler so that other
+ * parts of libc, notably posix_spawn, can easily and safely reset these to
+ * default handler before unblocking signals again and proceeding without
+ * the possibility of a signal handler altering process state in the middle of
+ * the vfork.
+ *
+ * This set of used signals should not be treated as an ultimate source of
+ * truth, but rather as a 'best guess'.
+ */
+static uint32_t _used_sigs[_SIG_WORDS];
+
+void
+__libc_used_signal_reset(void)
+{
+ int sig;
+ struct sigaction sa;
+
+ sa.sa_handler = SIG_DFL;
+ for (sig = 1; sig < _SIG_MAXSIG; ++sig) {
+ if ((_used_sigs[_SIG_WORD(sig)] & _SIG_BIT(sig)) != 0)
+ __libc_sigaction(sig, &sa, NULL);
+ }
+}
+
#pragma weak sigaction
int
sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
{
+ if (act != NULL && _SIG_VALID(sig) &&
+ ((act->sa_flags & SA_SIGINFO) != 0 || act->sa_handler != SIG_IGN))
+ atomic_set_32(&_used_sigs[_SIG_WORD(sig)], _SIG_BIT(sig));
return (((int (*)(int, const struct sigaction *, struct sigaction *))
__libc_interposing[INTERPOS_sigaction])(sig, act, oact));
}

File Metadata

Mime Type
text/plain
Expires
Mon, Jul 6, 2:42 AM (9 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34732872
Default Alt Text
D19058.id53521.diff (2 KB)

Event Timeline