blob: 9ee13b0cb9dc538693b094ef068b4ddcd77efdfc [file] [log] [blame]
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <malloc.h>
#include "sandbox/win/sandbox_poc/pocdll/exports.h"
#include "sandbox/win/sandbox_poc/pocdll/utils.h"
// This file contains the tests used to verify if it's possible to DOS or crash
// the machine. All tests that can impact the stability of the machine should
// be in this file.
// Sleeps forever. this function is used to be the
// entry point for the threads created by the thread bombing function.
// This function never returns.
DWORD WINAPI MyThreadBombimgFunction(void *param) {
UNREFERENCED_PARAMETER(param);
Sleep(INFINITE);
return 0;
}
void POCDLL_API TestThreadBombing(HANDLE log) {
HandleToFile handle2file;
FILE *output = handle2file.Translate(log, "w");
// we stop after 5 errors in a row
int number_errors = 0;
for (int i = 0; i < 100000; ++i) {
DWORD tid;
// Create the thread and leak the handle.
HANDLE thread = ::CreateThread(NULL, // Default security attributes
NULL, // Stack size
MyThreadBombimgFunction,
NULL, // Parameter
0, // No creation flags
&tid);
if (thread) {
fprintf(output, "[GRANTED] Creating thread with tid 0x%lX\r\n", tid);
::CloseHandle(thread);
number_errors = 0;
} else {
fprintf(output, "[BLOCKED] Creating thread. Error %ld\r\n",
::GetLastError());
number_errors++;
}
if (number_errors >= 5) {
break;
}
}
}
// Executes a complex mathematical operation forever in a loop. This function
// is used as entry point for the threads created by TestTakeAllCpu. It it
// designed to take all CPU on the processor where the thread is running.
// The return value is always 0.
DWORD WINAPI TakeAllCpu(void *param) {
UNREFERENCED_PARAMETER(param);
int cpt = 0;
for (;;) {
cpt += 2;
cpt /= 2;
cpt *= cpt;
cpt = cpt % 100;
cpt = cpt | (cpt * cpt);
}
}
void POCDLL_API TestTakeAllCpu(HANDLE log) {
HandleToFile handle2file;
FILE *output = handle2file.Translate(log, "w");
DWORD_PTR process_mask = 0;
DWORD_PTR system_mask = 0;
if (::GetProcessAffinityMask(::GetCurrentProcess(),
&process_mask,
&system_mask)) {
DWORD_PTR affinity_mask = 1;
while (system_mask) {
DWORD tid = 0;
HANDLE thread = ::CreateThread(NULL, // Default security attributes.
NULL, // Stack size.
TakeAllCpu,
NULL, // Parameter.
0, // No creation flags.
&tid);
::SetThreadAffinityMask(thread, affinity_mask);
if (::SetThreadPriority(thread, REALTIME_PRIORITY_CLASS)) {
fprintf(output, "[GRANTED] Set thread(%ld) priority to Realtime\r\n",
tid);
} else {
fprintf(output, "[BLOCKED] Set thread(%ld) priority to Realtime\r\n",
tid);
}
::CloseHandle(thread);
affinity_mask = affinity_mask << 1;
system_mask = system_mask >> 1;
}
} else {
fprintf(output, "[ERROR] Cannot get affinity mask. Error %ld\r\n",
::GetLastError());
}
}
void POCDLL_API TestUseAllMemory(HANDLE log) {
HandleToFile handle2file;
FILE *output = handle2file.Translate(log, "w");
int number_errors = 0;
unsigned long memory_size = 0;
for (;;) {
DWORD *ptr_to_leak = reinterpret_cast<DWORD *>(malloc(1024*256));
if (ptr_to_leak) {
memory_size += (256);
number_errors = 0;
} else {
number_errors++;
}
// check if we have more than 5 errors in a row. If so, quit.
if (number_errors >= 5) {
fprintf(output, "[INFO] Created %lu kb of memory\r\n", memory_size);
return;
}
Sleep(5); // 5ms to be able to see the progression easily with taskmgr.
}
}
void POCDLL_API TestCreateObjects(HANDLE log) {
HandleToFile handle2file;
FILE *output = handle2file.Translate(log, "w");
int mutexes = 0;
int jobs = 0;
int events = 0;
for (int i = 0; i < 1000000; ++i) {
if (::CreateMutex(NULL, // Default security attributes.
TRUE, // We are the initial owner.
NULL)) { // No name.
mutexes++;
}
if (::CreateJobObject(NULL, // Default security attributes.
NULL)) { // No name.
jobs++;
}
if (::CreateEvent(NULL, // Default security attributes.
TRUE, // Manual Reset.
TRUE, // Object is signaled.
NULL)) { // No name.
events++;
}
}
fprintf(output, "[GRANTED] Created %d mutexes, %d jobs and %d events for "
"a total of %d objects out of 3 000 000\r\n", mutexes, jobs,
events, mutexes + jobs + events);
}
BOOL CALLBACK EnumWindowCallback(HWND hwnd, LPARAM output) {
DWORD pid;
::GetWindowThreadProcessId(hwnd, &pid);
if (pid != ::GetCurrentProcessId()) {
wchar_t window_title[100 + 1] = {0};
::GetWindowText(hwnd, window_title, 100);
fprintf(reinterpret_cast<FILE*>(output),
"[GRANTED] Found window 0x%p with title %S\r\n",
hwnd,
window_title);
::CloseWindow(hwnd);
}
return TRUE;
}
// Enumerates all the windows on the system and call the function to try to
// close them. The goal of this function is to try to kill the system by
// closing all windows.
// "output" is the stream used for logging.
void POCDLL_API TestCloseHWND(HANDLE log) {
HandleToFile handle2file;
FILE *output = handle2file.Translate(log, "w");
::EnumWindows(EnumWindowCallback, PtrToLong(output));
// TODO(nsylvain): find a way to know when the enum is finished
// before returning.
::Sleep(3000);
}