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.
16DWORD WINAPI MyThreadBombimgFunction(void *param) {
17  UNREFERENCED_PARAMETER(param);
18  Sleep(INFINITE);
19  return 0;
20}
21
22void 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%lX\r\n", tid);
39      ::CloseHandle(thread);
40      number_errors = 0;
41    } else {
42      fprintf(output, "[BLOCKED] Creating thread. Error %ld\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.
58DWORD 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
70void 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(%ld) priority to Realtime\r\n",
94                tid);
95      } else {
96        fprintf(output, "[BLOCKED] Set thread(%ld) 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 %ld\r\n",
107           ::GetLastError());
108  }
109}
110
111void 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
136void 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
168BOOL 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.
188void 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