BreakoutProcess support
This commit is contained in:
parent
ade657bb14
commit
0da573a7bd
|
@ -958,7 +958,11 @@ _FX BOOL Proc_CreateProcessInternalW(
|
|||
resume_thread = TRUE;
|
||||
dwCreationFlags |= CREATE_SUSPENDED;
|
||||
|
||||
dwCreationFlags &= ~CREATE_BREAKAWAY_FROM_JOB;
|
||||
// no longer required see comment in GuiServer::GetJobObjectForAssign
|
||||
//extern BOOLEAN SysInfo_UseSbieJob;
|
||||
//if (SysInfo_UseSbieJob) {
|
||||
// dwCreationFlags &= ~CREATE_BREAKAWAY_FROM_JOB;
|
||||
//}
|
||||
|
||||
|
||||
//
|
||||
|
|
|
@ -58,10 +58,10 @@ static void Process_NotifyProcess(
|
|||
#endif
|
||||
|
||||
static void Process_NotifyProcessEx(
|
||||
HANDLE ParentId, HANDLE ProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo);
|
||||
PEPROCESS ParentId, HANDLE ProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo);
|
||||
|
||||
static PROCESS *Process_Create(
|
||||
HANDLE ProcessId, const BOX *box, const WCHAR *image_path,
|
||||
HANDLE ProcessId, HANDLE StarterId, const BOX *box, const WCHAR *image_path,
|
||||
KIRQL *out_irql);
|
||||
|
||||
static void Process_NotifyProcess_Delete(HANDLE ProcessId);
|
||||
|
@ -587,7 +587,7 @@ _FX void Process_CreateTerminated(HANDLE ProcessId, ULONG SessionId)
|
|||
|
||||
|
||||
_FX PROCESS *Process_Create(
|
||||
HANDLE ProcessId, const BOX *box, const WCHAR *image_path,
|
||||
HANDLE ProcessId, HANDLE StarterId, const BOX *box, const WCHAR *image_path,
|
||||
KIRQL *out_irql)
|
||||
{
|
||||
POOL *pool;
|
||||
|
@ -620,6 +620,7 @@ _FX PROCESS *Process_Create(
|
|||
memzero(proc, sizeof(PROCESS));
|
||||
|
||||
proc->pid = ProcessId;
|
||||
proc->starter_id = StarterId; // the pid of teh process that called CreateProcess, usually the parent
|
||||
proc->pool = pool;
|
||||
|
||||
proc->box = Box_Clone(pool, box);
|
||||
|
@ -1164,6 +1165,29 @@ _FX BOOLEAN Process_NotifyProcess_Create(
|
|||
ExReleaseResourceLite(Process_ListLock);
|
||||
KeLowerIrql(irql);
|
||||
|
||||
//
|
||||
// check if this process is set up as break out program,
|
||||
// it must't be located in a sandboxed for this to work.
|
||||
//
|
||||
|
||||
BOX* breakout_box = NULL;
|
||||
|
||||
if (box && Process_IsBreakoutProcess(box, ImagePath)) {
|
||||
|
||||
UNICODE_STRING image_uni;
|
||||
RtlInitUnicodeString(&image_uni, ImagePath);
|
||||
if (!Box_IsBoxedPath(box, file, &image_uni)) {
|
||||
|
||||
check_forced_program = TRUE; // the break out process of one mox may be the forced process of an otehr
|
||||
breakout_box = box;
|
||||
box = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// check forced processes
|
||||
//
|
||||
|
||||
if (check_forced_program) {
|
||||
|
||||
//
|
||||
|
@ -1171,7 +1195,7 @@ _FX BOOLEAN Process_NotifyProcess_Create(
|
|||
// check if it might be a forced process
|
||||
//
|
||||
|
||||
box = Process_GetForcedStartBox(ProcessId, ParentId, ImagePath, FALSE);
|
||||
box = Process_GetForcedStartBox(ProcessId, ParentId, ImagePath, FALSE, breakout_box ? breakout_box->sid : NULL);
|
||||
|
||||
if (box == (BOX *)-1) {
|
||||
|
||||
|
@ -1185,7 +1209,7 @@ _FX BOOLEAN Process_NotifyProcess_Create(
|
|||
}
|
||||
else
|
||||
{
|
||||
box = Process_GetForcedStartBox(ProcessId, ParentId, ImagePath, TRUE);
|
||||
box = Process_GetForcedStartBox(ProcessId, ParentId, ImagePath, TRUE, breakout_box ? breakout_box->sid : NULL);
|
||||
|
||||
if (box == (BOX *)-1) {
|
||||
|
||||
|
@ -1202,6 +1226,24 @@ _FX BOOLEAN Process_NotifyProcess_Create(
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// if this is a break out process and no other box clamed it as forced,
|
||||
// set bHostInject and threat it accordingly, we need this in order for
|
||||
// the custom SetInformationProcess call from CreateProcessInternalW to succeed
|
||||
//
|
||||
|
||||
if (breakout_box) {
|
||||
if (!box) {
|
||||
bHostInject = TRUE;
|
||||
add_process_to_job = FALSE;
|
||||
box = breakout_box;
|
||||
}
|
||||
else {
|
||||
Box_Free(breakout_box);
|
||||
breakout_box = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// if parent is a sandboxed process but for some reason we don't
|
||||
// have a box at this point, then terminate the new process
|
||||
|
@ -1244,7 +1286,7 @@ _FX BOOLEAN Process_NotifyProcess_Create(
|
|||
|
||||
if (box) {
|
||||
|
||||
PROCESS *new_proc = Process_Create(ProcessId, box, ImagePath, &irql);
|
||||
PROCESS *new_proc = Process_Create(ProcessId, CallerId, box, ImagePath, &irql);
|
||||
if (!new_proc) {
|
||||
|
||||
create_terminated = TRUE;
|
||||
|
@ -1262,8 +1304,12 @@ _FX BOOLEAN Process_NotifyProcess_Create(
|
|||
new_proc->rights_dropped = parent_had_rights_dropped;
|
||||
new_proc->forced_process = process_is_forced;
|
||||
|
||||
if (! bHostInject)
|
||||
{
|
||||
if (! bHostInject) {
|
||||
|
||||
//
|
||||
// Notify the agent about the new process using a specialized silent message
|
||||
//
|
||||
|
||||
WCHAR msg[48], *buf = msg;
|
||||
RtlStringCbPrintfW(buf, sizeof(msg), L"%s%c%d", new_proc->box->name, L'\0', (ULONG)ParentId);
|
||||
buf += wcslen(buf) + 1;
|
||||
|
@ -1272,8 +1318,11 @@ _FX BOOLEAN Process_NotifyProcess_Create(
|
|||
if (! add_process_to_job)
|
||||
new_proc->parent_was_sandboxed = TRUE;
|
||||
|
||||
add_process_to_job = TRUE; // we need this because of JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK used in GuiServer::GetJobObjectForAssign
|
||||
|
||||
//
|
||||
// don't put the process into a job if OpenWinClass=*
|
||||
// don't put the process into a job if NoSecurityIsolation=y
|
||||
//
|
||||
|
||||
if (new_proc->open_all_win_classes || new_proc->bAppCompartment || Conf_Get_Boolean(new_proc->box->name, L"NoAddProcessToJob", 0, FALSE)) {
|
||||
|
@ -1291,7 +1340,6 @@ _FX BOOLEAN Process_NotifyProcess_Create(
|
|||
new_proc->can_use_jobs = Conf_Get_Boolean(new_proc->box->name, L"AllowBoxedJobs", 0, FALSE);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// on Windows Vista, a forced process may start inside a
|
||||
// Program Compatibility Assistant (PCA) job, if its parent
|
||||
|
|
|
@ -58,6 +58,7 @@ struct _PROCESS {
|
|||
// process id
|
||||
|
||||
HANDLE pid;
|
||||
HANDLE starter_id;
|
||||
|
||||
// process pool. created on process creation. it is freed in its
|
||||
// entirety when the process terminates
|
||||
|
@ -242,6 +243,10 @@ BOOLEAN Process_NotifyProcess_Create(
|
|||
BOOLEAN Process_IsSameBox(PROCESS *proc, PROCESS *proc2, ULONG_PTR proc2_pid);
|
||||
|
||||
|
||||
// Process_IsStarter returns TRUE if proc2 was started by proc1
|
||||
|
||||
BOOLEAN Process_IsStarter(PROCESS* proc1, PROCESS* proc2);
|
||||
|
||||
// Process_MatchImage: given an image name pattern 'pat_str', which
|
||||
// may contain wild cards, tests the image name 'test_str' against
|
||||
// the pattern. If 'pat_len' is specified, only the first 'pat_len'
|
||||
|
@ -382,9 +387,11 @@ NTSTATUS Process_GetSidStringAndSessionId(
|
|||
// Get a box for a forced sandboxed process
|
||||
|
||||
BOX *Process_GetForcedStartBox(
|
||||
HANDLE ProcessId, HANDLE ParentId, const WCHAR *ImagePath, BOOLEAN bHostInject);
|
||||
HANDLE ProcessId, HANDLE ParentId, const WCHAR *ImagePath, BOOLEAN bHostInject, const WCHAR *pSidString);
|
||||
|
||||
|
||||
BOOLEAN Process_IsBreakoutProcess(BOX *box, const WCHAR *ImagePath);
|
||||
|
||||
// Manipulation of the List of Disabled Forced Processes: (Process_List2)
|
||||
// Add ProcessId to list if ParentId is already listed
|
||||
// Hold Process_ListLock before calling, if ParentId != PROCESS_TERMINATED
|
||||
|
|
|
@ -129,13 +129,14 @@ static void Process_CheckAlertProcess(
|
|||
static BOX *Process_CheckHostInjectProcess(
|
||||
LIST *boxes, const WCHAR *name);
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Process_GetForcedStartBox
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX BOX *Process_GetForcedStartBox(
|
||||
HANDLE ProcessId, HANDLE ParentId, const WCHAR *ImagePath, BOOLEAN bHostInject)
|
||||
HANDLE ProcessId, HANDLE ParentId, const WCHAR *ImagePath, BOOLEAN bHostInject, const WCHAR *pSidString)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG SessionId;
|
||||
|
@ -165,13 +166,16 @@ _FX BOX *Process_GetForcedStartBox(
|
|||
|
||||
ProcessObject = Process_OpenAndQuery(ProcessId, &SidString, &SessionId);
|
||||
|
||||
if (! pSidString)
|
||||
pSidString = SidString.Buffer;
|
||||
|
||||
if (! ProcessObject)
|
||||
return NULL;
|
||||
|
||||
if ( !bHostInject && (
|
||||
(_wcsicmp(SidString.Buffer, Driver_S_1_5_18) == 0 ||
|
||||
_wcsicmp(SidString.Buffer, Driver_S_1_5_19) == 0 ||
|
||||
_wcsicmp(SidString.Buffer, Driver_S_1_5_20) == 0)
|
||||
(_wcsicmp(pSidString, Driver_S_1_5_18) == 0 || // System
|
||||
_wcsicmp(pSidString, Driver_S_1_5_19) == 0 || // Local Service
|
||||
_wcsicmp(pSidString, Driver_S_1_5_20) == 0) // Network Service
|
||||
&& (! Process_IsDcomLaunchParent(ParentId))) ){
|
||||
|
||||
status = STATUS_SERVER_SID_MISMATCH; // random status code
|
||||
|
@ -222,7 +226,7 @@ _FX BOX *Process_GetForcedStartBox(
|
|||
|
||||
alert = 0;
|
||||
|
||||
Process_CreateForceData(&boxes, SidString.Buffer, SessionId);
|
||||
Process_CreateForceData(&boxes, pSidString, SessionId);
|
||||
|
||||
//
|
||||
// check if process can be forced
|
||||
|
@ -832,6 +836,153 @@ _FX BOOLEAN Process_IsImmersiveProcess(
|
|||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Process_AddForceFolders
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX void Process_AddForceFolders(
|
||||
LIST* Folders, const WCHAR* Setting, FORCE_BOX *box, const WCHAR *section)
|
||||
{
|
||||
ULONG index2;
|
||||
const WCHAR *value;
|
||||
FORCE_FOLDER *folder;
|
||||
|
||||
index2 = 0;
|
||||
|
||||
while (1) {
|
||||
|
||||
WCHAR *expnd, *buf;
|
||||
ULONG buf_len;
|
||||
|
||||
value = Conf_Get(section, Setting, index2);
|
||||
if (! value)
|
||||
break;
|
||||
++index2;
|
||||
|
||||
expnd = Conf_Expand(box->box->expand_args, value, Setting);
|
||||
|
||||
buf = NULL;
|
||||
|
||||
if (expnd) {
|
||||
|
||||
//
|
||||
// remove duplicate backslashes and translate reparse points
|
||||
//
|
||||
|
||||
WCHAR *tmp1, *tmp2;
|
||||
buf_len = (wcslen(expnd) + 1) * sizeof(WCHAR);
|
||||
tmp1 = Mem_Alloc(Driver_Pool, buf_len);
|
||||
|
||||
if (tmp1) {
|
||||
|
||||
WCHAR *src_ptr = expnd;
|
||||
WCHAR *dst_ptr = tmp1;
|
||||
while (*src_ptr) {
|
||||
if (src_ptr[0] == L'\\' && src_ptr[1] == L'\\') {
|
||||
++src_ptr;
|
||||
continue;
|
||||
}
|
||||
*dst_ptr = *src_ptr;
|
||||
++src_ptr;
|
||||
++dst_ptr;
|
||||
}
|
||||
*dst_ptr = L'\0';
|
||||
|
||||
tmp2 = File_TranslateReparsePoints(tmp1, Driver_Pool);
|
||||
if (tmp2) {
|
||||
|
||||
Mem_Free(tmp1, buf_len);
|
||||
buf = tmp2;
|
||||
buf_len = (wcslen(buf) + 1) * sizeof(WCHAR);
|
||||
|
||||
} else
|
||||
buf = tmp1;
|
||||
}
|
||||
|
||||
Mem_FreeString(expnd);
|
||||
}
|
||||
|
||||
if (! buf)
|
||||
continue;
|
||||
|
||||
folder = Mem_Alloc(Driver_Pool, sizeof(FORCE_FOLDER));
|
||||
if (! folder) {
|
||||
Mem_Free(buf, buf_len);
|
||||
break;
|
||||
}
|
||||
|
||||
if (wcschr(buf, L'*')) {
|
||||
|
||||
folder->pat =
|
||||
Pattern_Create(box->box->expand_args->pool, buf, TRUE, 0);
|
||||
|
||||
Mem_Free(buf, buf_len);
|
||||
|
||||
if (! folder->pat) {
|
||||
Mem_Free(folder, sizeof(FORCE_FOLDER));
|
||||
break;
|
||||
}
|
||||
|
||||
folder->buf_len = 0;
|
||||
folder->len = 0;
|
||||
folder->buf = NULL;
|
||||
|
||||
} else {
|
||||
|
||||
ULONG len = wcslen(buf);
|
||||
while (len && buf[len - 1] == L'\\')
|
||||
--len;
|
||||
|
||||
folder->buf_len = buf_len;
|
||||
folder->len = len;
|
||||
folder->buf = buf;
|
||||
|
||||
folder->pat = NULL;
|
||||
}
|
||||
|
||||
List_Insert_After(Folders, NULL, folder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Process_AddForceProcesses
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX void Process_AddForceProcesses(
|
||||
LIST* Processes, const WCHAR* Setting, const WCHAR *section)
|
||||
{
|
||||
ULONG index2;
|
||||
const WCHAR *value;
|
||||
FORCE_PROCESS *process;
|
||||
|
||||
index2 = 0;
|
||||
|
||||
while (1) {
|
||||
|
||||
value = Conf_Get(section, Setting, index2);
|
||||
if (! value)
|
||||
break;
|
||||
++index2;
|
||||
|
||||
process = Mem_Alloc(Driver_Pool, sizeof(FORCE_PROCESS));
|
||||
if (! process)
|
||||
break;
|
||||
|
||||
// Ideally, RtlStringCchCopy() would be used here - Build issues
|
||||
RtlZeroMemory(process->value, sizeof(process->value));
|
||||
if (wcslen(value) < MAX_FORCE_PROCESS_VALUE_LEN)
|
||||
{
|
||||
wcscpy(process->value, value);
|
||||
}
|
||||
|
||||
List_Insert_After(Processes, NULL, process);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Process_CreateForceData
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -840,12 +991,9 @@ _FX BOOLEAN Process_IsImmersiveProcess(
|
|||
_FX void Process_CreateForceData(
|
||||
LIST *boxes, const WCHAR *SidString, ULONG SessionId)
|
||||
{
|
||||
ULONG index1, index2;
|
||||
ULONG index1;
|
||||
const WCHAR *section;
|
||||
const WCHAR *value;
|
||||
FORCE_BOX *box;
|
||||
FORCE_FOLDER *folder;
|
||||
FORCE_PROCESS *process;
|
||||
|
||||
//
|
||||
// scan list of boxes and create FORCE_BOX elements
|
||||
|
@ -894,291 +1042,86 @@ _FX void Process_CreateForceData(
|
|||
// scan list of ForceFolder settings for the box
|
||||
//
|
||||
|
||||
index2 = 0;
|
||||
|
||||
while (1) {
|
||||
|
||||
static const WCHAR *_ForceFolder = L"ForceFolder";
|
||||
WCHAR *expnd, *buf;
|
||||
ULONG buf_len;
|
||||
|
||||
value = Conf_Get(section, _ForceFolder, index2);
|
||||
if (! value)
|
||||
break;
|
||||
++index2;
|
||||
|
||||
expnd = Conf_Expand(box->box->expand_args, value, _ForceFolder);
|
||||
|
||||
buf = NULL;
|
||||
|
||||
if (expnd) {
|
||||
|
||||
//
|
||||
// remove duplicate backslashes and translate reparse points
|
||||
//
|
||||
|
||||
WCHAR *tmp1, *tmp2;
|
||||
buf_len = (wcslen(expnd) + 1) * sizeof(WCHAR);
|
||||
tmp1 = Mem_Alloc(Driver_Pool, buf_len);
|
||||
|
||||
if (tmp1) {
|
||||
|
||||
WCHAR *src_ptr = expnd;
|
||||
WCHAR *dst_ptr = tmp1;
|
||||
while (*src_ptr) {
|
||||
if (src_ptr[0] == L'\\' && src_ptr[1] == L'\\') {
|
||||
++src_ptr;
|
||||
continue;
|
||||
}
|
||||
*dst_ptr = *src_ptr;
|
||||
++src_ptr;
|
||||
++dst_ptr;
|
||||
}
|
||||
*dst_ptr = L'\0';
|
||||
|
||||
tmp2 = File_TranslateReparsePoints(tmp1, Driver_Pool);
|
||||
if (tmp2) {
|
||||
|
||||
Mem_Free(tmp1, buf_len);
|
||||
buf = tmp2;
|
||||
buf_len = (wcslen(buf) + 1) * sizeof(WCHAR);
|
||||
|
||||
} else
|
||||
buf = tmp1;
|
||||
}
|
||||
|
||||
Mem_FreeString(expnd);
|
||||
}
|
||||
|
||||
if (! buf)
|
||||
continue;
|
||||
|
||||
folder = Mem_Alloc(Driver_Pool, sizeof(FORCE_FOLDER));
|
||||
if (! folder) {
|
||||
Mem_Free(buf, buf_len);
|
||||
break;
|
||||
}
|
||||
|
||||
if (wcschr(buf, L'*')) {
|
||||
|
||||
folder->pat =
|
||||
Pattern_Create(box->box->expand_args->pool, buf, TRUE, 0);
|
||||
|
||||
Mem_Free(buf, buf_len);
|
||||
|
||||
if (! folder->pat) {
|
||||
Mem_Free(folder, sizeof(FORCE_FOLDER));
|
||||
break;
|
||||
}
|
||||
|
||||
folder->buf_len = 0;
|
||||
folder->len = 0;
|
||||
folder->buf = NULL;
|
||||
|
||||
} else {
|
||||
|
||||
ULONG len = wcslen(buf);
|
||||
while (len && buf[len - 1] == L'\\')
|
||||
--len;
|
||||
|
||||
folder->buf_len = buf_len;
|
||||
folder->len = len;
|
||||
folder->buf = buf;
|
||||
|
||||
folder->pat = NULL;
|
||||
}
|
||||
|
||||
List_Insert_After(&box->ForceFolder, NULL, folder);
|
||||
}
|
||||
Process_AddForceFolders(&box->ForceFolder, L"ForceFolder", box, section);
|
||||
|
||||
//
|
||||
// scan list of ForceProcess settings for the box
|
||||
//
|
||||
|
||||
index2 = 0;
|
||||
|
||||
while (1) {
|
||||
|
||||
value = Conf_Get(section, L"ForceProcess", index2);
|
||||
if (! value)
|
||||
break;
|
||||
++index2;
|
||||
|
||||
process = Mem_Alloc(Driver_Pool, sizeof(FORCE_PROCESS));
|
||||
if (! process)
|
||||
break;
|
||||
|
||||
// Ideally, RtlStringCchCopy() would be used here - Build issues
|
||||
RtlZeroMemory(process->value, sizeof(process->value));
|
||||
if (wcslen(value) < MAX_FORCE_PROCESS_VALUE_LEN)
|
||||
{
|
||||
wcscpy(process->value, value);
|
||||
}
|
||||
|
||||
List_Insert_After(&box->ForceProcess, NULL, process);
|
||||
}
|
||||
Process_AddForceProcesses(&box->ForceProcess, L"ForceProcess", section);
|
||||
|
||||
//
|
||||
// scan list of AlertFolder settings for the box
|
||||
//
|
||||
|
||||
index2 = 0;
|
||||
|
||||
while (1) {
|
||||
|
||||
static const WCHAR *_AlertFolder = L"AlertFolder";
|
||||
WCHAR *expnd, *buf;
|
||||
ULONG buf_len;
|
||||
|
||||
value = Conf_Get(section, _AlertFolder, index2);
|
||||
if (! value)
|
||||
break;
|
||||
++index2;
|
||||
|
||||
expnd = Conf_Expand(box->box->expand_args, value, _AlertFolder);
|
||||
|
||||
buf = NULL;
|
||||
|
||||
if (expnd) {
|
||||
|
||||
//
|
||||
// remove duplicate backslashes and translate reparse points
|
||||
//
|
||||
|
||||
WCHAR *tmp1, *tmp2;
|
||||
buf_len = (wcslen(expnd) + 1) * sizeof(WCHAR);
|
||||
tmp1 = Mem_Alloc(Driver_Pool, buf_len);
|
||||
|
||||
if (tmp1) {
|
||||
|
||||
WCHAR *src_ptr = expnd;
|
||||
WCHAR *dst_ptr = tmp1;
|
||||
while (*src_ptr) {
|
||||
if (src_ptr[0] == L'\\' && src_ptr[1] == L'\\') {
|
||||
++src_ptr;
|
||||
continue;
|
||||
}
|
||||
*dst_ptr = *src_ptr;
|
||||
++src_ptr;
|
||||
++dst_ptr;
|
||||
}
|
||||
*dst_ptr = L'\0';
|
||||
|
||||
tmp2 = File_TranslateReparsePoints(tmp1, Driver_Pool);
|
||||
if (tmp2) {
|
||||
|
||||
Mem_Free(tmp1, buf_len);
|
||||
buf = tmp2;
|
||||
buf_len = (wcslen(buf) + 1) * sizeof(WCHAR);
|
||||
|
||||
} else
|
||||
buf = tmp1;
|
||||
}
|
||||
|
||||
Mem_FreeString(expnd);
|
||||
}
|
||||
|
||||
if (! buf)
|
||||
continue;
|
||||
|
||||
folder = Mem_Alloc(Driver_Pool, sizeof(FORCE_FOLDER));
|
||||
if (! folder) {
|
||||
Mem_Free(buf, buf_len);
|
||||
break;
|
||||
}
|
||||
|
||||
if (wcschr(buf, L'*')) {
|
||||
|
||||
folder->pat =
|
||||
Pattern_Create(box->box->expand_args->pool, buf, TRUE, 0);
|
||||
|
||||
Mem_Free(buf, buf_len);
|
||||
|
||||
if (! folder->pat) {
|
||||
Mem_Free(folder, sizeof(FORCE_FOLDER));
|
||||
break;
|
||||
}
|
||||
|
||||
folder->buf_len = 0;
|
||||
folder->len = 0;
|
||||
folder->buf = NULL;
|
||||
|
||||
} else {
|
||||
|
||||
ULONG len = wcslen(buf);
|
||||
while (len && buf[len - 1] == L'\\')
|
||||
--len;
|
||||
|
||||
folder->buf_len = buf_len;
|
||||
folder->len = len;
|
||||
folder->buf = buf;
|
||||
|
||||
folder->pat = NULL;
|
||||
}
|
||||
|
||||
List_Insert_After(&box->AlertFolder, NULL, folder);
|
||||
}
|
||||
Process_AddForceFolders(&box->AlertFolder, L"AlertFolder", box, section);
|
||||
|
||||
//
|
||||
// scan list of AlertProcess settings for the box
|
||||
//
|
||||
|
||||
index2 = 0;
|
||||
|
||||
while (1) {
|
||||
|
||||
value = Conf_Get(section, L"AlertProcess", index2);
|
||||
if (! value)
|
||||
break;
|
||||
++index2;
|
||||
|
||||
process = Mem_Alloc(Driver_Pool, sizeof(FORCE_PROCESS));
|
||||
if (! process)
|
||||
break;
|
||||
|
||||
// Ideally, RtlStringCchCopy() would be used here - Build issues
|
||||
RtlZeroMemory(process->value, sizeof(process->value));
|
||||
if (wcslen(value) < MAX_FORCE_PROCESS_VALUE_LEN)
|
||||
{
|
||||
wcscpy(process->value, value);
|
||||
}
|
||||
|
||||
List_Insert_After(&box->AlertProcess, NULL, process);
|
||||
}
|
||||
Process_AddForceProcesses(&box->AlertProcess, L"AlertProcess", section);
|
||||
|
||||
//
|
||||
// scan list of HostInjectProcess settings for the box
|
||||
//
|
||||
|
||||
index2 = 0;
|
||||
|
||||
while (1) {
|
||||
|
||||
value = Conf_Get(section, L"HostInjectProcess", index2);
|
||||
if (! value)
|
||||
break;
|
||||
++index2;
|
||||
|
||||
process = Mem_Alloc(Driver_Pool, sizeof(FORCE_PROCESS));
|
||||
if (! process)
|
||||
break;
|
||||
|
||||
// Ideally, RtlStringCchCopy() would be used here - Build issues
|
||||
RtlZeroMemory(process->value, sizeof(process->value));
|
||||
if (wcslen(value) < MAX_FORCE_PROCESS_VALUE_LEN)
|
||||
{
|
||||
wcscpy(process->value, value);
|
||||
}
|
||||
|
||||
List_Insert_After(&box->HostInjectProcess, NULL, process);
|
||||
}
|
||||
|
||||
Process_AddForceProcesses(&box->HostInjectProcess, L"HostInjectProcess", section);
|
||||
}
|
||||
|
||||
Conf_AdjustUseCount(FALSE);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Process_DeleteForceDataFolders
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX void Process_DeleteForceDataFolders(LIST* Folders)
|
||||
{
|
||||
FORCE_FOLDER *folder;
|
||||
while (1) {
|
||||
|
||||
folder = List_Head(Folders);
|
||||
if (!folder)
|
||||
break;
|
||||
|
||||
List_Remove(Folders, folder);
|
||||
|
||||
if (folder->pat)
|
||||
Pattern_Free(folder->pat);
|
||||
else
|
||||
Mem_Free(folder->buf, folder->buf_len);
|
||||
|
||||
Mem_Free(folder, sizeof(FORCE_FOLDER));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Process_DeleteForceDataProcesses
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX void Process_DeleteForceDataProcesses(LIST* Folders)
|
||||
{
|
||||
FORCE_PROCESS *process;
|
||||
|
||||
while (1) {
|
||||
|
||||
process = List_Head(Folders);
|
||||
if (! process)
|
||||
break;
|
||||
|
||||
List_Remove(Folders, process);
|
||||
|
||||
Mem_Free(process, sizeof(FORCE_PROCESS));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Process_DeleteForceData
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -1187,8 +1130,6 @@ _FX void Process_CreateForceData(
|
|||
_FX void Process_DeleteForceData(LIST *boxes)
|
||||
{
|
||||
FORCE_BOX *box;
|
||||
FORCE_FOLDER *folder;
|
||||
FORCE_PROCESS *process;
|
||||
|
||||
while (1) {
|
||||
|
||||
|
@ -1198,70 +1139,11 @@ _FX void Process_DeleteForceData(LIST *boxes)
|
|||
|
||||
List_Remove(boxes, box);
|
||||
|
||||
while (1) {
|
||||
|
||||
folder = List_Head(&box->ForceFolder);
|
||||
if (! folder)
|
||||
break;
|
||||
|
||||
List_Remove(&box->ForceFolder, folder);
|
||||
|
||||
if (folder->pat)
|
||||
Pattern_Free(folder->pat);
|
||||
else
|
||||
Mem_Free(folder->buf, folder->buf_len);
|
||||
|
||||
Mem_Free(folder, sizeof(FORCE_FOLDER));
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
||||
process = List_Head(&box->ForceProcess);
|
||||
if (! process)
|
||||
break;
|
||||
|
||||
List_Remove(&box->ForceProcess, process);
|
||||
|
||||
Mem_Free(process, sizeof(FORCE_PROCESS));
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
||||
folder = List_Head(&box->AlertFolder);
|
||||
if (!folder)
|
||||
break;
|
||||
|
||||
List_Remove(&box->AlertFolder, folder);
|
||||
|
||||
if (folder->pat)
|
||||
Pattern_Free(folder->pat);
|
||||
else
|
||||
Mem_Free(folder->buf, folder->buf_len);
|
||||
|
||||
Mem_Free(folder, sizeof(FORCE_FOLDER));
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
||||
process = List_Head(&box->AlertProcess);
|
||||
if (! process)
|
||||
break;
|
||||
|
||||
List_Remove(&box->AlertProcess, process);
|
||||
|
||||
Mem_Free(process, sizeof(FORCE_PROCESS));
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
||||
process = List_Head(&box->HostInjectProcess);
|
||||
if (! process)
|
||||
break;
|
||||
|
||||
List_Remove(&box->HostInjectProcess, process);
|
||||
|
||||
Mem_Free(process, sizeof(FORCE_PROCESS));
|
||||
}
|
||||
Process_DeleteForceDataFolders(&box->ForceFolder);
|
||||
Process_DeleteForceDataProcesses(&box->ForceProcess);
|
||||
Process_DeleteForceDataFolders(&box->AlertFolder);
|
||||
Process_DeleteForceDataProcesses(&box->AlertProcess);
|
||||
Process_DeleteForceDataProcesses(&box->HostInjectProcess);
|
||||
|
||||
Box_Free(box->box);
|
||||
|
||||
|
@ -1627,6 +1509,73 @@ _FX BOX *Process_CheckHostInjectProcess(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Process_DfpInsert
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX BOOLEAN Process_IsBreakoutProcess(
|
||||
BOX *box, const WCHAR *ImagePath)
|
||||
{
|
||||
NTSTATUS status;
|
||||
LIST BreakoutProcess;
|
||||
WCHAR *ImagePath2 = L"";
|
||||
ULONG ImagePath2_len;
|
||||
const WCHAR *ImageName = L"";
|
||||
BOOLEAN IsBreakout = FALSE;
|
||||
|
||||
//
|
||||
// get adjusted image path and image name
|
||||
//
|
||||
|
||||
status = Process_TranslateDosToNt(
|
||||
ImagePath, &ImagePath2, &ImagePath2_len);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
|
||||
ImageName = wcsrchr(ImagePath2, L'\\');
|
||||
if (ImageName && ImageName[1])
|
||||
++ImageName;
|
||||
else
|
||||
status = STATUS_OBJECT_PATH_SYNTAX_BAD; // random
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
List_Init(&BreakoutProcess);
|
||||
|
||||
Conf_AdjustUseCount(TRUE);
|
||||
|
||||
Process_AddForceProcesses(&BreakoutProcess, L"BreakoutProcess", box->name);
|
||||
|
||||
Conf_AdjustUseCount(FALSE);
|
||||
|
||||
|
||||
FORCE_PROCESS *process = List_Head(&BreakoutProcess);
|
||||
while (process) {
|
||||
|
||||
const WCHAR *value = process->value;
|
||||
if (Process_MatchImage(box, value, 0, ImageName, 1)) {
|
||||
|
||||
IsBreakout = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
process = List_Next(process);
|
||||
}
|
||||
|
||||
Process_DeleteForceDataProcesses(&BreakoutProcess);
|
||||
|
||||
Mem_Free(ImagePath2, ImagePath2_len);
|
||||
|
||||
return IsBreakout;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Process_DfpInsert
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -113,6 +113,24 @@ _FX BOOLEAN Process_IsSameBox(
|
|||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Process_IsStarter
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_FX BOOLEAN Process_IsStarter(
|
||||
PROCESS* proc1, PROCESS* proc2)
|
||||
{
|
||||
if (proc1->create_time > proc2->create_time)
|
||||
return FALSE; // reused pid? the new process can not be older than the on that started it
|
||||
|
||||
if (proc1->box->session_id != proc2->box->session_id)
|
||||
return FALSE; // SID must be same
|
||||
|
||||
return proc1->pid == proc2->starter_id;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Process_MatchImage
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -376,7 +376,7 @@ _FX PROCESS *Thread_FindAndInitProcess(
|
|||
PROCESS *proc2 = Process_Find(PsGetProcessId(ProcessObject2), out_irql);
|
||||
if (proc2) {
|
||||
|
||||
if (! Process_IsSameBox(proc1, proc2, 0))
|
||||
if (! Process_IsSameBox(proc1, proc2, 0) && ! Process_IsStarter(proc1, proc2))
|
||||
proc2 = NULL;
|
||||
|
||||
else if (! proc2->threads_lock) {
|
||||
|
|
|
@ -1031,16 +1031,6 @@ HANDLE GuiServer::GetJobObjectForAssign(const WCHAR *boxname)
|
|||
hJobObject = CreateJobObject(&sa, jobname);
|
||||
if (hJobObject) {
|
||||
|
||||
//
|
||||
// set UI restrictions on the job object
|
||||
//
|
||||
|
||||
JOBOBJECT_BASIC_UI_RESTRICTIONS info;
|
||||
info.UIRestrictionsClass = JOB_OBJECT_UILIMIT_EXITWINDOWS
|
||||
| JOB_OBJECT_UILIMIT_HANDLES
|
||||
| JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS
|
||||
| JOB_OBJECT_UILIMIT_READCLIPBOARD;
|
||||
|
||||
BOOL ok = FALSE; // set TRUE to skip UIRestrictions
|
||||
|
||||
// OriginalToken BEGIN
|
||||
|
@ -1053,6 +1043,17 @@ HANDLE GuiServer::GetJobObjectForAssign(const WCHAR *boxname)
|
|||
// UnrestrictedToken END
|
||||
|
||||
if (! ok) {
|
||||
|
||||
//
|
||||
// set UI restrictions on the job object
|
||||
//
|
||||
|
||||
JOBOBJECT_BASIC_UI_RESTRICTIONS info;
|
||||
info.UIRestrictionsClass = JOB_OBJECT_UILIMIT_EXITWINDOWS
|
||||
| JOB_OBJECT_UILIMIT_HANDLES
|
||||
| JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS
|
||||
| JOB_OBJECT_UILIMIT_READCLIPBOARD;
|
||||
|
||||
ok = SetInformationJobObject(
|
||||
hJobObject, JobObjectBasicUIRestrictions,
|
||||
&info, sizeof(info));
|
||||
|
@ -1067,6 +1068,21 @@ HANDLE GuiServer::GetJobObjectForAssign(const WCHAR *boxname)
|
|||
ok = UserHandleGrantAccess(
|
||||
GetDesktopWindow(), hJobObject, TRUE);
|
||||
}
|
||||
|
||||
//
|
||||
// we want to allow sandboxed processes to use jobs of thair own
|
||||
// with windows 8 we can have nested, a boxed process may want to use BREAKAWAY
|
||||
// hence we no longer prevent breaking away from our job,
|
||||
// instead we re assign the job on each initialization, like it was done for the initial one
|
||||
//
|
||||
|
||||
if (ok) {
|
||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobELInfo = {0};
|
||||
jobELInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_BREAKAWAY_OK
|
||||
| JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK;
|
||||
|
||||
ok = SetInformationJobObject(hJobObject, JobObjectExtendedLimitInformation, &jobELInfo, sizeof(jobELInfo));
|
||||
}
|
||||
}
|
||||
if (! ok) {
|
||||
// this should not happen
|
||||
|
|
Loading…
Reference in New Issue