X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=src%2Fprocess%2Fposix_spawn.c;h=f675a13c37dbb59c2e912854ea854f35d0bc31c1;hb=8011614da008032642aa8292c3fd079bf7a8843d;hp=dd4501298cb545eaedcd8aa35c32688a91142a11;hpb=4862864fc1a6d162b297db09c216b136db83d7dd;p=musl diff --git a/src/process/posix_spawn.c b/src/process/posix_spawn.c index dd450129..f675a13c 100644 --- a/src/process/posix_spawn.c +++ b/src/process/posix_spawn.c @@ -10,12 +10,6 @@ #include "fdop.h" #include "libc.h" -static void dummy_0() -{ -} -weak_alias(dummy_0, __acquire_ptc); -weak_alias(dummy_0, __release_ptc); - struct args { int p[2]; sigset_t oldmask; @@ -26,29 +20,43 @@ struct args { char *const *argv, *const *envp; }; +void __get_handler_set(sigset_t *); + static int child(void *args_vp) { int i, ret; - struct sigaction sa; + struct sigaction sa = {0}; struct args *args = args_vp; int p = args->p[1]; const posix_spawn_file_actions_t *fa = args->fa; const posix_spawnattr_t *restrict attr = args->attr; + sigset_t hset; close(args->p[0]); /* All signal dispositions must be either SIG_DFL or SIG_IGN * before signals are unblocked. Otherwise a signal handler * from the parent might get run in the child while sharing - * memory, with unpredictable and dangerous results. */ + * memory, with unpredictable and dangerous results. To + * reduce overhead, sigaction has tracked for us which signals + * potentially have a signal handler. */ + __get_handler_set(&hset); for (i=1; i<_NSIG; i++) { - __libc_sigaction(i, 0, &sa); - if (sa.sa_handler!=SIG_DFL && (sa.sa_handler!=SIG_IGN || - ((attr->__flags & POSIX_SPAWN_SETSIGDEF) - && sigismember(&attr->__def, i) ))) { + if ((attr->__flags & POSIX_SPAWN_SETSIGDEF) + && sigismember(&attr->__def, i)) { sa.sa_handler = SIG_DFL; - __libc_sigaction(i, &sa, 0); + } else if (sigismember(&hset, i)) { + if (i-32<3U) { + sa.sa_handler = SIG_IGN; + } else { + __libc_sigaction(i, 0, &sa); + if (sa.sa_handler==SIG_IGN) continue; + sa.sa_handler = SIG_DFL; + } + } else { + continue; } + __libc_sigaction(i, &sa, 0); } if (attr->__flags & POSIX_SPAWN_SETPGROUP) @@ -111,6 +119,7 @@ static int child(void *args_vp) ? &attr->__mask : &args->oldmask, 0); args->exec(args->path, args->argv, args->envp); + ret = -errno; fail: /* Since sizeof errno < PIPE_BUF, the write is atomic. */ @@ -144,11 +153,8 @@ int __posix_spawnx(pid_t *restrict res, const char *restrict path, args.envp = envp; pthread_sigmask(SIG_BLOCK, SIGALL_SET, &args.oldmask); - /* This lock prevents setuid/setgid operations while the parent - * is sharing memory with the child. Situations where processes - * with different permissions share VM are fundamentally unsafe. */ - __acquire_ptc(); - pid = __clone(child, stack+sizeof stack, CLONE_VM|SIGCHLD, &args); + pid = __clone(child, stack+sizeof stack, + CLONE_VM|CLONE_VFORK|SIGCHLD, &args); close(args.p[1]); if (pid > 0) { @@ -158,12 +164,9 @@ int __posix_spawnx(pid_t *restrict res, const char *restrict path, ec = -pid; } - /* At this point, the child has either exited or successfully - * performed exec, so the lock may be released. */ - __release_ptc(); close(args.p[0]); - if (!ec) *res = pid; + if (!ec && res) *res = pid; pthread_sigmask(SIG_SETMASK, &args.oldmask, 0); pthread_setcancelstate(cs, 0);