diff --git a/CHANGELOG.md b/CHANGELOG.md index 69b26e6bb7..00a78818d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added - added Ability to import encrypted archive files directly [#4255](https://github.com/sandboxie-plus/Sandboxie/issues/4255) +### Changed +- when the sbiesvc.exe worker crashes it now can automatically be restarted. + ### Fixed - fixed issue with sandbox path entry combo boxes - fixed Proxy for GetRawInputDeviceInfoW() causes a buffer overflow [#4267](https://github.com/sandboxie-plus/Sandboxie/issues/4267) (thanks marti4d) diff --git a/Sandboxie/core/dll/callsvc.c b/Sandboxie/core/dll/callsvc.c index c14f192315..c9cef604f7 100644 --- a/Sandboxie/core/dll/callsvc.c +++ b/Sandboxie/core/dll/callsvc.c @@ -1,6 +1,6 @@ /* * Copyright 2004-2020 Sandboxie Holdings, LLC - * Copyright 2020 David Xanatos, xanasoft.com + * Copyright 2020-2024 David Xanatos, xanasoft.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -572,11 +572,11 @@ _FX ULONG SbieDll_QueuePutRpl(const WCHAR *QueueName, //--------------------------------------------------------------------------- -// SbieDll_QueuePutReq +// SbieDll_QueuePutReqImpl //--------------------------------------------------------------------------- -_FX ULONG SbieDll_QueuePutReq(const WCHAR *QueueName, +_FX ULONG SbieDll_QueuePutReqImpl(const WCHAR *QueueName, void *DataPtr, ULONG DataLen, ULONG *out_RequestId, @@ -623,6 +623,9 @@ _FX ULONG SbieDll_QueuePutReq(const WCHAR *QueueName, if (! NT_SUCCESS(status)) { + if(req->event_handle) + CloseHandle((HANDLE)req->event_handle); + if (out_RequestId) *out_RequestId = 0; if (out_EventHandle) @@ -633,6 +636,71 @@ _FX ULONG SbieDll_QueuePutReq(const WCHAR *QueueName, } +//--------------------------------------------------------------------------- +// SbieDll_StartProxy +//--------------------------------------------------------------------------- + + +_FX ULONG SbieDll_StartProxy(const WCHAR *QueueName) +{ + NTSTATUS status; + QUEUE_CREATE_REQ req; + QUEUE_CREATE_RPL *rpl; + + req.h.length = sizeof(QUEUE_CREATE_REQ); + req.h.msgid = MSGID_QUEUE_STARTUP; + wcscpy(req.queue_name, QueueName); + req.event_handle = + (ULONG64)(ULONG_PTR)CreateEvent(NULL, FALSE, FALSE, NULL); + + if (! req.event_handle) + status = STATUS_UNSUCCESSFUL; + else { + + rpl = (QUEUE_CREATE_RPL *)SbieDll_CallServer(&req.h); + if (! rpl) + status = STATUS_SERVER_DISABLED; + else { + status = rpl->h.status; + Dll_Free(rpl); + } + + if (NT_SUCCESS(status)) { + + if (WaitForSingleObject((HANDLE)(ULONG_PTR)req.event_handle, 10 * 1000) != 0) + status = STATUS_TIMEOUT; + } + + CloseHandle((HANDLE)(ULONG_PTR)req.event_handle); + } + + return status; +} + + +//--------------------------------------------------------------------------- +// SbieDll_QueuePutReq +//--------------------------------------------------------------------------- + + +_FX ULONG SbieDll_QueuePutReq(const WCHAR *QueueName, + void *DataPtr, + ULONG DataLen, + ULONG *out_RequestId, + HANDLE *out_EventHandle) +{ + NTSTATUS status = SbieDll_QueuePutReqImpl(QueueName, DataPtr, DataLen, out_RequestId, out_EventHandle); + if (status == STATUS_OBJECT_NAME_NOT_FOUND) { + + if (NT_SUCCESS(SbieDll_StartProxy(QueueName))) { + + status = SbieDll_QueuePutReqImpl(QueueName, DataPtr, DataLen, out_RequestId, out_EventHandle); + } + } + return status; +} + + //--------------------------------------------------------------------------- // SbieDll_QueueGetRpl //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/svc/GuiServer.cpp b/Sandboxie/core/svc/GuiServer.cpp index c373287e5c..c82f467d60 100644 --- a/Sandboxie/core/svc/GuiServer.cpp +++ b/Sandboxie/core/svc/GuiServer.cpp @@ -4670,3 +4670,50 @@ ULONG GuiServer::KillJob(SlaveArgs* args) return STATUS_SUCCESS; } + + +//--------------------------------------------------------------------------- +// StartAsync +//--------------------------------------------------------------------------- + +struct SStartupParam +{ + ULONG session_id; + HANDLE hEvent; +}; + +ULONG GuiServer__StartupWorker(void* _Param) +{ + SStartupParam* pParam = (SStartupParam*)_Param; + + // + // thart the proxy process + // + + GuiServer::GetInstance()->StartSlave(pParam->session_id); + + // + // notify the requesting party that the server is now up and running + // + + SetEvent(pParam->hEvent); + + HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, pParam); + return 0; +} + +ULONG GuiServer::StartAsync(ULONG session_id, HANDLE hEvent) +{ + SStartupParam* pParam = (SStartupParam*)HeapAlloc(GetProcessHeap(), 0, sizeof(SStartupParam)); + pParam->session_id = session_id; + pParam->hEvent = hEvent; + + HANDLE hThread = CreateThread(NULL, 0, GuiServer__StartupWorker, (void *)pParam, 0, NULL); + if (!hThread) { + HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, pParam); + return STATUS_UNSUCCESSFUL; + } + CloseHandle(hThread); + return STATUS_SUCCESS; +} + diff --git a/Sandboxie/core/svc/GuiServer.h b/Sandboxie/core/svc/GuiServer.h index 49993d23cf..0b1fbc4119 100644 --- a/Sandboxie/core/svc/GuiServer.h +++ b/Sandboxie/core/svc/GuiServer.h @@ -34,6 +34,8 @@ class GuiServer static GuiServer *GetInstance(); + ULONG StartAsync(ULONG session_id, HANDLE hEvent); + bool InitProcess(HANDLE hProcess, ULONG process_id, ULONG session_id, BOOLEAN add_to_job); diff --git a/Sandboxie/core/svc/msgids.h b/Sandboxie/core/svc/msgids.h index 1cc1613199..918f68c82a 100644 --- a/Sandboxie/core/svc/msgids.h +++ b/Sandboxie/core/svc/msgids.h @@ -143,6 +143,7 @@ #define MSGID_QUEUE_PUTRPL 0x1E03 #define MSGID_QUEUE_PUTREQ 0x1E04 #define MSGID_QUEUE_GETRPL 0x1E05 +#define MSGID_QUEUE_STARTUP 0x1E10 #define MSGID_QUEUE_NOTIFICATION 0x1EFF #define MSGID_EPMAPPER 0x1F00 diff --git a/Sandboxie/core/svc/queueserver.cpp b/Sandboxie/core/svc/queueserver.cpp index aaa0e01e41..60e2ce974d 100644 --- a/Sandboxie/core/svc/queueserver.cpp +++ b/Sandboxie/core/svc/queueserver.cpp @@ -24,6 +24,7 @@ #include "queueserver.h" #include "queuewire.h" #include "core/dll/sbieapi.h" +#include "GuiServer.h" //--------------------------------------------------------------------------- @@ -111,6 +112,10 @@ MSG_HEADER *QueueServer::Handler(void *_this, MSG_HEADER *msg) HANDLE idProcess = (HANDLE)(ULONG_PTR)PipeServer::GetCallerProcessId(); + if (msg->msgid == MSGID_QUEUE_STARTUP) { + return pThis->StartupHandler(msg, idProcess); + } + if (msg->msgid == MSGID_QUEUE_NOTIFICATION) { pThis->NotifyHandler(idProcess); return NULL; @@ -952,3 +957,85 @@ void QueueServer::DeleteRequestObj(LIST *RequestsList, void *_RequestObj) List_Remove(RequestsList, RequestObj); HeapFree(m_heap, 0, RequestObj); } + + +//--------------------------------------------------------------------------- +// StartupHandler +//--------------------------------------------------------------------------- + + +MSG_HEADER *QueueServer::StartupHandler(MSG_HEADER *msg, HANDLE idProcess) +{ + WCHAR *QueueName = NULL; + HANDLE hProcess = NULL; + HANDLE hEvent = NULL; + ULONG status; + + EnterCriticalSection(&m_lock); + + QUEUE_CREATE_REQ *req = (QUEUE_CREATE_REQ *)msg; + if (req->h.length < sizeof(QUEUE_CREATE_REQ)) { + status = STATUS_INVALID_PARAMETER; + goto finish; + } + + // + // + // + + QueueName = MakeQueueName(idProcess, req->queue_name, &status); + if (! QueueName) + goto finish; + + QUEUE_OBJ *QueueObj = (QUEUE_OBJ *)FindQueueObj(QueueName); + if (QueueObj) { // already exists + status = STATUS_SUCCESS; + goto finish; + } + + status = OpenProcess(idProcess, &hProcess, + PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION); + if (! NT_SUCCESS(status)) + goto finish; + + status = DuplicateEvent(hProcess, req->event_handle, &hEvent); + if (! NT_SUCCESS(status)) + goto finish; + + // + // + // + + ULONG session_id; + if (!NT_SUCCESS(SbieApi_QueryProcess(idProcess, NULL, NULL, NULL, &session_id))) { + status = STATUS_ACCESS_DENIED; + goto finish; + } + + if (_wcsnicmp(req->queue_name, L"*GUIPROXY", 9) == 0) { + + status = GuiServer::GetInstance()->StartAsync(session_id, hEvent); + } + else { + + status = STATUS_INVALID_PARAMETER; + } + + if (NT_SUCCESS(status)) + hEvent = NULL; + +finish: + + LeaveCriticalSection(&m_lock); + + if (hEvent) + CloseHandle(hEvent); + + if (hProcess) + CloseHandle(hProcess); + + if (QueueName) + HeapFree(m_heap, 0, QueueName); + + return SHORT_REPLY(status); +} diff --git a/Sandboxie/core/svc/queueserver.h b/Sandboxie/core/svc/queueserver.h index be7f0cb249..67a4392aa6 100644 --- a/Sandboxie/core/svc/queueserver.h +++ b/Sandboxie/core/svc/queueserver.h @@ -51,6 +51,8 @@ class QueueServer MSG_HEADER *GetRplHandler(MSG_HEADER *msg, HANDLE idProcess); + MSG_HEADER *StartupHandler(MSG_HEADER *msg, HANDLE idProcess); + void NotifyHandler(HANDLE idProcess); LONG OpenProcess(HANDLE idProcess, HANDLE *out_hProcess,