21#include <winpr/config.h>
23#include <winpr/handle.h>
24#include "../handle/nonehandle.h"
26#include <winpr/thread.h>
27#include <winpr/wlog.h>
55#include <winpr/assert.h>
57#include <winpr/path.h>
58#include <winpr/environment.h>
67#include <sys/syscall.h>
74#include "../security/security.h"
99static char* FindApplicationPath(
char* application)
101 LPCSTR pathName =
"PATH";
105 LPSTR lpSystemPath = NULL;
106 char* filename = NULL;
111 if (application[0] ==
'/')
112 return _strdup(application);
114 nSize = GetEnvironmentVariableA(pathName, NULL, 0);
117 return _strdup(application);
119 lpSystemPath = (LPSTR)malloc(nSize);
124 if (GetEnvironmentVariableA(pathName, lpSystemPath, nSize) != nSize - 1)
131 path = strtok_s(lpSystemPath,
":", &save);
135 filename = GetCombinedPath(path, application);
137 if (winpr_PathFileExists(filename))
144 path = strtok_s(NULL,
":", &save);
151static HANDLE CreateProcessHandle(pid_t pid);
152static BOOL ProcessHandleCloseHandle(HANDLE handle);
154static BOOL CreateProcessExA(HANDLE hToken, WINPR_ATTR_UNUSED DWORD dwLogonFlags,
155 LPCSTR lpApplicationName, WINPR_ATTR_UNUSED LPSTR lpCommandLine,
156 WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpProcessAttributes,
157 WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpThreadAttributes,
158 WINPR_ATTR_UNUSED BOOL bInheritHandles,
159 WINPR_ATTR_UNUSED DWORD dwCreationFlags, LPVOID lpEnvironment,
161 LPPROCESS_INFORMATION lpProcessInformation)
167 char* filename = NULL;
168 HANDLE thread = NULL;
169 HANDLE process = NULL;
170 WINPR_ACCESS_TOKEN* token = NULL;
171 LPTCH lpszEnvironmentBlock = NULL;
175 BOOL restoreSigMask = FALSE;
177 lpszEnvironmentBlock = NULL;
181 pArgs = CommandLineToArgvA(lpCommandLine, &numArgs);
183 pArgs = CommandLineToArgvA(lpApplicationName, &numArgs);
188 token = (WINPR_ACCESS_TOKEN*)hToken;
192 envp = EnvironmentBlockToEnvpA(lpEnvironment);
196 lpszEnvironmentBlock = GetEnvironmentStrings();
198 if (!lpszEnvironmentBlock)
201 envp = EnvironmentBlockToEnvpA(lpszEnvironmentBlock);
207 filename = FindApplicationPath(pArgs[0]);
209 if (NULL == filename)
213 sigfillset(&newSigMask);
214 restoreSigMask = !pthread_sigmask(SIG_SETMASK, &newSigMask, &oldSigMask);
230 sigset_t set = { 0 };
231 struct sigaction act = { 0 };
233 act.sa_handler = SIG_DFL;
235 sigemptyset(&act.sa_mask);
237 for (
int sig = 1; sig < NSIG; sig++)
238 sigaction(sig, &act, NULL);
242 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
247 handle_fd = winpr_Handle_getFd(lpStartupInfo->hStdOutput);
250 dup2(handle_fd, STDOUT_FILENO);
252 handle_fd = winpr_Handle_getFd(lpStartupInfo->hStdError);
255 dup2(handle_fd, STDERR_FILENO);
257 handle_fd = winpr_Handle_getFd(lpStartupInfo->hStdInput);
260 dup2(handle_fd, STDIN_FILENO);
267 maxfd = fcntl(0, F_MAXFD);
270 const long rc = sysconf(_SC_OPEN_MAX);
271 if ((rc < INT32_MIN) || (rc > INT32_MAX))
277 for (
int fd = 3; fd < maxfd; fd++)
286 int rc = setgid((gid_t)token->GroupId);
293 initgroups(token->Username, (gid_t)token->GroupId);
299 int rc = setuid((uid_t)token->UserId);
306 if (lpCurrentDirectory && strlen(lpCurrentDirectory) > 0)
308 int rc = chdir(lpCurrentDirectory);
313 if (execve(filename, pArgs, envp) < 0)
324 process = CreateProcessHandle(pid);
331 thread = CreateNoneHandle();
335 ProcessHandleCloseHandle(process);
339 lpProcessInformation->hProcess = process;
340 lpProcessInformation->hThread = thread;
341 lpProcessInformation->dwProcessId = (DWORD)pid;
342 lpProcessInformation->dwThreadId = (DWORD)pid;
348 pthread_sigmask(SIG_SETMASK, &oldSigMask, NULL);
353 if (lpszEnvironmentBlock)
354 FreeEnvironmentStrings(lpszEnvironmentBlock);
372BOOL CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine,
373 LPSECURITY_ATTRIBUTES lpProcessAttributes,
374 LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
375 DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
376 LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
378 return CreateProcessExA(NULL, 0, lpApplicationName, lpCommandLine, lpProcessAttributes,
379 lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
380 lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
383BOOL CreateProcessW(WINPR_ATTR_UNUSED LPCWSTR lpApplicationName,
384 WINPR_ATTR_UNUSED LPWSTR lpCommandLine,
385 WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpProcessAttributes,
386 WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpThreadAttributes,
387 WINPR_ATTR_UNUSED BOOL bInheritHandles, WINPR_ATTR_UNUSED DWORD dwCreationFlags,
388 WINPR_ATTR_UNUSED LPVOID lpEnvironment,
389 WINPR_ATTR_UNUSED LPCWSTR lpCurrentDirectory,
391 WINPR_ATTR_UNUSED LPPROCESS_INFORMATION lpProcessInformation)
393 WLog_ERR(
"TODO",
"TODO: implement");
397BOOL CreateProcessAsUserA(HANDLE hToken, LPCSTR lpApplicationName, LPSTR lpCommandLine,
398 LPSECURITY_ATTRIBUTES lpProcessAttributes,
399 LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
400 DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
401 LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
403 return CreateProcessExA(hToken, 0, lpApplicationName, lpCommandLine, lpProcessAttributes,
404 lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
405 lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
408BOOL CreateProcessAsUserW(WINPR_ATTR_UNUSED HANDLE hToken,
409 WINPR_ATTR_UNUSED LPCWSTR lpApplicationName,
410 WINPR_ATTR_UNUSED LPWSTR lpCommandLine,
411 WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpProcessAttributes,
412 WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpThreadAttributes,
413 WINPR_ATTR_UNUSED BOOL bInheritHandles,
414 WINPR_ATTR_UNUSED DWORD dwCreationFlags,
415 WINPR_ATTR_UNUSED LPVOID lpEnvironment,
416 WINPR_ATTR_UNUSED LPCWSTR lpCurrentDirectory,
418 WINPR_ATTR_UNUSED LPPROCESS_INFORMATION lpProcessInformation)
420 WLog_ERR(
"TODO",
"TODO: implement");
424BOOL CreateProcessWithLogonA(
425 WINPR_ATTR_UNUSED LPCSTR lpUsername, WINPR_ATTR_UNUSED LPCSTR lpDomain,
426 WINPR_ATTR_UNUSED LPCSTR lpPassword, WINPR_ATTR_UNUSED DWORD dwLogonFlags,
427 WINPR_ATTR_UNUSED LPCSTR lpApplicationName, WINPR_ATTR_UNUSED LPSTR lpCommandLine,
428 WINPR_ATTR_UNUSED DWORD dwCreationFlags, WINPR_ATTR_UNUSED LPVOID lpEnvironment,
429 WINPR_ATTR_UNUSED LPCSTR lpCurrentDirectory, WINPR_ATTR_UNUSED
LPSTARTUPINFOA lpStartupInfo,
430 WINPR_ATTR_UNUSED LPPROCESS_INFORMATION lpProcessInformation)
432 WLog_ERR(
"TODO",
"TODO: implement");
436BOOL CreateProcessWithLogonW(
437 WINPR_ATTR_UNUSED LPCWSTR lpUsername, WINPR_ATTR_UNUSED LPCWSTR lpDomain,
438 WINPR_ATTR_UNUSED LPCWSTR lpPassword, WINPR_ATTR_UNUSED DWORD dwLogonFlags,
439 WINPR_ATTR_UNUSED LPCWSTR lpApplicationName, WINPR_ATTR_UNUSED LPWSTR lpCommandLine,
440 WINPR_ATTR_UNUSED DWORD dwCreationFlags, WINPR_ATTR_UNUSED LPVOID lpEnvironment,
441 WINPR_ATTR_UNUSED LPCWSTR lpCurrentDirectory, WINPR_ATTR_UNUSED
LPSTARTUPINFOW lpStartupInfo,
442 WINPR_ATTR_UNUSED LPPROCESS_INFORMATION lpProcessInformation)
444 WLog_ERR(
"TODO",
"TODO: implement");
448BOOL CreateProcessWithTokenA(WINPR_ATTR_UNUSED HANDLE hToken, WINPR_ATTR_UNUSED DWORD dwLogonFlags,
449 LPCSTR lpApplicationName, LPSTR lpCommandLine, DWORD dwCreationFlags,
450 LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
452 LPPROCESS_INFORMATION lpProcessInformation)
454 return CreateProcessExA(NULL, 0, lpApplicationName, lpCommandLine, NULL, NULL, FALSE,
455 dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo,
456 lpProcessInformation);
459BOOL CreateProcessWithTokenW(WINPR_ATTR_UNUSED HANDLE hToken, WINPR_ATTR_UNUSED DWORD dwLogonFlags,
460 WINPR_ATTR_UNUSED LPCWSTR lpApplicationName,
461 WINPR_ATTR_UNUSED LPWSTR lpCommandLine,
462 WINPR_ATTR_UNUSED DWORD dwCreationFlags,
463 WINPR_ATTR_UNUSED LPVOID lpEnvironment,
464 WINPR_ATTR_UNUSED LPCWSTR lpCurrentDirectory,
466 WINPR_ATTR_UNUSED LPPROCESS_INFORMATION lpProcessInformation)
468 WLog_ERR(
"TODO",
"TODO: implement");
472VOID ExitProcess(UINT uExitCode)
475 exit((
int)uExitCode);
478BOOL GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode)
489 *lpExitCode = process->dwExitCode;
493HANDLE _GetCurrentProcess(VOID)
495 WLog_ERR(
"TODO",
"TODO: implement");
499DWORD GetCurrentProcessId(VOID)
501 return ((DWORD)getpid());
504BOOL TerminateProcess(HANDLE hProcess, WINPR_ATTR_UNUSED UINT uExitCode)
509 if (!process || (process->pid <= 0))
512 if (kill(process->pid, SIGTERM))
518static BOOL ProcessHandleCloseHandle(HANDLE handle)
521 WINPR_ASSERT(process);
522 if (process->fd >= 0)
531static BOOL ProcessHandleIsHandle(HANDLE handle)
533 return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_PROCESS, FALSE);
536static int ProcessGetFd(HANDLE handle)
540 if (!ProcessHandleIsHandle(handle))
546static DWORD ProcessCleanupHandle(HANDLE handle)
550 WINPR_ASSERT(process);
553 if (waitpid(process->pid, &process->status, WNOHANG) == process->pid)
554 process->dwExitCode = (DWORD)process->status;
556 return WAIT_OBJECT_0;
559static HANDLE_OPS ops = { ProcessHandleIsHandle,
560 ProcessHandleCloseHandle,
562 ProcessCleanupHandle,
581static int pidfd_open(pid_t pid)
584#if !defined(__NR_pidfd_open)
585#define __NR_pidfd_open 434
588#ifndef PIDFD_NONBLOCK
589#define PIDFD_NONBLOCK O_NONBLOCK
592 long fd = syscall(__NR_pidfd_open, pid, PIDFD_NONBLOCK);
593 if (fd < 0 && errno == EINVAL)
598 fd = syscall(__NR_pidfd_open, pid, 0);
599 if ((fd < 0) || (fd > INT32_MAX))
602 flags = fcntl((
int)fd, F_GETFL);
603 if ((flags < 0) || fcntl((
int)fd, F_SETFL, flags | O_NONBLOCK) < 0)
609 if ((fd < 0) || (fd > INT32_MAX))
617HANDLE CreateProcessHandle(pid_t pid)
626 process->common.Type = HANDLE_TYPE_PROCESS;
627 process->common.ops = &ops;
628 process->fd = pidfd_open(pid);
629 if (process->fd >= 0)
630 process->common.Mode = WINPR_FD_READ;
631 return (HANDLE)process;