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, |
(...skipping 14 matching lines...) Expand all Loading... |
25 #elif defined(_WIN32) | 25 #elif defined(_WIN32) |
26 #define OS_WIN 1 | 26 #define OS_WIN 1 |
27 #endif | 27 #endif |
28 | 28 |
29 #if defined(OS_POSIX) | 29 #if defined(OS_POSIX) |
30 #include <unistd.h> | 30 #include <unistd.h> |
31 #elif defined(OS_WIN) | 31 #elif defined(OS_WIN) |
32 #include <windows.h> | 32 #include <windows.h> |
33 #endif | 33 #endif |
34 | 34 |
35 #if defined(OS_WIN) | |
36 | |
37 namespace { | |
38 | |
39 // Various semi-documented NT internals to retrieve open handles. | |
40 | |
41 typedef enum _SYSTEM_INFORMATION_CLASS { | |
42 SystemHandleInformation = 16 | |
43 } SYSTEM_INFORMATION_CLASS; | |
44 | |
45 typedef struct _SYSTEM_HANDLE_INFORMATION { | |
46 USHORT ProcessId; | |
47 USHORT CreatorBackTraceIndex; | |
48 UCHAR ObjectTypeNumber; | |
49 UCHAR Flags; | |
50 USHORT Handle; | |
51 PVOID Object; | |
52 ACCESS_MASK GrantedAccess; | |
53 } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; | |
54 | |
55 typedef struct _SYSTEM_HANDLE_INFORMATION_EX { | |
56 ULONG NumberOfHandles; | |
57 SYSTEM_HANDLE_INFORMATION Information[1]; | |
58 } SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; | |
59 | |
60 typedef NTSTATUS(WINAPI* NTQUERYSYSTEMINFORMATION)( | |
61 SYSTEM_INFORMATION_CLASS SystemInformationClass, | |
62 PVOID SystemInformation, | |
63 ULONG SystemInformationLength, | |
64 PULONG ReturnLength); | |
65 | |
66 void EnsureOnlyStdioHandlesOpen() { | |
67 // Initialize the NTAPI functions we need. | |
68 HMODULE ntdll_handle = GetModuleHandle(L"ntdll.dll"); | |
69 if (!ntdll_handle) { | |
70 fprintf(stderr, "GetModuleHandle ntdll.dll failed.\n"); | |
71 abort(); | |
72 } | |
73 | |
74 NTQUERYSYSTEMINFORMATION NtQuerySystemInformation; | |
75 NtQuerySystemInformation = reinterpret_cast<NTQUERYSYSTEMINFORMATION>( | |
76 GetProcAddress(ntdll_handle, "NtQuerySystemInformation")); | |
77 if (!NtQuerySystemInformation) { | |
78 fprintf(stderr, "GetProcAddress NtQuerySystemInformation failed.\n"); | |
79 abort(); | |
80 } | |
81 | |
82 // Get the number of handles on the system. | |
83 DWORD buffer_size = 0; | |
84 SYSTEM_HANDLE_INFORMATION_EX temp_info; | |
85 NTSTATUS status = NtQuerySystemInformation( | |
86 SystemHandleInformation, &temp_info, sizeof(temp_info), &buffer_size); | |
87 if (!buffer_size) { | |
88 fprintf(stderr, | |
89 "NtQuerySystemInformation for number of handles failed: 0x%lX\n", | |
90 status); | |
91 abort(); | |
92 } | |
93 | |
94 SYSTEM_HANDLE_INFORMATION_EX *system_handles = | |
95 reinterpret_cast<SYSTEM_HANDLE_INFORMATION_EX*>(new BYTE[buffer_size]); | |
96 | |
97 // This is likely flaky as we're racing with other handles being created on | |
98 // the system between the size query above, and the actual retrieval here. | |
99 status = NtQuerySystemInformation(SystemHandleInformation, system_handles, | |
100 buffer_size, &buffer_size); | |
101 if (status != 0) { | |
102 fprintf(stderr, "Failed to get the handle list: 0x%lX\n", status); | |
103 delete[] system_handles; | |
104 abort(); | |
105 } | |
106 | |
107 for (ULONG i = 0; i < system_handles->NumberOfHandles; ++i) { | |
108 USHORT h = system_handles->Information[i].Handle; | |
109 if (system_handles->Information[i].ProcessId != GetCurrentProcessId()) | |
110 continue; | |
111 | |
112 // TODO(scottmg): This is probably insufficient, we'll need to allow having | |
113 // a few other standard handles open (for example, to the window station), | |
114 // or only check for handles of certain types. | |
115 HANDLE handle = reinterpret_cast<HANDLE>(h); | |
116 if (handle != GetStdHandle(STD_INPUT_HANDLE) && | |
117 handle != GetStdHandle(STD_OUTPUT_HANDLE) && | |
118 handle != GetStdHandle(STD_ERROR_HANDLE)) { | |
119 fprintf(stderr, "Handle 0x%lX is not stdio handle\n", handle); | |
120 abort(); | |
121 } | |
122 } | |
123 | |
124 delete [] system_handles; | |
125 } | |
126 | |
127 } // namespace | |
128 | |
129 #endif // OS_WIN | |
130 | |
131 int main(int argc, char* argv[]) { | 35 int main(int argc, char* argv[]) { |
132 #if defined(OS_POSIX) | 36 #if defined(OS_POSIX) |
133 // Make sure that there’s nothing open at any FD higher than 3. All FDs other | 37 // Make sure that there’s nothing open at any FD higher than 3. All FDs other |
134 // than stdin, stdout, and stderr should have been closed prior to or at | 38 // than stdin, stdout, and stderr should have been closed prior to or at |
135 // exec(). | 39 // exec(). |
136 int max_fd = std::max(static_cast<int>(sysconf(_SC_OPEN_MAX)), OPEN_MAX); | 40 int max_fd = std::max(static_cast<int>(sysconf(_SC_OPEN_MAX)), OPEN_MAX); |
137 max_fd = std::max(max_fd, getdtablesize()); | 41 max_fd = std::max(max_fd, getdtablesize()); |
138 for (int fd = STDERR_FILENO + 1; fd < max_fd; ++fd) { | 42 for (int fd = STDERR_FILENO + 1; fd < max_fd; ++fd) { |
139 if (close(fd) == 0 || errno != EBADF) { | 43 if (close(fd) == 0 || errno != EBADF) { |
140 abort(); | 44 abort(); |
141 } | 45 } |
142 } | 46 } |
143 | 47 |
144 // Read a byte from stdin, expecting it to be a specific value. | 48 // Read a byte from stdin, expecting it to be a specific value. |
145 char c; | 49 char c; |
146 ssize_t rv = read(STDIN_FILENO, &c, 1); | 50 ssize_t rv = read(STDIN_FILENO, &c, 1); |
147 if (rv != 1 || c != 'z') { | 51 if (rv != 1 || c != 'z') { |
148 abort(); | 52 abort(); |
149 } | 53 } |
150 | 54 |
151 // Write a byte to stdout. | 55 // Write a byte to stdout. |
152 c = 'Z'; | 56 c = 'Z'; |
153 rv = write(STDOUT_FILENO, &c, 1); | 57 rv = write(STDOUT_FILENO, &c, 1); |
154 if (rv != 1) { | 58 if (rv != 1) { |
155 abort(); | 59 abort(); |
156 } | 60 } |
157 #elif defined(OS_WIN) | 61 #elif defined(OS_WIN) |
158 // Make sure there's nothing open other than stdin, stdout, and stderr. | 62 // TODO(scottmg): Verify that only the handles we expect to be open, are. |
159 EnsureOnlyStdioHandlesOpen(); | |
160 | 63 |
161 // Read a byte from stdin, expecting it to be a specific value. | 64 // Read a byte from stdin, expecting it to be a specific value. |
162 char c; | 65 char c; |
163 DWORD bytes_read; | 66 DWORD bytes_read; |
164 if (!ReadFile(GetStdHandle(STD_INPUT_HANDLE), &c, 1, &bytes_read, nullptr) || | 67 HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE); |
| 68 if (!ReadFile(stdin_handle, &c, 1, &bytes_read, nullptr) || |
165 bytes_read != 1 || c != 'z') { | 69 bytes_read != 1 || c != 'z') { |
166 abort(); | 70 abort(); |
167 } | 71 } |
168 | 72 |
169 // Write a byte to stdout. | 73 // Write a byte to stdout. |
170 c = 'Z'; | 74 c = 'Z'; |
171 DWORD bytes_written; | 75 DWORD bytes_written; |
172 if (!WriteFile( | 76 if (!WriteFile( |
173 GetStdHandle(STD_OUTPUT_HANDLE), &c, 1, &bytes_written, nullptr) || | 77 GetStdHandle(STD_OUTPUT_HANDLE), &c, 1, &bytes_written, nullptr) || |
174 bytes_written != 1) { | 78 bytes_written != 1) { |
175 abort(); | 79 abort(); |
176 } | 80 } |
177 #endif // OS_POSIX | 81 #endif // OS_POSIX |
178 | 82 |
179 return 0; | 83 return 0; |
180 } | 84 } |
OLD | NEW |