summaryrefslogtreecommitdiff
path: root/src/process
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2012-10-15 11:42:46 -0400
committerRich Felker <dalias@aerifal.cx>2012-10-15 11:42:46 -0400
commitd5304147b983f309ed0c9050e3b8b6f2c9f87f43 (patch)
treee388817e710423d6b27ce1b8c6a354c34a4f09e4 /src/process
parent42c36f957d54926eec87b072a73439b9a1539347 (diff)
downloadmusl-d5304147b983f309ed0c9050e3b8b6f2c9f87f43.tar.gz
musl-d5304147b983f309ed0c9050e3b8b6f2c9f87f43.tar.bz2
musl-d5304147b983f309ed0c9050e3b8b6f2c9f87f43.tar.xz
musl-d5304147b983f309ed0c9050e3b8b6f2c9f87f43.zip
block uid/gid changes during posix_spawn
usage of vfork creates a situation where a process of lower privilege may momentarily have write access to the memory of a process of higher privilege. consider the case of a multi-threaded suid program which is calling posix_spawn in one thread while another thread drops the elevated privileges then runs untrusted (relative to the elevated privilege) code as the original invoking user. this untrusted code can then potentially modify the data the child process will use before calling exec, for example changing the pathname or arguments that will be passed to exec. note that if vfork is implemented as fork, the lock will not be held until the child execs, but since memory is not shared it does not matter.
Diffstat (limited to 'src/process')
-rw-r--r--src/process/posix_spawn.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/src/process/posix_spawn.c b/src/process/posix_spawn.c
index 604756e9..8a6ff6db 100644
--- a/src/process/posix_spawn.c
+++ b/src/process/posix_spawn.c
@@ -5,9 +5,16 @@
#include <fcntl.h>
#include "syscall.h"
#include "fdop.h"
+#include "libc.h"
extern char **environ;
+static void dummy_0()
+{
+}
+weak_alias(dummy_0, __acquire_ptc);
+weak_alias(dummy_0, __release_ptc);
+
pid_t __vfork(void);
int __posix_spawnx(pid_t *restrict res, const char *restrict path,
@@ -24,7 +31,10 @@ int __posix_spawnx(pid_t *restrict res, const char *restrict path,
if (!attr) attr = &dummy_attr;
sigprocmask(SIG_BLOCK, (void *)(uint64_t []){-1}, &oldmask);
+
+ __acquire_ptc();
pid = __vfork();
+ __release_ptc();
if (pid) {
sigprocmask(SIG_SETMASK, &oldmask, 0);