Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. | 13 // limitations under the License. |
| 14 | 14 |
| 15 #include <errno.h> | 15 #include <errno.h> |
| 16 #include <limits.h> | 16 #include <limits.h> |
| 17 #include <stdio.h> | 17 #include <stdio.h> |
| 18 #include <stdlib.h> | 18 #include <stdlib.h> |
| 19 #include <sys/types.h> | 19 #include <sys/types.h> |
| 20 #include <unistd.h> | |
| 21 | 20 |
| 22 #include <algorithm> | 21 #include <algorithm> |
| 23 | 22 |
| 23 #if defined(__APPLE__) || defined(__linux__) | |
| 24 #define OS_POSIX 1 | |
| 25 #elif defined(_WIN32) | |
| 26 #define OS_WIN 1 | |
| 27 #endif | |
| 28 | |
| 29 #if defined(OS_POSIX) | |
| 30 #include <unistd.h> | |
| 31 #elif defined(OS_WIN) | |
| 32 #include <windows.h> | |
| 33 #endif | |
| 34 | |
| 35 #if defined(OS_WIN) | |
| 36 | |
| 37 // Various semi-documented NT internals to retrieve open handles. | |
| 38 | |
| 39 typedef enum _SYSTEM_INFORMATION_CLASS { | |
| 40 SystemHandleInformation = 16 | |
| 41 } SYSTEM_INFORMATION_CLASS; | |
| 42 | |
| 43 typedef struct _SYSTEM_HANDLE_INFORMATION { | |
| 44 USHORT ProcessId; | |
| 45 USHORT CreatorBackTraceIndex; | |
| 46 UCHAR ObjectTypeNumber; | |
| 47 UCHAR Flags; | |
| 48 USHORT Handle; | |
| 49 PVOID Object; | |
| 50 ACCESS_MASK GrantedAccess; | |
| 51 } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; | |
| 52 | |
| 53 typedef struct _SYSTEM_HANDLE_INFORMATION_EX { | |
| 54 ULONG NumberOfHandles; | |
| 55 SYSTEM_HANDLE_INFORMATION Information[1]; | |
| 56 } SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; | |
| 57 | |
| 58 typedef NTSTATUS(WINAPI* NTQUERYSYSTEMINFORMATION)( | |
| 59 SYSTEM_INFORMATION_CLASS SystemInformationClass, | |
| 60 PVOID SystemInformation, | |
| 61 ULONG SystemInformationLength, | |
| 62 PULONG ReturnLength); | |
| 63 | |
| 64 void EnsureOnlyStdioHandlesOpen() { | |
|
Mark Mentovai
2015/01/08 18:58:15
Unnamed namespace for this.
scottmg
2015/01/08 19:07:43
Done.
| |
| 65 // Initialize the NTAPI functions we need. | |
| 66 HMODULE ntdll_handle = GetModuleHandle(L"ntdll.dll"); | |
| 67 if (!ntdll_handle) { | |
| 68 fprintf(stderr, "GetModuleHandle ntdll.dll failed.\n"); | |
| 69 abort(); | |
| 70 } | |
| 71 | |
| 72 NTQUERYSYSTEMINFORMATION NtQuerySystemInformation; | |
| 73 NtQuerySystemInformation = reinterpret_cast<NTQUERYSYSTEMINFORMATION>( | |
| 74 GetProcAddress(ntdll_handle, "NtQuerySystemInformation")); | |
| 75 if (!NtQuerySystemInformation) { | |
| 76 fprintf(stderr, "GetProcAddress NtQuerySystemInformation failed.\n"); | |
| 77 abort(); | |
| 78 } | |
| 79 | |
| 80 // Get the number of handles on the system. | |
| 81 DWORD buffer_size = 0; | |
| 82 SYSTEM_HANDLE_INFORMATION_EX temp_info; | |
| 83 NTSTATUS status = NtQuerySystemInformation( | |
| 84 SystemHandleInformation, &temp_info, sizeof(temp_info), &buffer_size); | |
| 85 if (!buffer_size) { | |
| 86 fprintf(stderr, | |
| 87 "NtQuerySystemInformation for number of handles failed: 0x%lX\n", | |
| 88 status); | |
| 89 abort(); | |
| 90 } | |
| 91 | |
| 92 SYSTEM_HANDLE_INFORMATION_EX *system_handles = | |
| 93 reinterpret_cast<SYSTEM_HANDLE_INFORMATION_EX*>(new BYTE[buffer_size]); | |
| 94 | |
| 95 // This is likely flaky as we're racing with other handles being created on | |
| 96 // the system between the size query above, and the actual retrieval here. | |
|
Mark Mentovai
2015/01/08 18:58:15
Well, hopefully we’re single-threaded here.
scottmg
2015/01/08 19:07:43
Unfortunately, NtQuerySystemInformation has no way
| |
| 97 status = NtQuerySystemInformation(SystemHandleInformation, system_handles, | |
| 98 buffer_size, &buffer_size); | |
| 99 if (status != 0) { | |
| 100 fprintf(stderr, "Failed to get the handle list: 0x%lX\n", status); | |
| 101 delete[] system_handles; | |
| 102 abort(); | |
| 103 } | |
| 104 | |
| 105 for (ULONG i = 0; i < system_handles->NumberOfHandles; ++i) { | |
| 106 USHORT h = system_handles->Information[i].Handle; | |
| 107 if (system_handles->Information[i].ProcessId != GetCurrentProcessId()) | |
| 108 continue; | |
| 109 | |
| 110 // TODO(scottmg): This is probably insufficient, we'll need to allow having | |
| 111 // a few other standard handles open (for example, to the window station), | |
| 112 // or only check for handles of certain types. | |
| 113 HANDLE handle = reinterpret_cast<HANDLE>(h); | |
| 114 if (handle != GetStdHandle(STD_INPUT_HANDLE) && | |
| 115 handle != GetStdHandle(STD_OUTPUT_HANDLE) && | |
| 116 handle != GetStdHandle(STD_ERROR_HANDLE)) { | |
| 117 fprintf(stderr, "Handle 0x%lX is not stdio handle\n", handle); | |
| 118 abort(); | |
| 119 } | |
| 120 } | |
| 121 | |
| 122 delete [] system_handles; | |
| 123 } | |
| 124 | |
| 125 #endif // OS_WIN | |
| 126 | |
| 24 int main(int argc, char* argv[]) { | 127 int main(int argc, char* argv[]) { |
| 128 #if defined(OS_POSIX) | |
| 25 // Make sure that there’s nothing open at any FD higher than 3. All FDs other | 129 // Make sure that there’s nothing open at any FD higher than 3. All FDs other |
| 26 // than stdin, stdout, and stderr should have been closed prior to or at | 130 // than stdin, stdout, and stderr should have been closed prior to or at |
| 27 // exec(). | 131 // exec(). |
| 28 int max_fd = std::max(static_cast<int>(sysconf(_SC_OPEN_MAX)), OPEN_MAX); | 132 int max_fd = std::max(static_cast<int>(sysconf(_SC_OPEN_MAX)), OPEN_MAX); |
| 29 max_fd = std::max(max_fd, getdtablesize()); | 133 max_fd = std::max(max_fd, getdtablesize()); |
| 30 for (int fd = STDERR_FILENO + 1; fd < max_fd; ++fd) { | 134 for (int fd = STDERR_FILENO + 1; fd < max_fd; ++fd) { |
| 31 if (close(fd) == 0 || errno != EBADF) { | 135 if (close(fd) == 0 || errno != EBADF) { |
| 32 abort(); | 136 abort(); |
| 33 } | 137 } |
| 34 } | 138 } |
| 35 | 139 |
| 36 // Read a byte from stdin, expecting it to be a specific value. | 140 // Read a byte from stdin, expecting it to be a specific value. |
| 37 char c; | 141 char c; |
| 38 ssize_t rv = read(STDIN_FILENO, &c, 1); | 142 ssize_t rv = read(STDIN_FILENO, &c, 1); |
| 39 if (rv != 1 || c != 'z') { | 143 if (rv != 1 || c != 'z') { |
| 40 abort(); | 144 abort(); |
| 41 } | 145 } |
| 42 | 146 |
| 43 // Write a byte to stdout. | 147 // Write a byte to stdout. |
| 44 c = 'Z'; | 148 c = 'Z'; |
| 45 rv = write(STDOUT_FILENO, &c, 1); | 149 rv = write(STDOUT_FILENO, &c, 1); |
| 46 if (rv != 1) { | 150 if (rv != 1) { |
| 47 abort(); | 151 abort(); |
| 48 } | 152 } |
| 153 #elif defined(OS_WIN) | |
| 154 // Make sure there's nothing open other than stdin, stdout, and stderr. | |
| 155 EnsureOnlyStdioHandlesOpen(); | |
| 156 | |
| 157 // Read a byte from stdin, expecting it to be a specific value. | |
| 158 char c; | |
| 159 DWORD bytes_read; | |
| 160 if (!ReadFile(GetStdHandle(STD_INPUT_HANDLE), &c, 1, &bytes_read, nullptr) || | |
| 161 bytes_read != 1 || c != 'z') { | |
| 162 abort(); | |
| 163 } | |
| 164 | |
| 165 // Write a byte to stdout. | |
| 166 c = 'Z'; | |
| 167 DWORD bytes_written; | |
| 168 if (!WriteFile( | |
| 169 GetStdHandle(STD_OUTPUT_HANDLE), &c, 1, &bytes_written, nullptr) || | |
| 170 bytes_written != 1) { | |
| 171 abort(); | |
| 172 } | |
| 173 #endif // OS_POSIX | |
| 49 | 174 |
| 50 return 0; | 175 return 0; |
| 51 } | 176 } |
| OLD | NEW |