move POSIX spawn, exec and child tracking into posixsrv, keep process transactions alive across reconnects and preserve stable PIDs across image replacement, flesh out spawn with ordered file actions, process-group selection and signal inheritance, implement execve with bootstrap validation and rollback before retiring the old process, add vfork children that share the native process while keeping separate POSIX descriptor and signal state, replace local spawn bookkeeping with child reaping, nonblocking and process-group waits and orphan cleanup, add signal dispositions, per-thread masks, pending delivery, process/group signalling and alarms, translate native exceptions into POSIX signals and inherit masks when creating threads, make pipe waits interruptible and raise SIGPIPE for broken pipes, pass arguments and environment into main and add getenv/environ, add direct user APC notifications that can run without an alertable wait, add current-thread capabilities and resume-and-wait, let accepted IPC endpoints open restricted peer process capabilities and preserve caller security during spawn and exec, make process preparation reusable and improve DLL lookup across current, executable and fallback directories, move keyboard repeat into RSSRV so PS/2 and USB share one repeat policy, fix video presentation, report launch failure stages and status codes, mooaaar tests.
This commit is contained in:
1 parent
73abd6f90d
commit
899225f551
57 files changed
+8817
-1216
No files matched your search
@@ -33,6 +33,9 @@ typedef void (*PKRUNDOWN_ROUTINE)(KAPC* apc);
|
||||
|
||||
typedef struct KUSER_APC KUSER_APC;
|
||||
|
||||
#define KE_USER_APC_FLAG_NONE 0x00000000u
|
||||
#define KE_USER_APC_FLAG_INTERRUPT 0x00000001u
|
||||
|
||||
typedef struct SYS_USER_APC_FRAME_K {
|
||||
uint64_t Magic;
|
||||
uint64_t ReturnToken;
|
||||
@@ -50,6 +53,7 @@ struct KUSER_APC {
|
||||
void* NormalContext;
|
||||
void* SystemArgument1;
|
||||
void* SystemArgument2;
|
||||
uint32_t Flags;
|
||||
};
|
||||
|
||||
struct KAPC {
|
||||
@@ -92,7 +96,8 @@ __declspec(dllexport) KSTATUS KeQueueUserApc(THREAD* thread,
|
||||
void* routine,
|
||||
void* normalContext,
|
||||
void* systemArgument1,
|
||||
void* systemArgument2);
|
||||
void* systemArgument2,
|
||||
uint32_t flags);
|
||||
__declspec(dllexport) uint64_t KeUserApcReturn(const SYS_USER_APC_FRAME_K* frame);
|
||||
|
||||
void KiRundownApcState(THREAD* thread);
|
||||
|
||||
@@ -28,7 +28,7 @@ typedef struct KE_PORT_STATS {
|
||||
void KePortQueryStats(KE_PORT_STATS* statsOut);
|
||||
|
||||
// Creates one waitable connection-listener Port.
|
||||
KSTATUS KePortCreate(uint32_t backlog, PORT** portOut);
|
||||
KSTATUS KePortCreate(uint32_t backlog, SYS_RIGHTS peerProcessRights, PORT** portOut);
|
||||
|
||||
// Returns whether one Port object is a listener rather than a connected endpoint.
|
||||
bool KePortIsListener(const PORT* port);
|
||||
@@ -96,3 +96,9 @@ KSTATUS KePortReply(PORT* endpoint,
|
||||
|
||||
// Disconnects one endpoint and wakes peer waiters and pending synchronous callers.
|
||||
KSTATUS KePortDisconnect(PORT* endpoint);
|
||||
|
||||
// Opens a capability to the process bound as the peer of an authorized accepted endpoint.
|
||||
KSTATUS KePortOpenPeerProcess(PORT* endpoint,
|
||||
struct PROCESS* callerProcess,
|
||||
SYS_RIGHTS desiredRights,
|
||||
SYS_HANDLE* processHandleOut);
|
||||
@@ -20,187 +20,193 @@
|
||||
#define SYS_GET_PROCESS_LIST 9
|
||||
#define SYS_GET_PROCESS_PID 10
|
||||
#define SYS_CREATE_THREAD 11
|
||||
#define SYS_RESUME_THREAD 12
|
||||
#define SYS_GET_THREAD_LIST 13
|
||||
#define SYS_GET_CURRENT_TID 14
|
||||
#define SYS_GET_CURRENT_PID 15
|
||||
#define SYS_SET_THREAD_PRIORITY 16
|
||||
#define SYS_SET_THREAD_NAME 17
|
||||
#define SYS_QUERY_THREAD_NAME 18
|
||||
#define SYS_YIELD 19
|
||||
#define SYS_SLEEP 20
|
||||
#define SYS_WAIT_SINGLE 21
|
||||
#define SYS_WAIT_MANY 22
|
||||
#define SYS_SET_USER_APC_DISPATCHER 23
|
||||
#define SYS_APC_RETURN 24
|
||||
#define SYS_SET_EXCEPTION_DISPATCHER 25
|
||||
#define SYS_GET_EXCEPTION_DISPATCHER 26
|
||||
#define SYS_CONTINUE_EXCEPTION 27
|
||||
#define SYS_RAISE_EXCEPTION 28
|
||||
#define SYS_OPEN_CURRENT_THREAD 12
|
||||
#define SYS_RESUME_THREAD 13
|
||||
#define SYS_RESUME_THREAD_AND_WAIT 14
|
||||
#define SYS_GET_THREAD_LIST 15
|
||||
#define SYS_GET_THREAD_TID 16
|
||||
#define SYS_GET_CURRENT_TID 17
|
||||
#define SYS_GET_CURRENT_PID 18
|
||||
#define SYS_SET_THREAD_PRIORITY 19
|
||||
#define SYS_SET_THREAD_NAME 20
|
||||
#define SYS_QUERY_THREAD_NAME 21
|
||||
#define SYS_YIELD 22
|
||||
#define SYS_SLEEP 23
|
||||
#define SYS_WAIT_SINGLE 24
|
||||
#define SYS_WAIT_MANY 25
|
||||
#define SYS_SET_USER_APC_DISPATCHER 26
|
||||
#define SYS_QUEUE_USER_APC 27
|
||||
#define SYS_APC_RETURN 28
|
||||
#define SYS_SET_EXCEPTION_DISPATCHER 29
|
||||
#define SYS_GET_EXCEPTION_DISPATCHER 30
|
||||
#define SYS_CONTINUE_EXCEPTION 31
|
||||
#define SYS_RAISE_EXCEPTION 32
|
||||
|
||||
// Virtual memory, mappings, and handles.
|
||||
#define SYS_ALLOC_VM 29
|
||||
#define SYS_FREE_VM 30
|
||||
#define SYS_PROTECT_VM 31
|
||||
#define SYS_QUERY_VM 32
|
||||
#define SYS_CLOSE_HANDLE 33
|
||||
#define SYS_DUPLICATE_HANDLE 34
|
||||
#define SYS_DERIVE_HANDLE 35
|
||||
#define SYS_REVOKE_HANDLE 36
|
||||
#define SYS_DERIVE_SECURITY_CONTEXT 37
|
||||
#define SYS_QUERY_SECURITY_CONTEXT 38
|
||||
#define SYS_CREATE_FILE_MAPPING 39
|
||||
#define SYS_MAP_FILE 40
|
||||
#define SYS_ALLOC_VM 33
|
||||
#define SYS_FREE_VM 34
|
||||
#define SYS_PROTECT_VM 35
|
||||
#define SYS_QUERY_VM 36
|
||||
#define SYS_CLOSE_HANDLE 37
|
||||
#define SYS_DUPLICATE_HANDLE 38
|
||||
#define SYS_DERIVE_HANDLE 39
|
||||
#define SYS_REVOKE_HANDLE 40
|
||||
#define SYS_DERIVE_SECURITY_CONTEXT 41
|
||||
#define SYS_QUERY_SECURITY_CONTEXT 42
|
||||
#define SYS_OPEN_PROCESS_SECURITY_CONTEXT 43
|
||||
#define SYS_CREATE_FILE_MAPPING 44
|
||||
#define SYS_MAP_FILE 45
|
||||
|
||||
// Synchronization objects.
|
||||
#define SYS_CREATE_MUTEX 41
|
||||
#define SYS_TRY_ACQUIRE_MUTEX 42
|
||||
#define SYS_RELEASE_MUTEX 43
|
||||
#define SYS_CREATE_SEM 44
|
||||
#define SYS_TRY_WAIT_SEM 45
|
||||
#define SYS_SIGNAL_SEM 46
|
||||
#define SYS_CREATE_EVENT 47
|
||||
#define SYS_SIGNAL_EVENT 48
|
||||
#define SYS_CLEAR_EVENT 49
|
||||
#define SYS_CREATE_MUTEX 46
|
||||
#define SYS_TRY_ACQUIRE_MUTEX 47
|
||||
#define SYS_RELEASE_MUTEX 48
|
||||
#define SYS_CREATE_SEM 49
|
||||
#define SYS_TRY_WAIT_SEM 50
|
||||
#define SYS_SIGNAL_SEM 51
|
||||
#define SYS_CREATE_EVENT 52
|
||||
#define SYS_SIGNAL_EVENT 53
|
||||
#define SYS_CLEAR_EVENT 54
|
||||
|
||||
// Queues and named queues.
|
||||
#define SYS_CREATE_QUEUE 50
|
||||
#define SYS_SEND_QUEUE 51
|
||||
#define SYS_RECV_QUEUE 52
|
||||
#define SYS_PUBLISH_QUEUE 53
|
||||
#define SYS_OPEN_NAMED_QUEUE 54
|
||||
#define SYS_OPEN_NAMED_QUEUE_OWNER_PROCESS 55
|
||||
#define SYS_UNPUBLISH_QUEUE 56
|
||||
#define SYS_CREATE_QUEUE 55
|
||||
#define SYS_SEND_QUEUE 56
|
||||
#define SYS_RECV_QUEUE 57
|
||||
#define SYS_PUBLISH_QUEUE 58
|
||||
#define SYS_OPEN_NAMED_QUEUE 59
|
||||
#define SYS_OPEN_NAMED_QUEUE_OWNER_PROCESS 60
|
||||
#define SYS_UNPUBLISH_QUEUE 61
|
||||
|
||||
// LPC-like Ports and well-known system services.
|
||||
#define SYS_CREATE_PORT 57
|
||||
#define SYS_CONNECT_PORT 58
|
||||
#define SYS_ACCEPT_PORT 59
|
||||
#define SYS_SEND_PORT 60
|
||||
#define SYS_RECEIVE_PORT 61
|
||||
#define SYS_CALL_PORT 62
|
||||
#define SYS_REPLY_PORT 63
|
||||
#define SYS_DISCONNECT_PORT 64
|
||||
#define SYS_REGISTER_SYSTEM_SERVICE 65
|
||||
#define SYS_UNREGISTER_SYSTEM_SERVICE 66
|
||||
#define SYS_CONNECT_SYSTEM_SERVICE 67
|
||||
#define SYS_CREATE_PORT 62
|
||||
#define SYS_CONNECT_PORT 63
|
||||
#define SYS_ACCEPT_PORT 64
|
||||
#define SYS_SEND_PORT 65
|
||||
#define SYS_RECEIVE_PORT 66
|
||||
#define SYS_CALL_PORT 67
|
||||
#define SYS_REPLY_PORT 68
|
||||
#define SYS_DISCONNECT_PORT 69
|
||||
#define SYS_OPEN_PORT_PEER_PROCESS 70
|
||||
#define SYS_REGISTER_SYSTEM_SERVICE 71
|
||||
#define SYS_UNREGISTER_SYSTEM_SERVICE 72
|
||||
#define SYS_CONNECT_SYSTEM_SERVICE 73
|
||||
|
||||
// Mounted-volume manager control plane.
|
||||
#define SYS_QUERY_VOLUMES 68
|
||||
#define SYS_OPEN_VOLUME 69
|
||||
#define SYS_WAIT_VOLUME_CHANGE 70
|
||||
#define SYS_QUERY_VOLUMES 74
|
||||
#define SYS_OPEN_VOLUME 75
|
||||
#define SYS_WAIT_VOLUME_CHANGE 76
|
||||
|
||||
// Files and directories.
|
||||
#define SYS_OPEN_FILE_AT 71
|
||||
#define SYS_OPEN_DIR_AT 72
|
||||
#define SYS_STAT_AT 73
|
||||
#define SYS_DELETE_AT 74
|
||||
#define SYS_RENAME_AT 75
|
||||
#define SYS_CREATE_DIR_AT 76
|
||||
#define SYS_REMOVE_DIR_AT 77
|
||||
#define SYS_READ_FILE 78
|
||||
#define SYS_WRITE_FILE 79
|
||||
#define SYS_READ_FILE_ASYNC 80
|
||||
#define SYS_WRITE_FILE_ASYNC 81
|
||||
#define SYS_CANCEL_IO 82
|
||||
#define SYS_SEEK_FILE 83
|
||||
#define SYS_GET_FILE_POS 84
|
||||
#define SYS_GET_FILE_SIZE 85
|
||||
#define SYS_GET_FILE_STAT 86
|
||||
#define SYS_TRUNCATE_FILE 87
|
||||
#define SYS_FLUSH_FILE 88
|
||||
#define SYS_LOCK_FILE 89
|
||||
#define SYS_UNLOCK_FILE 90
|
||||
#define SYS_QUERY_FILE_LOCK 91
|
||||
#define SYS_SET_FILE_STATUS 92
|
||||
#define SYS_CREATE_PIPE 93
|
||||
#define SYS_NOTIFY_PIPE 94
|
||||
#define SYS_READ_DIR 95
|
||||
#define SYS_OPEN_FILE_AT 77
|
||||
#define SYS_OPEN_DIR_AT 78
|
||||
#define SYS_STAT_AT 79
|
||||
#define SYS_DELETE_AT 80
|
||||
#define SYS_RENAME_AT 81
|
||||
#define SYS_CREATE_DIR_AT 82
|
||||
#define SYS_REMOVE_DIR_AT 83
|
||||
#define SYS_READ_FILE 84
|
||||
#define SYS_WRITE_FILE 85
|
||||
#define SYS_READ_FILE_ASYNC 86
|
||||
#define SYS_WRITE_FILE_ASYNC 87
|
||||
#define SYS_CANCEL_IO 88
|
||||
#define SYS_SEEK_FILE 89
|
||||
#define SYS_GET_FILE_POS 90
|
||||
#define SYS_GET_FILE_SIZE 91
|
||||
#define SYS_GET_FILE_STAT 92
|
||||
#define SYS_TRUNCATE_FILE 93
|
||||
#define SYS_FLUSH_FILE 94
|
||||
#define SYS_LOCK_FILE 95
|
||||
#define SYS_UNLOCK_FILE 96
|
||||
#define SYS_QUERY_FILE_LOCK 97
|
||||
#define SYS_SET_FILE_STATUS 98
|
||||
#define SYS_CREATE_PIPE 99
|
||||
#define SYS_NOTIFY_PIPE 100
|
||||
#define SYS_READ_DIR 101
|
||||
|
||||
// Console, display, and surfaces.
|
||||
#define SYS_WRITE_CONSOLE 96
|
||||
#define SYS_GET_CONSOLE_INFO 97
|
||||
#define SYS_SET_CONSOLE_CURSOR 98
|
||||
#define SYS_FILL_CONSOLE_CHARACTER 99
|
||||
#define SYS_FILL_CONSOLE_ATTRIBUTE 100
|
||||
#define SYS_PUT_SCREEN_CHAR 101
|
||||
#define SYS_CLEAR_SCREEN 102
|
||||
#define SYS_GET_SCREEN_SIZE 103
|
||||
#define SYS_QUERY_DISPLAY_INFO 104
|
||||
#define SYS_QUERY_DISPLAY_MANAGER_INFO 105
|
||||
#define SYS_PRESENT_DISPLAY_MANAGER_SURFACE 106
|
||||
#define SYS_SET_DISPLAY_MANAGER_CURSOR 107
|
||||
#define SYS_WRITE_DISPLAY_MANAGER_CONSOLE 108
|
||||
#define SYS_QUERY_DISPLAY_MANAGER_CONSOLE_INFO 109
|
||||
#define SYS_SET_DISPLAY_MANAGER_CONSOLE_CURSOR 110
|
||||
#define SYS_FILL_DISPLAY_MANAGER_CONSOLE_CHARACTER 111
|
||||
#define SYS_FILL_DISPLAY_MANAGER_CONSOLE_ATTRIBUTE 112
|
||||
#define SYS_PUT_DISPLAY_MANAGER_CONSOLE_CHARACTER 113
|
||||
#define SYS_CLEAR_DISPLAY_MANAGER_CONSOLE 114
|
||||
#define SYS_OPEN_DISPLAY_CLOCK 115
|
||||
#define SYS_CREATE_SURFACE 116
|
||||
#define SYS_MAP_SURFACE 117
|
||||
#define SYS_UNMAP_SURFACE 118
|
||||
#define SYS_QUERY_SURFACE 119
|
||||
#define SYS_COMMIT_SURFACE 120
|
||||
#define SYS_WRITE_CONSOLE 102
|
||||
#define SYS_GET_CONSOLE_INFO 103
|
||||
#define SYS_SET_CONSOLE_CURSOR 104
|
||||
#define SYS_FILL_CONSOLE_CHARACTER 105
|
||||
#define SYS_FILL_CONSOLE_ATTRIBUTE 106
|
||||
#define SYS_PUT_SCREEN_CHAR 107
|
||||
#define SYS_CLEAR_SCREEN 108
|
||||
#define SYS_GET_SCREEN_SIZE 109
|
||||
#define SYS_QUERY_DISPLAY_INFO 110
|
||||
#define SYS_QUERY_DISPLAY_MANAGER_INFO 111
|
||||
#define SYS_PRESENT_DISPLAY_MANAGER_SURFACE 112
|
||||
#define SYS_SET_DISPLAY_MANAGER_CURSOR 113
|
||||
#define SYS_WRITE_DISPLAY_MANAGER_CONSOLE 114
|
||||
#define SYS_QUERY_DISPLAY_MANAGER_CONSOLE_INFO 115
|
||||
#define SYS_SET_DISPLAY_MANAGER_CONSOLE_CURSOR 116
|
||||
#define SYS_FILL_DISPLAY_MANAGER_CONSOLE_CHARACTER 117
|
||||
#define SYS_FILL_DISPLAY_MANAGER_CONSOLE_ATTRIBUTE 118
|
||||
#define SYS_PUT_DISPLAY_MANAGER_CONSOLE_CHARACTER 119
|
||||
#define SYS_CLEAR_DISPLAY_MANAGER_CONSOLE 120
|
||||
#define SYS_OPEN_DISPLAY_CLOCK 121
|
||||
#define SYS_CREATE_SURFACE 122
|
||||
#define SYS_MAP_SURFACE 123
|
||||
#define SYS_UNMAP_SURFACE 124
|
||||
#define SYS_QUERY_SURFACE 125
|
||||
#define SYS_COMMIT_SURFACE 126
|
||||
|
||||
// Native render audio.
|
||||
#define SYS_AUDIO_ENUMERATE_ENDPOINTS 121
|
||||
#define SYS_AUDIO_OPEN_STREAM 122
|
||||
#define SYS_AUDIO_WRITE 123
|
||||
#define SYS_AUDIO_ARM_WAIT 124
|
||||
#define SYS_AUDIO_QUERY_STREAM 125
|
||||
#define SYS_AUDIO_START 126
|
||||
#define SYS_AUDIO_PAUSE 127
|
||||
#define SYS_AUDIO_RESUME 128
|
||||
#define SYS_AUDIO_DRAIN 129
|
||||
#define SYS_AUDIO_STOP 130
|
||||
#define SYS_AUDIO_RESET 131
|
||||
#define SYS_AUDIO_SET_VOLUME 132
|
||||
#define SYS_AUDIO_SET_MASTER_VOLUME 133
|
||||
#define SYS_AUDIO_ENUMERATE_ENDPOINTS 127
|
||||
#define SYS_AUDIO_OPEN_STREAM 128
|
||||
#define SYS_AUDIO_WRITE 129
|
||||
#define SYS_AUDIO_ARM_WAIT 130
|
||||
#define SYS_AUDIO_QUERY_STREAM 131
|
||||
#define SYS_AUDIO_START 132
|
||||
#define SYS_AUDIO_PAUSE 133
|
||||
#define SYS_AUDIO_RESUME 134
|
||||
#define SYS_AUDIO_DRAIN 135
|
||||
#define SYS_AUDIO_STOP 136
|
||||
#define SYS_AUDIO_RESET 137
|
||||
#define SYS_AUDIO_SET_VOLUME 138
|
||||
#define SYS_AUDIO_SET_MASTER_VOLUME 139
|
||||
|
||||
// Input.
|
||||
#define SYS_READ_INPUT_MANAGER_EVENT 134
|
||||
#define SYS_POLL_KEYBOARD 135
|
||||
#define SYS_IS_KEY_DOWN 136
|
||||
#define SYS_READ_KEYBOARD_CHAR 137
|
||||
#define SYS_READ_KEY 138
|
||||
#define SYS_GET_KEY_MODIFIERS 139
|
||||
#define SYS_QUERY_GLOBAL_INPUT_STATE 140
|
||||
#define SYS_OPEN_INPUT_QUEUE 141
|
||||
#define SYS_READ_INPUT_EVENT 142
|
||||
#define SYS_PEEK_INPUT_EVENT 143
|
||||
#define SYS_PEEK_MOUSE 144
|
||||
#define SYS_READ_MOUSE 145
|
||||
#define SYS_GET_MOUSE_POS 146
|
||||
#define SYS_READ_INPUT_MANAGER_EVENT 140
|
||||
#define SYS_POLL_KEYBOARD 141
|
||||
#define SYS_IS_KEY_DOWN 142
|
||||
#define SYS_READ_KEYBOARD_CHAR 143
|
||||
#define SYS_READ_KEY 144
|
||||
#define SYS_GET_KEY_MODIFIERS 145
|
||||
#define SYS_QUERY_GLOBAL_INPUT_STATE 146
|
||||
#define SYS_OPEN_INPUT_QUEUE 147
|
||||
#define SYS_READ_INPUT_EVENT 148
|
||||
#define SYS_PEEK_INPUT_EVENT 149
|
||||
#define SYS_PEEK_MOUSE 150
|
||||
#define SYS_READ_MOUSE 151
|
||||
#define SYS_GET_MOUSE_POS 152
|
||||
|
||||
// Time, debug, and system information.
|
||||
#define SYS_CREATE_TIMER 147
|
||||
#define SYS_SET_TIMER 148
|
||||
#define SYS_CANCEL_TIMER 149
|
||||
#define SYS_GET_TICK 150
|
||||
#define SYS_GET_TICK_FREQUENCY 151
|
||||
#define SYS_GET_SYSTEM_TIME 152
|
||||
#define SYS_PRINT_DEBUG 153
|
||||
#define SYS_QUERY_TRAP_FRAME 154
|
||||
#define SYS_GET_MEMORY_STATUS 155
|
||||
#define SYS_QUERY_KERNEL_STATS 156
|
||||
#define SYS_CREATE_TIMER 153
|
||||
#define SYS_SET_TIMER 154
|
||||
#define SYS_CANCEL_TIMER 155
|
||||
#define SYS_GET_TICK 156
|
||||
#define SYS_GET_TICK_FREQUENCY 157
|
||||
#define SYS_GET_SYSTEM_TIME 158
|
||||
#define SYS_PRINT_DEBUG 159
|
||||
#define SYS_QUERY_TRAP_FRAME 160
|
||||
#define SYS_GET_MEMORY_STATUS 161
|
||||
#define SYS_QUERY_KERNEL_STATS 162
|
||||
|
||||
// Native sockets and polling.
|
||||
#define SYS_CREATE_SOCKET 157
|
||||
#define SYS_SOCKET_IO_ASYNC 158
|
||||
#define SYS_BIND_SOCKET 159
|
||||
#define SYS_LISTEN_SOCKET 160
|
||||
#define SYS_ACCEPT_SOCKET 161
|
||||
#define SYS_CONNECT_SOCKET 162
|
||||
#define SYS_SEND_SOCKET 163
|
||||
#define SYS_RECV_SOCKET 164
|
||||
#define SYS_SHUTDOWN_SOCKET 165
|
||||
#define SYS_SEND_TO_SOCKET 166
|
||||
#define SYS_RECV_FROM_SOCKET 167
|
||||
#define SYS_RESOLVE_HOST 168
|
||||
#define SYS_SET_SOCKET_OPTION 169
|
||||
#define SYS_GET_SOCKET_OPTION 170
|
||||
#define SYS_POLL 171
|
||||
#define SYS_CREATE_SOCKET 163
|
||||
#define SYS_SOCKET_IO_ASYNC 164
|
||||
#define SYS_BIND_SOCKET 165
|
||||
#define SYS_LISTEN_SOCKET 166
|
||||
#define SYS_ACCEPT_SOCKET 167
|
||||
#define SYS_CONNECT_SOCKET 168
|
||||
#define SYS_SEND_SOCKET 169
|
||||
#define SYS_RECV_SOCKET 170
|
||||
#define SYS_SHUTDOWN_SOCKET 171
|
||||
#define SYS_SEND_TO_SOCKET 172
|
||||
#define SYS_RECV_FROM_SOCKET 173
|
||||
#define SYS_RESOLVE_HOST 174
|
||||
#define SYS_SET_SOCKET_OPTION 175
|
||||
#define SYS_GET_SOCKET_OPTION 176
|
||||
#define SYS_POLL 177
|
||||
|
||||
#define SYS_MAX 172
|
||||
#define SYS_MAX 178
|
||||
+25
-16
@@ -265,8 +265,10 @@ __declspec(dllexport) KSTATUS KeQueueUserApc(THREAD* thread,
|
||||
void* routine,
|
||||
void* normalContext,
|
||||
void* systemArgument1,
|
||||
void* systemArgument2) {
|
||||
if (!thread || !routine)
|
||||
void* systemArgument2,
|
||||
uint32_t flags) {
|
||||
if (!thread || !routine ||
|
||||
(flags & ~KE_USER_APC_FLAG_INTERRUPT) != 0)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (!KiUserAddressValid((uint64_t)(uintptr_t)routine))
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
@@ -283,14 +285,15 @@ __declspec(dllexport) KSTATUS KeQueueUserApc(THREAD* thread,
|
||||
apc->NormalContext = normalContext;
|
||||
apc->SystemArgument1 = systemArgument1;
|
||||
apc->SystemArgument2 = systemArgument2;
|
||||
apc->Flags = flags;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&thread->UserApcLock);
|
||||
uintptr_t lockFlags = KeAcquireSpinlock(&thread->UserApcLock);
|
||||
ListInsertTail(&thread->UserApcQueue, &apc->Link);
|
||||
thread->UserApcPending = 1;
|
||||
uint8_t wakeAlertable = (thread->State == ThreadWaiting &&
|
||||
thread->AlertableWait &&
|
||||
thread->UserApcDispatcher != 0);
|
||||
KeReleaseSpinlock(&thread->UserApcLock, flags);
|
||||
KeReleaseSpinlock(&thread->UserApcLock, lockFlags);
|
||||
|
||||
if (wakeAlertable)
|
||||
KiWakeThreadForUserApc(thread);
|
||||
@@ -298,17 +301,23 @@ __declspec(dllexport) KSTATUS KeQueueUserApc(THREAD* thread,
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the pop User Apc operation.
|
||||
static KUSER_APC* KiPopUserApc(THREAD* thread) {
|
||||
// Pops the first APC eligible for the current return-to-user transition.
|
||||
static KUSER_APC* KiPopUserApc(THREAD* thread, bool alertableDelivery) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&thread->UserApcLock);
|
||||
LIST_ENTRY* node = ListPopHead(&thread->UserApcQueue);
|
||||
if (LIST_IS_EMPTY(&thread->UserApcQueue))
|
||||
thread->UserApcPending = 0;
|
||||
LIST_ENTRY* node = thread->UserApcQueue.Fwd;
|
||||
while (node != &thread->UserApcQueue) {
|
||||
KUSER_APC* apc = CONTAINING_RECORD(node, KUSER_APC, Link);
|
||||
if (alertableDelivery || (apc->Flags & KE_USER_APC_FLAG_INTERRUPT) != 0) {
|
||||
KeListRemoveChecked(node);
|
||||
if (LIST_IS_EMPTY(&thread->UserApcQueue))
|
||||
thread->UserApcPending = 0;
|
||||
KeReleaseSpinlock(&thread->UserApcLock, flags);
|
||||
return apc;
|
||||
}
|
||||
node = node->Fwd;
|
||||
}
|
||||
KeReleaseSpinlock(&thread->UserApcLock, flags);
|
||||
|
||||
if (!node)
|
||||
return (KUSER_APC*)0;
|
||||
return CONTAINING_RECORD(node, KUSER_APC, Link);
|
||||
return (KUSER_APC*)0;
|
||||
}
|
||||
|
||||
// Implements the check For User Apc Delivery operation.
|
||||
@@ -320,14 +329,14 @@ void KiCheckForUserApcDelivery(KTRAP_FRAME* frame) {
|
||||
if (!thread)
|
||||
return;
|
||||
|
||||
if (!thread->UserApcDeliverable || thread->UserApcDeliveryActive ||
|
||||
!thread->UserApcPending || !thread->UserApcDispatcher)
|
||||
if (thread->UserApcDeliveryActive || !thread->UserApcPending ||
|
||||
!thread->UserApcDispatcher)
|
||||
return;
|
||||
|
||||
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
|
||||
return;
|
||||
|
||||
KUSER_APC* apc = KiPopUserApc(thread);
|
||||
KUSER_APC* apc = KiPopUserApc(thread, thread->UserApcDeliverable != 0);
|
||||
if (!apc)
|
||||
return;
|
||||
|
||||
|
||||
@@ -234,10 +234,10 @@ SYS_RIGHTS KeGetValidHandleRights(OBJECT_TYPE type) {
|
||||
case ObjectTypeProcess:
|
||||
return management | SYS_RIGHT_QUERY | SYS_RIGHT_WAIT |
|
||||
SYS_PROCESS_RIGHT_TERMINATE | SYS_PROCESS_RIGHT_INSERT_HANDLE |
|
||||
SYS_PROCESS_RIGHT_BUILD;
|
||||
SYS_PROCESS_RIGHT_BUILD | SYS_PROCESS_RIGHT_SECURITY_CONTEXT;
|
||||
case ObjectTypeThread:
|
||||
return management | SYS_RIGHT_QUERY | SYS_RIGHT_WAIT | SYS_THREAD_RIGHT_RESUME |
|
||||
SYS_THREAD_RIGHT_SET_INFORMATION;
|
||||
SYS_THREAD_RIGHT_SET_INFORMATION | SYS_THREAD_RIGHT_NOTIFY;
|
||||
case ObjectTypeMutex:
|
||||
return management | SYS_RIGHT_QUERY | SYS_RIGHT_WAIT | SYS_MUTEX_RIGHT_RELEASE;
|
||||
case ObjectTypeSemaphore:
|
||||
@@ -288,7 +288,7 @@ SYS_RIGHTS KeGetValidHandleRights(OBJECT_TYPE type) {
|
||||
SYS_PORT_RIGHT_CONNECT | SYS_PORT_RIGHT_ACCEPT |
|
||||
SYS_PORT_RIGHT_SEND | SYS_PORT_RIGHT_RECEIVE |
|
||||
SYS_PORT_RIGHT_CALL | SYS_PORT_RIGHT_REPLY |
|
||||
SYS_PORT_RIGHT_DISCONNECT;
|
||||
SYS_PORT_RIGHT_DISCONNECT | SYS_PORT_RIGHT_OPEN_PEER_PROCESS;
|
||||
case ObjectTypeVolume:
|
||||
return management | SYS_RIGHT_QUERY | SYS_VOLUME_RIGHT_OPEN | SYS_VOLUME_RIGHT_MODIFY;
|
||||
case ObjectTypeVolumeManager:
|
||||
|
||||
+61
-11
@@ -94,6 +94,8 @@ struct PORT_CONNECTION {
|
||||
volatile long RefCount;
|
||||
SPINLOCK Lock;
|
||||
struct PORT* Endpoints[2];
|
||||
struct PROCESS* PeerProcesses[2];
|
||||
SYS_RIGHTS PeerProcessRights[2];
|
||||
uint8_t Disconnected[2];
|
||||
LIST_ENTRY Calls;
|
||||
};
|
||||
@@ -103,6 +105,7 @@ typedef struct PORT_LISTENER_STATE {
|
||||
LIST_ENTRY Pending;
|
||||
uint32_t PendingCount;
|
||||
uint32_t Backlog;
|
||||
SYS_RIGHTS PeerProcessRights;
|
||||
EVENT* WaitEvent;
|
||||
} PORT_LISTENER_STATE;
|
||||
|
||||
@@ -164,11 +167,13 @@ void KePortQueryStats(KE_PORT_STATS* statsOut) {
|
||||
}
|
||||
|
||||
// Returns the complete capability rights granted to a newly created endpoint handle.
|
||||
static SYS_RIGHTS KiPortEndpointRights(void) {
|
||||
return SYS_RIGHT_MANAGE | SYS_RIGHT_QUERY | SYS_RIGHT_WAIT |
|
||||
SYS_PORT_RIGHT_SEND | SYS_PORT_RIGHT_RECEIVE |
|
||||
SYS_PORT_RIGHT_CALL | SYS_PORT_RIGHT_REPLY |
|
||||
SYS_PORT_RIGHT_DISCONNECT;
|
||||
static SYS_RIGHTS KiPortEndpointRights(bool openPeerProcess) {
|
||||
SYS_RIGHTS rights = SYS_RIGHT_MANAGE | SYS_RIGHT_QUERY | SYS_RIGHT_WAIT |
|
||||
SYS_PORT_RIGHT_SEND | SYS_PORT_RIGHT_RECEIVE |
|
||||
SYS_PORT_RIGHT_CALL | SYS_PORT_RIGHT_REPLY |
|
||||
SYS_PORT_RIGHT_DISCONNECT;
|
||||
if (openPeerProcess) rights |= SYS_PORT_RIGHT_OPEN_PEER_PROCESS;
|
||||
return rights;
|
||||
}
|
||||
|
||||
// Returns one process security identity for kernel-stamped IPC metadata.
|
||||
@@ -273,6 +278,12 @@ static void KiPortDereferenceConnection(PORT_CONNECTION* connection) {
|
||||
"port: destroying connection with pending calls connection=0x%016llX\n",
|
||||
(uint64_t)(uintptr_t)connection);
|
||||
}
|
||||
for (uint32_t side = 0; side < 2u; ++side) {
|
||||
if (connection->PeerProcesses[side]) {
|
||||
ObDereferenceObject(&connection->PeerProcesses[side]->Header);
|
||||
connection->PeerProcesses[side] = (struct PROCESS*)0;
|
||||
}
|
||||
}
|
||||
MmFreePool(connection);
|
||||
}
|
||||
|
||||
@@ -713,8 +724,11 @@ static KSTATUS KiPortCreateEndpoint(PORT_CONNECTION* connection, uint32_t side,
|
||||
}
|
||||
|
||||
// Allocates one paired connection and its two endpoint objects.
|
||||
static KSTATUS KiPortCreateConnection(PORT** clientOut, PORT** serverOut) {
|
||||
if (!clientOut || !serverOut)
|
||||
static KSTATUS KiPortCreateConnection(PROCESS* clientProcess,
|
||||
SYS_RIGHTS serverPeerProcessRights,
|
||||
PORT** clientOut,
|
||||
PORT** serverOut) {
|
||||
if (!clientProcess || !clientOut || !serverOut)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
*clientOut = (PORT*)0;
|
||||
*serverOut = (PORT*)0;
|
||||
@@ -727,6 +741,15 @@ static KSTATUS KiPortCreateConnection(PORT** clientOut, PORT** serverOut) {
|
||||
connection->RefCount = 2;
|
||||
connection->Lock = (SPINLOCK)SPINLOCK_INIT;
|
||||
LIST_INIT(&connection->Calls);
|
||||
if (serverPeerProcessRights != 0) {
|
||||
if (!ObTryReferenceObject(&clientProcess->Header)) {
|
||||
connection->RefCount = 1;
|
||||
KiPortDereferenceConnection(connection);
|
||||
return NTLSTATUS_OBJECT_DEAD;
|
||||
}
|
||||
connection->PeerProcesses[1] = clientProcess;
|
||||
connection->PeerProcessRights[1] = serverPeerProcessRights;
|
||||
}
|
||||
|
||||
PORT* client = (PORT*)0;
|
||||
PORT* server = (PORT*)0;
|
||||
@@ -754,10 +777,12 @@ static KSTATUS KiPortCreateConnection(PORT** clientOut, PORT** serverOut) {
|
||||
}
|
||||
|
||||
// Creates one bounded listener Port with a waitable pending-connection event.
|
||||
KSTATUS KePortCreate(uint32_t backlog, PORT** portOut) {
|
||||
KSTATUS KePortCreate(uint32_t backlog, SYS_RIGHTS peerProcessRights, PORT** portOut) {
|
||||
if (!portOut)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
*portOut = (PORT*)0;
|
||||
if ((peerProcessRights & ~KeGetValidHandleRights(ObjectTypeProcess)) != 0)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
if (backlog == 0)
|
||||
backlog = SYS_PORT_DEFAULT_BACKLOG;
|
||||
if (backlog > SYS_PORT_MAX_BACKLOG)
|
||||
@@ -770,6 +795,7 @@ KSTATUS KePortCreate(uint32_t backlog, PORT** portOut) {
|
||||
port->Kind = PORT_KIND_LISTENER;
|
||||
port->u.Listener.Lock = (SPINLOCK)SPINLOCK_INIT;
|
||||
port->u.Listener.Backlog = backlog;
|
||||
port->u.Listener.PeerProcessRights = peerProcessRights;
|
||||
LIST_INIT(&port->u.Listener.Pending);
|
||||
|
||||
KSTATUS status = KeEventCreate(EventManualReset, 0, &port->u.Listener.WaitEvent);
|
||||
@@ -816,14 +842,17 @@ KSTATUS KePortConnect(PORT* listener,
|
||||
|
||||
PORT* clientEndpoint = (PORT*)0;
|
||||
PORT* serverEndpoint = (PORT*)0;
|
||||
KSTATUS status = KiPortCreateConnection(&clientEndpoint, &serverEndpoint);
|
||||
KSTATUS status = KiPortCreateConnection(clientProcess,
|
||||
listener->u.Listener.PeerProcessRights,
|
||||
&clientEndpoint,
|
||||
&serverEndpoint);
|
||||
if (!KSUCCESS(status))
|
||||
return status;
|
||||
|
||||
SYS_HANDLE clientHandle = SYS_HANDLE_INVALID;
|
||||
status = KeCreateHandle(clientProcess,
|
||||
&clientEndpoint->Header,
|
||||
KiPortEndpointRights(),
|
||||
KiPortEndpointRights(false),
|
||||
&clientHandle);
|
||||
if (!KSUCCESS(status)) {
|
||||
ObDereferenceObject(&serverEndpoint->Header);
|
||||
@@ -899,7 +928,7 @@ KSTATUS KePortAccept(PORT* listener,
|
||||
SYS_HANDLE handle = SYS_HANDLE_INVALID;
|
||||
KSTATUS status = KeCreateHandle(serverProcess,
|
||||
&pending->ServerEndpoint->Header,
|
||||
KiPortEndpointRights(),
|
||||
KiPortEndpointRights(listener->u.Listener.PeerProcessRights != 0),
|
||||
&handle);
|
||||
if (KSUCCESS(status)) {
|
||||
if (infoOut)
|
||||
@@ -1634,3 +1663,24 @@ KSTATUS KePortDisconnect(PORT* endpoint) {
|
||||
KiPortMarkDisconnected(endpoint, false);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Opens one process capability through an accepted endpoint's peer-authority ceiling.
|
||||
KSTATUS KePortOpenPeerProcess(PORT* endpoint,
|
||||
PROCESS* callerProcess,
|
||||
SYS_RIGHTS desiredRights,
|
||||
SYS_HANDLE* processHandleOut) {
|
||||
if (!endpoint || endpoint->Kind != PORT_KIND_ENDPOINT || !callerProcess ||
|
||||
desiredRights == 0 || !processHandleOut)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
PORT_CONNECTION* connection = endpoint->u.Endpoint.Connection;
|
||||
uint32_t side = endpoint->u.Endpoint.Side;
|
||||
if (!connection || side > 1u) return NTLSTATUS_PORT_DISCONNECTED;
|
||||
|
||||
PROCESS* peer = connection->PeerProcesses[side];
|
||||
SYS_RIGHTS ceiling = connection->PeerProcessRights[side];
|
||||
if (!peer || ceiling == 0 || (desiredRights & ~ceiling) != 0)
|
||||
return NTLSTATUS_ACCESS_DENIED;
|
||||
|
||||
return KeCreateHandle(callerProcess, &peer->Header, desiredRights, processHandleOut);
|
||||
}
|
||||
+190
-4
@@ -416,6 +416,33 @@ static uint64_t SyscallCreateThread(const SYS_CREATE_THREAD_REQUEST* request) {
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements SYS_OPEN_CURRENT_THREAD.
|
||||
static uint64_t SyscallOpenCurrentThread(SYS_RIGHTS desiredAccess, SYS_HANDLE* handleOut) {
|
||||
if (!handleOut || desiredAccess == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
SYS_RIGHTS validAccess = KeGetValidHandleRights(ObjectTypeThread);
|
||||
if ((desiredAccess & ~validAccess) != 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KSTATUS status = MmProbeUserWrite(handleOut, sizeof(SYS_HANDLE));
|
||||
if (!KSUCCESS(status)) return status;
|
||||
|
||||
PROCESS* process = KeGetCurrentProcess();
|
||||
THREAD* thread = KeGetCurrentThread();
|
||||
if (!process || !thread) return NTLSTATUS_FAILURE;
|
||||
|
||||
SYS_HANDLE handle = SYS_HANDLE_INVALID;
|
||||
status = KeCreateHandle(process, &thread->Header, desiredAccess, &handle);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
|
||||
status = KiCopyHandleToUser(handleOut, handle);
|
||||
if (!KSUCCESS(status)) {
|
||||
KeCloseHandle(process, handle);
|
||||
return status;
|
||||
}
|
||||
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements SYS_RESUME_THREAD.
|
||||
static uint64_t SyscallResumeThread(SYS_HANDLE threadHandle, uint32_t* previousSuspendCountOut) {
|
||||
if (!threadHandle || !previousSuspendCountOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -440,6 +467,61 @@ static uint64_t SyscallResumeThread(SYS_HANDLE threadHandle, uint32_t* previousS
|
||||
return KiCopyU32ToUser(previousSuspendCountOut, previousSuspendCount);
|
||||
}
|
||||
|
||||
// Implements SYS_RESUME_THREAD_AND_WAIT.
|
||||
// Resumes one suspended thread and blocks until that same thread exits without
|
||||
// returning to userspace between the resume and wait operations.
|
||||
static uint64_t SyscallResumeThreadAndWait(SYS_HANDLE threadHandle,
|
||||
uint32_t* previousSuspendCountOut) {
|
||||
if (!threadHandle || !previousSuspendCountOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KSTATUS status = MmProbeUserWrite(previousSuspendCountOut, sizeof(uint32_t));
|
||||
if (!KSUCCESS(status)) return status;
|
||||
|
||||
PROCESS* process = KeGetCurrentProcess();
|
||||
THREAD* currentThread = KeGetCurrentThread();
|
||||
if (!process || !currentThread) return NTLSTATUS_FAILURE;
|
||||
|
||||
OBJECT* object = (OBJECT*)0;
|
||||
status = KeReferenceHandle(process, threadHandle, ObjectTypeThread,
|
||||
SYS_THREAD_RIGHT_RESUME | SYS_RIGHT_WAIT, &object);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
|
||||
THREAD* thread = CONTAINING_RECORD(object, THREAD, Header);
|
||||
if (thread == currentThread) {
|
||||
ObDereferenceObject(object);
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
uint32_t previousSuspendCount = 0;
|
||||
status = KeResumeThread(thread, &previousSuspendCount);
|
||||
if (KSUCCESS(status))
|
||||
status = KeWaitForEvent(thread->ExitEvent, 0);
|
||||
|
||||
ObDereferenceObject(object);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
return KiCopyU32ToUser(previousSuspendCountOut, previousSuspendCount);
|
||||
}
|
||||
|
||||
// Implements SYS_GET_THREAD_TID.
|
||||
static uint64_t SyscallGetThreadTid(SYS_HANDLE threadHandle, uint32_t* tidOut) {
|
||||
if (!threadHandle || !tidOut) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KSTATUS status = MmProbeUserWrite(tidOut, sizeof(uint32_t));
|
||||
if (!KSUCCESS(status)) return status;
|
||||
|
||||
PROCESS* process = KeGetCurrentProcess();
|
||||
if (!process) return NTLSTATUS_FAILURE;
|
||||
|
||||
OBJECT* object = (OBJECT*)0;
|
||||
status = KeReferenceHandle(process, threadHandle, ObjectTypeThread, SYS_RIGHT_QUERY, &object);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
|
||||
THREAD* thread = CONTAINING_RECORD(object, THREAD, Header);
|
||||
uint32_t tid = thread->ThreadId;
|
||||
ObDereferenceObject(object);
|
||||
return KiCopyU32ToUser(tidOut, tid);
|
||||
}
|
||||
|
||||
static void KiFinishAlertableUserWait(uint8_t alertable) {
|
||||
if (!alertable) return;
|
||||
|
||||
@@ -740,6 +822,36 @@ static uint64_t SyscallSetUserApcDispatcher(void* dispatcher) {
|
||||
return KeSetUserApcDispatcher(dispatcher);
|
||||
}
|
||||
|
||||
// Implements SYS_QUEUE_USER_APC.
|
||||
static uint64_t SyscallQueueUserApc(const SYS_QUEUE_USER_APC_REQUEST* userRequest) {
|
||||
SYS_QUEUE_USER_APC_REQUEST request;
|
||||
KSTATUS status = KiCopySizedUserRequest(userRequest, &request, sizeof(request));
|
||||
if (!KSUCCESS(status)) return status;
|
||||
if (!request.ThreadHandle || !request.Routine || request.Reserved != 0 ||
|
||||
(request.Flags & ~SYS_QUEUE_USER_APC_FLAG_INTERRUPT) != 0)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
PROCESS* process = KeGetCurrentProcess();
|
||||
if (!process) return NTLSTATUS_FAILURE;
|
||||
|
||||
OBJECT* object = (OBJECT*)0;
|
||||
status = KeReferenceHandle(process, request.ThreadHandle, ObjectTypeThread,
|
||||
SYS_THREAD_RIGHT_NOTIFY, &object);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
|
||||
THREAD* thread = CONTAINING_RECORD(object, THREAD, Header);
|
||||
status = KeQueueUserApc(thread,
|
||||
(void*)(uintptr_t)request.Routine,
|
||||
request.NormalContext,
|
||||
request.SystemArgument1,
|
||||
request.SystemArgument2,
|
||||
(request.Flags & SYS_QUEUE_USER_APC_FLAG_INTERRUPT) != 0
|
||||
? KE_USER_APC_FLAG_INTERRUPT
|
||||
: KE_USER_APC_FLAG_NONE);
|
||||
ObDereferenceObject(object);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Implements SYS_APC_RETURN.
|
||||
static uint64_t SyscallApcReturn(const SYS_USER_APC_FRAME* frame) {
|
||||
return KeUserApcReturn((const SYS_USER_APC_FRAME_K*)(uintptr_t)frame);
|
||||
@@ -1978,7 +2090,8 @@ static void SyscallUserAsyncNormalRoutine(void* normalContext,
|
||||
(void*)ctx->UserRoutine,
|
||||
ctx->UserContext,
|
||||
iosb,
|
||||
(void*)(uintptr_t)information);
|
||||
(void*)(uintptr_t)information,
|
||||
KE_USER_APC_FLAG_NONE);
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("USER/APC async: KeQueueUserApc failed status=%u\n", s);
|
||||
}
|
||||
@@ -3105,7 +3218,7 @@ static uint64_t SyscallOpenProcess(uint32_t pid, SYS_RIGHTS desiredAccess, SYS_H
|
||||
|
||||
PROCESS* caller = KeGetCurrentProcess();
|
||||
if (!caller) return NTLSTATUS_FAILURE;
|
||||
if (pid != caller->ProcessId) {
|
||||
if (pid != caller->ProcessId || (desiredAccess & SYS_PROCESS_RIGHT_SECURITY_CONTEXT) != 0) {
|
||||
KSTATUS privilegeStatus = KiRequirePrivilege(SYS_PRIV_PROCESS_OPEN_ANY);
|
||||
if (!KSUCCESS(privilegeStatus)) return privilegeStatus;
|
||||
}
|
||||
@@ -3214,13 +3327,16 @@ static uint64_t SyscallCreatePort(const SYS_CREATE_PORT_REQUEST* request) {
|
||||
SYS_CREATE_PORT_REQUEST req;
|
||||
KSTATUS status = KiCopySizedUserRequest(request, &req, sizeof(req));
|
||||
if (!KSUCCESS(status)) return status;
|
||||
if (req.Flags != SYS_PORT_FLAG_NONE || !req.HandleOut)
|
||||
if (req.Flags != SYS_PORT_FLAG_NONE || req.Reserved != 0 || !req.HandleOut)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
SYS_RIGHTS validPeerRights = KeGetValidHandleRights(ObjectTypeProcess);
|
||||
if ((req.PeerProcessRights & ~validPeerRights) != 0)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
status = MmProbeUserWrite(req.HandleOut, sizeof(*req.HandleOut));
|
||||
if (!KSUCCESS(status)) return status;
|
||||
|
||||
PORT* port = (PORT*)0;
|
||||
status = KePortCreate(req.Backlog, &port);
|
||||
status = KePortCreate(req.Backlog, req.PeerProcessRights, &port);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
|
||||
SYS_HANDLE handle = SYS_HANDLE_INVALID;
|
||||
@@ -3509,6 +3625,36 @@ static uint64_t SyscallDisconnectPort(SYS_HANDLE endpointHandle) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// Implements SYS_OPEN_PORT_PEER_PROCESS.
|
||||
static uint64_t SyscallOpenPortPeerProcess(SYS_HANDLE endpointHandle,
|
||||
SYS_RIGHTS desiredRights,
|
||||
SYS_HANDLE* processHandleOut) {
|
||||
if (!processHandleOut || desiredRights == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
SYS_RIGHTS validRights = KeGetValidHandleRights(ObjectTypeProcess);
|
||||
if ((desiredRights & ~validRights) != 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KSTATUS status = MmProbeUserWrite(processHandleOut, sizeof(*processHandleOut));
|
||||
if (!KSUCCESS(status)) return status;
|
||||
|
||||
KSTATUS handleStatus = NTLSTATUS_SUCCESS;
|
||||
PORT* endpoint = (PORT*)KiHandleToObject(endpointHandle,
|
||||
ObjectTypePort,
|
||||
SYS_PORT_RIGHT_OPEN_PEER_PROCESS,
|
||||
&handleStatus);
|
||||
if (!endpoint) return handleStatus;
|
||||
|
||||
PROCESS* caller = KeGetCurrentProcess();
|
||||
SYS_HANDLE processHandle = SYS_HANDLE_INVALID;
|
||||
status = caller ? KePortOpenPeerProcess(endpoint, caller, desiredRights, &processHandle)
|
||||
: NTLSTATUS_FAILURE;
|
||||
ObDereferenceObject((OBJECT*)endpoint);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
|
||||
status = KiCopyHandleToUser(processHandleOut, processHandle);
|
||||
if (!KSUCCESS(status) && caller) (void)KeCloseHandle(caller, processHandle);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Implements SYS_REGISTER_SYSTEM_SERVICE.
|
||||
static uint64_t SyscallRegisterSystemService(SYS_SERVICE_ID serviceId, SYS_HANDLE listenerHandle) {
|
||||
if (serviceId == SYS_SERVICE_INVALID || serviceId > SYS_SERVICE_MAX)
|
||||
@@ -4060,6 +4206,40 @@ static uint64_t SyscallQuerySecurityContext(SYS_HANDLE contextHandle, SYS_SECURI
|
||||
return CopyToUser(infoOut, &info, sizeof(info));
|
||||
}
|
||||
|
||||
// Implements SYS_OPEN_PROCESS_SECURITY_CONTEXT.
|
||||
static uint64_t SyscallOpenProcessSecurityContext(SYS_HANDLE processHandle,
|
||||
SYS_RIGHTS desiredRights,
|
||||
SYS_HANDLE* contextHandleOut) {
|
||||
if (!contextHandleOut || desiredRights == 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
SYS_RIGHTS validRights = KeGetValidHandleRights(ObjectTypeSecurityContext);
|
||||
if ((desiredRights & ~validRights) != 0) return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
KSTATUS status = MmProbeUserWrite(contextHandleOut, sizeof(*contextHandleOut));
|
||||
if (!KSUCCESS(status)) return status;
|
||||
|
||||
PROCESS* target = (PROCESS*)KiHandleToObject(processHandle,
|
||||
ObjectTypeProcess,
|
||||
SYS_PROCESS_RIGHT_SECURITY_CONTEXT,
|
||||
&status);
|
||||
if (!target) return status;
|
||||
SECURITY_CONTEXT* context = target->SecurityContext;
|
||||
if (!context || !ObTryReferenceObject(&context->Header)) {
|
||||
ObDereferenceObject(&target->Header);
|
||||
return NTLSTATUS_OBJECT_DEAD;
|
||||
}
|
||||
ObDereferenceObject(&target->Header);
|
||||
|
||||
SYS_HANDLE handle = SYS_HANDLE_INVALID;
|
||||
status = KiAllocHandleForCurrentWithRights(&context->Header, desiredRights, &handle);
|
||||
if (!KSUCCESS(status)) return status;
|
||||
status = KiCopyHandleToUser(contextHandleOut, handle);
|
||||
if (!KSUCCESS(status)) {
|
||||
PROCESS* caller = KeGetCurrentProcess();
|
||||
if (caller) (void)KeCloseHandle(caller, handle);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// Implements SYS_OPEN_NAMED_QUEUE_OWNER_PROCESS.
|
||||
|
||||
// Opens a process handle for the process that published a named queue.
|
||||
@@ -6542,8 +6722,11 @@ static const SYSCALL_ENTRY gSyscallTable[SYS_MAX] = {
|
||||
[SYS_GET_PROCESS_LIST] = SYSCALL_ENTRY3(SyscallGetProcessList),
|
||||
[SYS_GET_PROCESS_PID] = SYSCALL_ENTRY2(SyscallGetProcessPid),
|
||||
[SYS_CREATE_THREAD] = SYSCALL_ENTRY1(SyscallCreateThread),
|
||||
[SYS_OPEN_CURRENT_THREAD] = SYSCALL_ENTRY2(SyscallOpenCurrentThread),
|
||||
[SYS_RESUME_THREAD] = SYSCALL_ENTRY2(SyscallResumeThread),
|
||||
[SYS_RESUME_THREAD_AND_WAIT] = SYSCALL_ENTRY2(SyscallResumeThreadAndWait),
|
||||
[SYS_GET_THREAD_LIST] = SYSCALL_ENTRY4(SyscallGetThreadList),
|
||||
[SYS_GET_THREAD_TID] = SYSCALL_ENTRY2(SyscallGetThreadTid),
|
||||
[SYS_GET_CURRENT_TID] = SYSCALL_ENTRY0(SyscallGetCurrentTid),
|
||||
[SYS_GET_CURRENT_PID] = SYSCALL_ENTRY0(SyscallGetCurrentPid),
|
||||
[SYS_SET_THREAD_PRIORITY] = SYSCALL_ENTRY1(SyscallSetThreadPriority),
|
||||
@@ -6554,6 +6737,7 @@ static const SYSCALL_ENTRY gSyscallTable[SYS_MAX] = {
|
||||
[SYS_WAIT_SINGLE] = SYSCALL_ENTRY3(SyscallWaitSingle),
|
||||
[SYS_WAIT_MANY] = SYSCALL_ENTRY1(SyscallWaitMany),
|
||||
[SYS_SET_USER_APC_DISPATCHER] = SYSCALL_ENTRY1(SyscallSetUserApcDispatcher),
|
||||
[SYS_QUEUE_USER_APC] = SYSCALL_ENTRY1(SyscallQueueUserApc),
|
||||
[SYS_APC_RETURN] = SYSCALL_ENTRY1(SyscallApcReturn),
|
||||
[SYS_SET_EXCEPTION_DISPATCHER] = SYSCALL_ENTRY1(SyscallSetExceptionDispatcher),
|
||||
[SYS_GET_EXCEPTION_DISPATCHER] = SYSCALL_ENTRY1(SyscallGetExceptionDispatcher),
|
||||
@@ -6571,6 +6755,7 @@ static const SYSCALL_ENTRY gSyscallTable[SYS_MAX] = {
|
||||
[SYS_REVOKE_HANDLE] = SYSCALL_ENTRY1(SyscallRevokeHandle),
|
||||
[SYS_DERIVE_SECURITY_CONTEXT] = SYSCALL_ENTRY1(SyscallDeriveSecurityContext),
|
||||
[SYS_QUERY_SECURITY_CONTEXT] = SYSCALL_ENTRY2(SyscallQuerySecurityContext),
|
||||
[SYS_OPEN_PROCESS_SECURITY_CONTEXT] = SYSCALL_ENTRY3(SyscallOpenProcessSecurityContext),
|
||||
[SYS_CREATE_FILE_MAPPING] = SYSCALL_ENTRY1(SyscallCreateFileMapping),
|
||||
[SYS_MAP_FILE] = SYSCALL_ENTRY1(SyscallMapFile),
|
||||
|
||||
@@ -6603,6 +6788,7 @@ static const SYSCALL_ENTRY gSyscallTable[SYS_MAX] = {
|
||||
[SYS_CALL_PORT] = SYSCALL_ENTRY1(SyscallCallPort),
|
||||
[SYS_REPLY_PORT] = SYSCALL_ENTRY1(SyscallReplyPort),
|
||||
[SYS_DISCONNECT_PORT] = SYSCALL_ENTRY1(SyscallDisconnectPort),
|
||||
[SYS_OPEN_PORT_PEER_PROCESS] = SYSCALL_ENTRY3(SyscallOpenPortPeerProcess),
|
||||
[SYS_REGISTER_SYSTEM_SERVICE] = SYSCALL_ENTRY2(SyscallRegisterSystemService),
|
||||
[SYS_UNREGISTER_SYSTEM_SERVICE] = SYSCALL_ENTRY2(SyscallUnregisterSystemService),
|
||||
[SYS_CONNECT_SYSTEM_SERVICE] = SYSCALL_ENTRY1(SyscallConnectSystemService),
|
||||
|
||||
@@ -75,8 +75,9 @@ void KiExitTrapFrame(KTRAP_FRAME* frame) {
|
||||
if (!frame || frame->Magic != KTRAP_FRAME_MAGIC)
|
||||
KePanic(KE_PANIC_CODE_TRAP, "KiExitTrapFrame: invalid trap frame 0x%016llX\n", (uint64_t)frame);
|
||||
|
||||
// Give alertable user-mode returns a chance to redirect through the
|
||||
// registered user APC dispatcher before committing IRET slots.
|
||||
// Give eligible user APCs a chance to redirect through the registered
|
||||
// dispatcher before committing IRET slots. Interrupt APCs are eligible on
|
||||
// any user return; ordinary APCs still require an alertable wait.
|
||||
KiCheckForUserApcDelivery(frame);
|
||||
|
||||
// Commit editable return state. Kernel-mode interrupts have no RSP/SS
|
||||
|
||||
Reference in new issue
Block a user