diff options
Diffstat (limited to 'src/VBox/Runtime/r3/posix/process-creation-posix.cpp')
-rw-r--r-- | src/VBox/Runtime/r3/posix/process-creation-posix.cpp | 71 |
1 files changed, 60 insertions, 11 deletions
diff --git a/src/VBox/Runtime/r3/posix/process-creation-posix.cpp b/src/VBox/Runtime/r3/posix/process-creation-posix.cpp index 2f8841c4..4fd2d0e2 100644 --- a/src/VBox/Runtime/r3/posix/process-creation-posix.cpp +++ b/src/VBox/Runtime/r3/posix/process-creation-posix.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -29,6 +29,8 @@ * Header Files * *******************************************************************************/ #define LOG_GROUP RTLOGGROUP_PROCESS +#include <iprt/cdefs.h> + #include <unistd.h> #include <stdlib.h> #include <errno.h> @@ -37,20 +39,28 @@ #include <sys/wait.h> #include <fcntl.h> #include <signal.h> +#include <grp.h> #if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) # include <crypt.h> # include <pwd.h> # include <shadow.h> #endif + #if defined(RT_OS_LINUX) || defined(RT_OS_OS2) /* While Solaris has posix_spawn() of course we don't want to use it as * we need to have the child in a different process contract, no matter * whether it is started detached or not. */ # define HAVE_POSIX_SPAWN 1 #endif +#if defined(RT_OS_DARWIN) && defined(MAC_OS_X_VERSION_MIN_REQUIRED) +# if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 +# define HAVE_POSIX_SPAWN 1 +# endif +#endif #ifdef HAVE_POSIX_SPAWN # include <spawn.h> #endif + #ifdef RT_OS_DARWIN # include <mach-o/dyld.h> #endif @@ -297,6 +307,10 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg AssertReturn(!pszAsUser || *pszAsUser, VERR_INVALID_PARAMETER); AssertReturn(!pszPassword || pszAsUser, VERR_INVALID_PARAMETER); AssertPtrNullReturn(pszPassword, VERR_INVALID_POINTER); +#if defined(RT_OS_OS2) + if (fFlags & RTPROC_FLAGS_DETACHED) + return VERR_PROC_DETACH_NOT_SUPPORTED; +#endif /* * Get the file descriptors for the handles we've been passed. @@ -462,20 +476,30 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg rc = posix_spawnattr_init(&Attr); if (!rc) { -# ifndef RT_OS_OS2 /* We don't need this on OS/2 and I don't recall if it's actually implemented. */ - rc = posix_spawnattr_setflags(&Attr, POSIX_SPAWN_SETPGROUP); + /* Indicate that process group and signal mask are to be changed, + and that the child should use default signal actions. */ + rc = posix_spawnattr_setflags(&Attr, POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF); Assert(rc == 0); + + /* The child starts in its own process group. */ if (!rc) { rc = posix_spawnattr_setpgroup(&Attr, 0 /* pg == child pid */); Assert(rc == 0); } -# endif + + /* Unmask all signals. */ + if (!rc) + { + sigset_t SigMask; + sigemptyset(&SigMask); + rc = posix_spawnattr_setsigmask(&Attr, &SigMask); Assert(rc == 0); + } /* File changes. */ posix_spawn_file_actions_t FileActions; posix_spawn_file_actions_t *pFileActions = NULL; - if (aStdFds[0] != -1 || aStdFds[1] != -1 || aStdFds[2] != -1) + if ((aStdFds[0] != -1 || aStdFds[1] != -1 || aStdFds[2] != -1) && !rc) { rc = posix_spawn_file_actions_init(&FileActions); if (!rc) @@ -525,7 +549,7 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg /* For a detached process this happens in the temp process, so * it's not worth doing anything as this process must exit. */ if (fFlags & RTPROC_FLAGS_DETACHED) - _Exit(0); + _Exit(0); if (phProcess) *phProcess = pid; return VINF_SUCCESS; @@ -540,15 +564,20 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg #endif { #ifdef RT_OS_SOLARIS - int templateFd = rtSolarisContractPreFork(); - if (templateFd == -1) - return VERR_OPEN_FAILED; + int templateFd = -1; + if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT)) + { + templateFd = rtSolarisContractPreFork(); + if (templateFd == -1) + return VERR_OPEN_FAILED; + } #endif /* RT_OS_SOLARIS */ pid = fork(); if (!pid) { #ifdef RT_OS_SOLARIS - rtSolarisContractPostForkChild(templateFd); + if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT)) + rtSolarisContractPostForkChild(templateFd); #endif /* RT_OS_SOLARIS */ if (!(fFlags & RTPROC_FLAGS_DETACHED)) setpgid(0, 0); /* see comment above */ @@ -557,6 +586,17 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg * Change group and user if requested. */ #if 1 /** @todo This needs more work, see suplib/hardening. */ + if (pszAsUser) + { + int ret = initgroups(pszAsUser, gid); + if (ret) + { + if (fFlags & RTPROC_FLAGS_DETACHED) + _Exit(126); + else + exit(126); + } + } if (gid != ~(gid_t)0) { if (setgid(gid)) @@ -581,6 +621,14 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg #endif /* + * Unset the signal mask. + */ + sigset_t SigMask; + sigemptyset(&SigMask); + rc = sigprocmask(SIG_SETMASK, &SigMask, NULL); + Assert(rc == 0); + + /* * Apply changes to the standard file descriptor and stuff. */ for (int i = 0; i < 3; i++) @@ -627,7 +675,8 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg exit(127); } #ifdef RT_OS_SOLARIS - rtSolarisContractPostForkParent(templateFd, pid); + if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT)) + rtSolarisContractPostForkParent(templateFd, pid); #endif /* RT_OS_SOLARIS */ if (pid > 0) { |