21 #include <winpr/config.h>
23 #include <winpr/handle.h>
24 #include "../handle/nonehandle.h"
26 #include <winpr/thread.h>
54 #include <winpr/assert.h>
55 #include <winpr/crt.h>
56 #include <winpr/path.h>
57 #include <winpr/environment.h>
62 #include <sys/types.h>
66 #include <sys/syscall.h>
73 #include "../security/security.h"
98 static char* FindApplicationPath(
char* application)
100 LPCSTR pathName =
"PATH";
104 LPSTR lpSystemPath = NULL;
105 char* filename = NULL;
110 if (application[0] ==
'/')
111 return _strdup(application);
113 nSize = GetEnvironmentVariableA(pathName, NULL, 0);
116 return _strdup(application);
118 lpSystemPath = (LPSTR)malloc(nSize);
123 if (GetEnvironmentVariableA(pathName, lpSystemPath, nSize) != nSize - 1)
130 path = strtok_s(lpSystemPath,
":", &save);
134 filename = GetCombinedPath(path, application);
136 if (winpr_PathFileExists(filename))
143 path = strtok_s(NULL,
":", &save);
150 static HANDLE CreateProcessHandle(pid_t pid);
151 static BOOL ProcessHandleCloseHandle(HANDLE handle);
153 static BOOL CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, LPCSTR lpApplicationName,
154 LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
155 LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
156 DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
158 LPPROCESS_INFORMATION lpProcessInformation)
164 char* filename = NULL;
165 HANDLE thread = NULL;
166 HANDLE process = NULL;
167 WINPR_ACCESS_TOKEN* token = NULL;
168 LPTCH lpszEnvironmentBlock = NULL;
172 BOOL restoreSigMask = FALSE;
174 lpszEnvironmentBlock = NULL;
178 pArgs = CommandLineToArgvA(lpCommandLine, &numArgs);
180 pArgs = CommandLineToArgvA(lpApplicationName, &numArgs);
185 token = (WINPR_ACCESS_TOKEN*)hToken;
189 envp = EnvironmentBlockToEnvpA(lpEnvironment);
193 lpszEnvironmentBlock = GetEnvironmentStrings();
195 if (!lpszEnvironmentBlock)
198 envp = EnvironmentBlockToEnvpA(lpszEnvironmentBlock);
204 filename = FindApplicationPath(pArgs[0]);
206 if (NULL == filename)
210 sigfillset(&newSigMask);
211 restoreSigMask = !pthread_sigmask(SIG_SETMASK, &newSigMask, &oldSigMask);
227 sigset_t set = { 0 };
228 struct sigaction act = { 0 };
230 act.sa_handler = SIG_DFL;
232 sigemptyset(&act.sa_mask);
234 for (
int sig = 1; sig < NSIG; sig++)
235 sigaction(sig, &act, NULL);
239 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
244 handle_fd = winpr_Handle_getFd(lpStartupInfo->hStdOutput);
247 dup2(handle_fd, STDOUT_FILENO);
249 handle_fd = winpr_Handle_getFd(lpStartupInfo->hStdError);
252 dup2(handle_fd, STDERR_FILENO);
254 handle_fd = winpr_Handle_getFd(lpStartupInfo->hStdInput);
257 dup2(handle_fd, STDIN_FILENO);
264 maxfd = fcntl(0, F_MAXFD);
267 const long rc = sysconf(_SC_OPEN_MAX);
268 if ((rc < INT32_MIN) || (rc > INT32_MAX))
274 for (
int fd = 3; fd < maxfd; fd++)
283 int rc = setgid((gid_t)token->GroupId);
290 initgroups(token->Username, (gid_t)token->GroupId);
296 int rc = setuid((uid_t)token->UserId);
303 if (lpCurrentDirectory && strlen(lpCurrentDirectory) > 0)
305 int rc = chdir(lpCurrentDirectory);
310 if (execve(filename, pArgs, envp) < 0)
321 process = CreateProcessHandle(pid);
328 thread = CreateNoneHandle();
332 ProcessHandleCloseHandle(process);
336 lpProcessInformation->hProcess = process;
337 lpProcessInformation->hThread = thread;
338 lpProcessInformation->dwProcessId = (DWORD)pid;
339 lpProcessInformation->dwThreadId = (DWORD)pid;
345 pthread_sigmask(SIG_SETMASK, &oldSigMask, NULL);
350 if (lpszEnvironmentBlock)
351 FreeEnvironmentStrings(lpszEnvironmentBlock);
369 BOOL CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine,
370 LPSECURITY_ATTRIBUTES lpProcessAttributes,
371 LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
372 DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
373 LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
375 return CreateProcessExA(NULL, 0, lpApplicationName, lpCommandLine, lpProcessAttributes,
376 lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
377 lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
380 BOOL CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
381 LPSECURITY_ATTRIBUTES lpProcessAttributes,
382 LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
383 DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
384 LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
389 BOOL CreateProcessAsUserA(HANDLE hToken, LPCSTR lpApplicationName, LPSTR lpCommandLine,
390 LPSECURITY_ATTRIBUTES lpProcessAttributes,
391 LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
392 DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
393 LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
395 return CreateProcessExA(hToken, 0, lpApplicationName, lpCommandLine, lpProcessAttributes,
396 lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
397 lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
400 BOOL CreateProcessAsUserW(HANDLE hToken, LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
401 LPSECURITY_ATTRIBUTES lpProcessAttributes,
402 LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
403 DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
404 LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
409 BOOL CreateProcessWithLogonA(LPCSTR lpUsername, LPCSTR lpDomain, LPCSTR lpPassword,
410 DWORD dwLogonFlags, LPCSTR lpApplicationName, LPSTR lpCommandLine,
411 DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
413 LPPROCESS_INFORMATION lpProcessInformation)
418 BOOL CreateProcessWithLogonW(LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword,
419 DWORD dwLogonFlags, LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
420 DWORD dwCreationFlags, LPVOID lpEnvironment,
422 LPPROCESS_INFORMATION lpProcessInformation)
427 BOOL CreateProcessWithTokenA(HANDLE hToken, DWORD dwLogonFlags, LPCSTR lpApplicationName,
428 LPSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
430 LPPROCESS_INFORMATION lpProcessInformation)
432 return CreateProcessExA(NULL, 0, lpApplicationName, lpCommandLine, NULL, NULL, FALSE,
433 dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo,
434 lpProcessInformation);
437 BOOL CreateProcessWithTokenW(HANDLE hToken, DWORD dwLogonFlags, LPCWSTR lpApplicationName,
438 LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
440 LPPROCESS_INFORMATION lpProcessInformation)
445 VOID ExitProcess(UINT uExitCode)
447 exit((
int)uExitCode);
450 BOOL GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode)
461 *lpExitCode = process->dwExitCode;
465 HANDLE _GetCurrentProcess(VOID)
470 DWORD GetCurrentProcessId(VOID)
472 return ((DWORD)getpid());
475 BOOL TerminateProcess(HANDLE hProcess, UINT uExitCode)
480 if (!process || (process->pid <= 0))
483 if (kill(process->pid, SIGTERM))
489 static BOOL ProcessHandleCloseHandle(HANDLE handle)
492 WINPR_ASSERT(process);
493 if (process->fd >= 0)
502 static BOOL ProcessHandleIsHandle(HANDLE handle)
504 return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_PROCESS, FALSE);
507 static int ProcessGetFd(HANDLE handle)
511 if (!ProcessHandleIsHandle(handle))
517 static DWORD ProcessCleanupHandle(HANDLE handle)
521 WINPR_ASSERT(process);
524 if (waitpid(process->pid, &process->status, WNOHANG) == process->pid)
525 process->dwExitCode = (DWORD)process->status;
527 return WAIT_OBJECT_0;
530 static HANDLE_OPS ops = { ProcessHandleIsHandle,
531 ProcessHandleCloseHandle,
533 ProcessCleanupHandle,
552 static int pidfd_open(pid_t pid)
555 #if !defined(__NR_pidfd_open)
556 #define __NR_pidfd_open 434
559 #ifndef PIDFD_NONBLOCK
560 #define PIDFD_NONBLOCK O_NONBLOCK
563 long fd = syscall(__NR_pidfd_open, pid, PIDFD_NONBLOCK);
564 if (fd < 0 && errno == EINVAL)
569 fd = syscall(__NR_pidfd_open, pid, 0);
570 if ((fd < 0) || (fd > INT32_MAX))
573 flags = fcntl((
int)fd, F_GETFL);
574 if ((flags < 0) || fcntl((
int)fd, F_SETFL, flags | O_NONBLOCK) < 0)
580 if ((fd < 0) || (fd > INT32_MAX))
588 HANDLE CreateProcessHandle(pid_t pid)
597 process->common.Type = HANDLE_TYPE_PROCESS;
598 process->common.ops = &ops;
599 process->fd = pidfd_open(pid);
600 if (process->fd >= 0)
601 process->common.Mode = WINPR_FD_READ;
602 return (HANDLE)process;