Mercurial > illumos > git > illumos-omnios
changeset 18381:0c39f4745dad
OS-4127 lx brand: clone(CLONE_VFORK) followed by sigaction corrupts parent
author | Bryan Cantrill <bryan@joyent.com> |
---|---|
date | Mon, 30 Mar 2015 23:18:47 +0000 |
parents | 1c328f69e981 |
children | 1798e9cce90e |
files | usr/src/lib/brand/lx/lx_brand/common/clone.c usr/src/lib/brand/lx/lx_brand/common/signal.c usr/src/lib/brand/lx/lx_brand/sys/lx_signal.h |
diffstat | 3 files changed, 31 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/lib/brand/lx/lx_brand/common/clone.c Mon Mar 30 14:49:36 2015 +0000 +++ b/usr/src/lib/brand/lx/lx_brand/common/clone.c Mon Mar 30 23:18:47 2015 +0000 @@ -421,10 +421,26 @@ _sigoff(); lx_stack_prefork(); if (flags & LX_CLONE_VFORK) { + lx_sighandlers_t saved; + + /* + * Because we keep our signal disposition at user-land + * (and in memory), we must prevent it from being + * clobbered should our vforked child change the + * disposition (e.g., via sigaction()) before releasing + * the address space. We preserve our disposition by + * taking a snapshot of it before the vfork and + * restoring it afterwards -- which we can get away + * with because we know that we aren't executing + * concurrently with our child. + */ + lx_sighandlers_save(&saved); is_vforked++; rval = vforkx(fork_flags); - if (rval != 0) + if (rval != 0) { is_vforked--; + lx_sighandlers_restore(&saved); + } } else { rval = forkx(fork_flags); }
--- a/usr/src/lib/brand/lx/lx_brand/common/signal.c Mon Mar 30 14:49:36 2015 +0000 +++ b/usr/src/lib/brand/lx/lx_brand/common/signal.c Mon Mar 30 23:18:47 2015 +0000 @@ -2044,6 +2044,18 @@ } #endif +void +lx_sighandlers_save(lx_sighandlers_t *saved) +{ + bcopy(&lx_sighandlers, saved, sizeof (lx_sighandlers_t)); +} + +void +lx_sighandlers_restore(lx_sighandlers_t *saved) +{ + bcopy(saved, &lx_sighandlers, sizeof (lx_sighandlers_t)); +} + int lx_siginit(void) {
--- a/usr/src/lib/brand/lx/lx_brand/sys/lx_signal.h Mon Mar 30 14:49:36 2015 +0000 +++ b/usr/src/lib/brand/lx/lx_brand/sys/lx_signal.h Mon Mar 30 23:18:47 2015 +0000 @@ -292,6 +292,8 @@ int (*)(const ucontext_t *)); extern int lx_siginit(void); +extern void lx_sighandlers_save(lx_sighandlers_t *); +extern void lx_sighandlers_restore(lx_sighandlers_t *); extern int stol_siginfo(siginfo_t *siginfop, lx_siginfo_t *lx_siginfop); extern int stol_status(int);