Home | History | Annotate | Download | only in pocdll
      1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <malloc.h>
      6 #include "sandbox/win/sandbox_poc/pocdll/exports.h"
      7 #include "sandbox/win/sandbox_poc/pocdll/utils.h"
      8 
      9 // This file contains the tests used to verify if it's possible to DOS or crash
     10 // the machine. All tests that can impact the stability of the machine should
     11 // be in this file.
     12 
     13 // Sleeps forever. this function is used to be the
     14 // entry point for the threads created by the thread bombing function.
     15 // This function never returns.
     16 DWORD WINAPI MyThreadBombimgFunction(void *param) {
     17   UNREFERENCED_PARAMETER(param);
     18   Sleep(INFINITE);
     19   return 0;
     20 }
     21 
     22 void POCDLL_API TestThreadBombing(HANDLE log) {
     23   HandleToFile handle2file;
     24   FILE *output = handle2file.Translate(log, "w");
     25 
     26   // we stop after 5 errors in a row
     27   int number_errors = 0;
     28   for (int i = 0; i < 100000; ++i) {
     29     DWORD tid;
     30     // Create the thread and leak the handle.
     31     HANDLE thread = ::CreateThread(NULL,  // Default security attributes
     32                                    NULL,  // Stack size
     33                                    MyThreadBombimgFunction,
     34                                    NULL,  // Parameter
     35                                    0,     // No creation flags
     36                                    &tid);
     37     if (thread) {
     38       fprintf(output, "[GRANTED] Creating thread with tid 0x%X\r\n", tid);
     39       ::CloseHandle(thread);
     40       number_errors = 0;
     41     } else {
     42       fprintf(output, "[BLOCKED] Creating thread. Error %d\r\n",
     43               ::GetLastError());
     44       number_errors++;
     45     }
     46 
     47     if (number_errors >= 5) {
     48       break;
     49     }
     50   }
     51 }
     52 
     53 
     54 // Executes a complex mathematical operation forever in a loop. This function
     55 // is used as entry point for the threads created by TestTakeAllCpu. It it
     56 // designed to take all CPU on the processor where the thread is running.
     57 // The return value is always 0.
     58 DWORD WINAPI TakeAllCpu(void *param) {
     59   UNREFERENCED_PARAMETER(param);
     60   int cpt = 0;
     61   for (;;) {
     62     cpt += 2;
     63     cpt /= 2;
     64     cpt *= cpt;
     65     cpt = cpt % 100;
     66     cpt = cpt | (cpt * cpt);
     67   }
     68 }
     69 
     70 void POCDLL_API TestTakeAllCpu(HANDLE log) {
     71   HandleToFile handle2file;
     72   FILE *output = handle2file.Translate(log, "w");
     73 
     74   DWORD_PTR process_mask = 0;
     75   DWORD_PTR system_mask = 0;
     76   if (::GetProcessAffinityMask(::GetCurrentProcess(),
     77                                &process_mask,
     78                                &system_mask)) {
     79     DWORD_PTR affinity_mask = 1;
     80 
     81     while (system_mask) {
     82       DWORD tid = 0;
     83 
     84       HANDLE thread = ::CreateThread(NULL,  // Default security attributes.
     85                                      NULL,  // Stack size.
     86                                      TakeAllCpu,
     87                                      NULL,  // Parameter.
     88                                      0,     // No creation flags.
     89                                      &tid);
     90       ::SetThreadAffinityMask(thread, affinity_mask);
     91 
     92       if (::SetThreadPriority(thread, REALTIME_PRIORITY_CLASS)) {
     93         fprintf(output, "[GRANTED] Set thread(%d) priority to Realtime\r\n",
     94                 tid);
     95       } else {
     96         fprintf(output, "[BLOCKED] Set thread(%d) priority to Realtime\r\n",
     97                 tid);
     98       }
     99 
    100       ::CloseHandle(thread);
    101 
    102       affinity_mask = affinity_mask << 1;
    103       system_mask = system_mask >> 1;
    104     }
    105   } else {
    106     fprintf(output, "[ERROR] Cannot get affinity mask. Error %d\r\n",
    107            ::GetLastError());
    108   }
    109 }
    110 
    111 void POCDLL_API TestUseAllMemory(HANDLE log) {
    112   HandleToFile handle2file;
    113   FILE *output = handle2file.Translate(log, "w");
    114 
    115   int number_errors = 0;
    116   unsigned long memory_size = 0;
    117   for (;;) {
    118     DWORD *ptr_to_leak = reinterpret_cast<DWORD *>(malloc(1024*256));
    119     if (ptr_to_leak) {
    120       memory_size += (256);
    121       number_errors = 0;
    122     } else {
    123       number_errors++;
    124     }
    125 
    126     // check if we have more than 5 errors in a row. If so, quit.
    127     if (number_errors >= 5) {
    128       fprintf(output, "[INFO] Created %lu kb of memory\r\n", memory_size);
    129       return;
    130     }
    131 
    132     Sleep(5);  // 5ms to be able to see the progression easily with taskmgr.
    133   }
    134 }
    135 
    136 void POCDLL_API TestCreateObjects(HANDLE log) {
    137   HandleToFile handle2file;
    138   FILE *output = handle2file.Translate(log, "w");
    139 
    140   int mutexes = 0;
    141   int jobs = 0;
    142   int events = 0;
    143   for (int i = 0; i < 1000000; ++i) {
    144     if (::CreateMutex(NULL,     // Default security attributes.
    145                       TRUE,     // We are the initial owner.
    146                       NULL)) {  // No name.
    147       mutexes++;
    148     }
    149 
    150     if (::CreateJobObject(NULL,     // Default security attributes.
    151                           NULL)) {  // No name.
    152       jobs++;
    153     }
    154 
    155     if (::CreateEvent(NULL,     // Default security attributes.
    156                       TRUE,     // Manual Reset.
    157                       TRUE,     // Object is signaled.
    158                       NULL)) {  // No name.
    159       events++;
    160     }
    161   }
    162 
    163   fprintf(output, "[GRANTED] Created %d mutexes, %d jobs and %d events for "
    164                   "a total of %d objects out of 3 000 000\r\n", mutexes, jobs,
    165                   events, mutexes + jobs + events);
    166 }
    167 
    168 BOOL CALLBACK EnumWindowCallback(HWND hwnd, LPARAM output) {
    169   DWORD pid;
    170   ::GetWindowThreadProcessId(hwnd, &pid);
    171   if (pid != ::GetCurrentProcessId()) {
    172     wchar_t window_title[100 + 1] = {0};
    173     ::GetWindowText(hwnd, window_title, 100);
    174     fprintf(reinterpret_cast<FILE*>(output),
    175             "[GRANTED] Found window 0x%p with title %S\r\n",
    176             hwnd,
    177             window_title);
    178     ::CloseWindow(hwnd);
    179   }
    180 
    181   return TRUE;
    182 }
    183 
    184 // Enumerates all the windows on the system and call the function to try to
    185 // close them. The goal of this function is to try to kill the system by
    186 // closing all windows.
    187 // "output" is the stream used for logging.
    188 void POCDLL_API TestCloseHWND(HANDLE log) {
    189   HandleToFile handle2file;
    190   FILE *output = handle2file.Translate(log, "w");
    191 
    192   ::EnumWindows(EnumWindowCallback, PtrToLong(output));
    193   // TODO(nsylvain): find a way to know when the enum is finished
    194   // before returning.
    195   ::Sleep(3000);
    196 }
    197