// 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 #include "sandbox/sandbox_poc/pocdll/exports.h" #include "sandbox/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%X\r\n", tid); ::CloseHandle(thread); number_errors = 0; } else { fprintf(output, "[BLOCKED] Creating thread. Error %d\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(%d) priority to Realtime\r\n", tid); } else { fprintf(output, "[BLOCKED] Set thread(%d) 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 %d\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(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(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); }