* Create a restricted token, a job object sandbox, and execute the specified * process with it. * * Returns 0 on success, non-zero on failure, same as CreateProcess(). * * On NT4, or any other system not containing the required functions, will * launch the process under the current token without doing any modifications. * * NOTE! Job object will only work when running as a service, because
| 2013 | * automatically destroyed when pg_ctl exits. |
| 2014 | */ |
| 2015 | static int |
| 2016 | CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, bool as_service) |
| 2017 | { |
| 2018 | int r; |
| 2019 | BOOL b; |
| 2020 | STARTUPINFO si; |
| 2021 | HANDLE origToken; |
| 2022 | HANDLE restrictedToken; |
| 2023 | SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; |
| 2024 | SID_AND_ATTRIBUTES dropSids[2]; |
| 2025 | PTOKEN_PRIVILEGES delPrivs; |
| 2026 | |
| 2027 | /* Functions loaded dynamically */ |
| 2028 | __CreateRestrictedToken _CreateRestrictedToken = NULL; |
| 2029 | __IsProcessInJob _IsProcessInJob = NULL; |
| 2030 | __CreateJobObject _CreateJobObject = NULL; |
| 2031 | __SetInformationJobObject _SetInformationJobObject = NULL; |
| 2032 | __AssignProcessToJobObject _AssignProcessToJobObject = NULL; |
| 2033 | __QueryInformationJobObject _QueryInformationJobObject = NULL; |
| 2034 | HANDLE Kernel32Handle; |
| 2035 | HANDLE Advapi32Handle; |
| 2036 | |
| 2037 | ZeroMemory(&si, sizeof(si)); |
| 2038 | si.cb = sizeof(si); |
| 2039 | |
| 2040 | Advapi32Handle = LoadLibrary("ADVAPI32.DLL"); |
| 2041 | if (Advapi32Handle != NULL) |
| 2042 | { |
| 2043 | _CreateRestrictedToken = (__CreateRestrictedToken) (pg_funcptr_t) GetProcAddress(Advapi32Handle, "CreateRestrictedToken"); |
| 2044 | } |
| 2045 | |
| 2046 | if (_CreateRestrictedToken == NULL) |
| 2047 | { |
| 2048 | /* |
| 2049 | * NT4 doesn't have CreateRestrictedToken, so just call ordinary |
| 2050 | * CreateProcess |
| 2051 | */ |
| 2052 | write_stderr(_("%s: WARNING: cannot create restricted tokens on this platform\n"), progname); |
| 2053 | if (Advapi32Handle != NULL) |
| 2054 | FreeLibrary(Advapi32Handle); |
| 2055 | return CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, processInfo); |
| 2056 | } |
| 2057 | |
| 2058 | /* Open the current token to use as a base for the restricted one */ |
| 2059 | if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken)) |
| 2060 | { |
| 2061 | /* |
| 2062 | * Most Windows targets make DWORD a 32-bit unsigned long, but in case |
| 2063 | * it doesn't cast DWORD before printing. |
| 2064 | */ |
| 2065 | write_stderr(_("%s: could not open process token: error code %lu\n"), |
| 2066 | progname, (unsigned long) GetLastError()); |
| 2067 | return 0; |
| 2068 | } |
| 2069 | |
| 2070 | /* Allocate list of SIDs to remove */ |
| 2071 | ZeroMemory(&dropSids, sizeof(dropSids)); |
| 2072 | if (!AllocateAndInitializeSid(&NtAuthority, 2, |