1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 */ 21 22 #include <assert.h> 23 #include <io.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 27 #include "uv.h" 28 #include "internal.h" 29 #include "handle-inl.h" 30 31 32 /* 33 * The `child_stdio_buffer` buffer has the following layout: 34 * int number_of_fds 35 * unsigned char crt_flags[number_of_fds] 36 * HANDLE os_handle[number_of_fds] 37 */ 38 #define CHILD_STDIO_SIZE(count) \ 39 (sizeof(int) + \ 40 sizeof(unsigned char) * (count) + \ 41 sizeof(uintptr_t) * (count)) 42 43 #define CHILD_STDIO_COUNT(buffer) \ 44 *((unsigned int*) (buffer)) 45 46 #define CHILD_STDIO_CRT_FLAGS(buffer, fd) \ 47 *((unsigned char*) (buffer) + sizeof(int) + fd) 48 49 #define CHILD_STDIO_HANDLE(buffer, fd) \ 50 *((HANDLE*) ((unsigned char*) (buffer) + \ 51 sizeof(int) + \ 52 sizeof(unsigned char) * \ 53 CHILD_STDIO_COUNT((buffer)) + \ 54 sizeof(HANDLE) * (fd))) 55 56 57 /* CRT file descriptor mode flags */ 58 #define FOPEN 0x01 59 #define FEOFLAG 0x02 60 #define FCRLF 0x04 61 #define FPIPE 0x08 62 #define FNOINHERIT 0x10 63 #define FAPPEND 0x20 64 #define FDEV 0x40 65 #define FTEXT 0x80 66 67 68 /* 69 * Clear the HANDLE_FLAG_INHERIT flag from all HANDLEs that were inherited 70 * the parent process. Don't check for errors - the stdio handles may not be 71 * valid, or may be closed already. There is no guarantee that this function 72 * does a perfect job. 73 */ 74 void uv_disable_stdio_inheritance(void) { 75 HANDLE handle; 76 STARTUPINFOW si; 77 78 /* Make the windows stdio handles non-inheritable. */ 79 handle = GetStdHandle(STD_INPUT_HANDLE); 80 if (handle != NULL && handle != INVALID_HANDLE_VALUE) 81 SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); 82 83 handle = GetStdHandle(STD_OUTPUT_HANDLE); 84 if (handle != NULL && handle != INVALID_HANDLE_VALUE) 85 SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); 86 87 handle = GetStdHandle(STD_ERROR_HANDLE); 88 if (handle != NULL && handle != INVALID_HANDLE_VALUE) 89 SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); 90 91 /* Make inherited CRT FDs non-inheritable. */ 92 GetStartupInfoW(&si); 93 if (uv__stdio_verify(si.lpReserved2, si.cbReserved2)) 94 uv__stdio_noinherit(si.lpReserved2); 95 } 96 97 98 static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) { 99 HANDLE current_process; 100 101 102 /* _get_osfhandle will sometimes return -2 in case of an error. This seems to 103 * happen when fd <= 2 and the process' corresponding stdio handle is set to 104 * NULL. Unfortunately DuplicateHandle will happily duplicate (HANDLE) -2, so 105 * this situation goes unnoticed until someone tries to use the duplicate. 106 * Therefore we filter out known-invalid handles here. */ 107 if (handle == INVALID_HANDLE_VALUE || 108 handle == NULL || 109 handle == (HANDLE) -2) { 110 *dup = INVALID_HANDLE_VALUE; 111 return ERROR_INVALID_HANDLE; 112 } 113 114 current_process = GetCurrentProcess(); 115 116 if (!DuplicateHandle(current_process, 117 handle, 118 current_process, 119 dup, 120 0, 121 TRUE, 122 DUPLICATE_SAME_ACCESS)) { 123 *dup = INVALID_HANDLE_VALUE; 124 return GetLastError(); 125 } 126 127 return 0; 128 } 129 130 131 static int uv__duplicate_fd(uv_loop_t* loop, int fd, HANDLE* dup) { 132 HANDLE handle; 133 134 if (fd == -1) { 135 *dup = INVALID_HANDLE_VALUE; 136 return ERROR_INVALID_HANDLE; 137 } 138 139 handle = uv__get_osfhandle(fd); 140 return uv__duplicate_handle(loop, handle, dup); 141 } 142 143 144 int uv__create_nul_handle(HANDLE* handle_ptr, 145 DWORD access) { 146 HANDLE handle; 147 SECURITY_ATTRIBUTES sa; 148 149 sa.nLength = sizeof sa; 150 sa.lpSecurityDescriptor = NULL; 151 sa.bInheritHandle = TRUE; 152 153 handle = CreateFileW(L"NUL", 154 access, 155 FILE_SHARE_READ | FILE_SHARE_WRITE, 156 &sa, 157 OPEN_EXISTING, 158 0, 159 NULL); 160 if (handle == INVALID_HANDLE_VALUE) { 161 return GetLastError(); 162 } 163 164 *handle_ptr = handle; 165 return 0; 166 } 167 168 169 int uv__stdio_create(uv_loop_t* loop, 170 const uv_process_options_t* options, 171 BYTE** buffer_ptr) { 172 BYTE* buffer; 173 int count, i; 174 int err; 175 176 count = options->stdio_count; 177 178 if (count < 0 || count > 255) { 179 /* Only support FDs 0-255 */ 180 return ERROR_NOT_SUPPORTED; 181 } else if (count < 3) { 182 /* There should always be at least 3 stdio handles. */ 183 count = 3; 184 } 185 186 /* Allocate the child stdio buffer */ 187 buffer = (BYTE*) uv__malloc(CHILD_STDIO_SIZE(count)); 188 if (buffer == NULL) { 189 return ERROR_OUTOFMEMORY; 190 } 191 192 /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can clean 193 * up on failure. */ 194 CHILD_STDIO_COUNT(buffer) = count; 195 for (i = 0; i < count; i++) { 196 CHILD_STDIO_CRT_FLAGS(buffer, i) = 0; 197 CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE; 198 } 199 200 for (i = 0; i < count; i++) { 201 uv_stdio_container_t fdopt; 202 if (i < options->stdio_count) { 203 fdopt = options->stdio[i]; 204 } else { 205 fdopt.flags = UV_IGNORE; 206 } 207 208 switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | 209 UV_INHERIT_STREAM)) { 210 case UV_IGNORE: 211 /* Starting a process with no stdin/stout/stderr can confuse it. So no 212 * matter what the user specified, we make sure the first three FDs are 213 * always open in their typical modes, e. g. stdin be readable and 214 * stdout/err should be writable. For FDs > 2, don't do anything - all 215 * handles in the stdio buffer are initialized with. 216 * INVALID_HANDLE_VALUE, which should be okay. */ 217 if (i <= 2) { 218 DWORD access = (i == 0) ? FILE_GENERIC_READ : 219 FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES; 220 221 err = uv__create_nul_handle(&CHILD_STDIO_HANDLE(buffer, i), 222 access); 223 if (err) 224 goto error; 225 226 CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV; 227 } 228 break; 229 230 case UV_CREATE_PIPE: { 231 /* Create a pair of two connected pipe ends; one end is turned into an 232 * uv_pipe_t for use by the parent. The other one is given to the 233 * child. */ 234 uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream; 235 HANDLE child_pipe = INVALID_HANDLE_VALUE; 236 237 /* Create a new, connected pipe pair. stdio[i]. stream should point to 238 * an uninitialized, but not connected pipe handle. */ 239 assert(fdopt.data.stream->type == UV_NAMED_PIPE); 240 assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION)); 241 assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER)); 242 243 err = uv__create_stdio_pipe_pair(loop, 244 parent_pipe, 245 &child_pipe, 246 fdopt.flags); 247 if (err) 248 goto error; 249 250 CHILD_STDIO_HANDLE(buffer, i) = child_pipe; 251 CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE; 252 break; 253 } 254 255 case UV_INHERIT_FD: { 256 /* Inherit a raw FD. */ 257 HANDLE child_handle; 258 259 /* Make an inheritable duplicate of the handle. */ 260 err = uv__duplicate_fd(loop, fdopt.data.fd, &child_handle); 261 if (err) { 262 /* If fdopt. data. fd is not valid and fd <= 2, then ignore the 263 * error. */ 264 if (fdopt.data.fd <= 2 && err == ERROR_INVALID_HANDLE) { 265 CHILD_STDIO_CRT_FLAGS(buffer, i) = 0; 266 CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE; 267 break; 268 } 269 goto error; 270 } 271 272 /* Figure out what the type is. */ 273 switch (GetFileType(child_handle)) { 274 case FILE_TYPE_DISK: 275 CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN; 276 break; 277 278 case FILE_TYPE_PIPE: 279 CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE; 280 break; 281 282 case FILE_TYPE_CHAR: 283 case FILE_TYPE_REMOTE: 284 CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV; 285 break; 286 287 case FILE_TYPE_UNKNOWN: 288 if (GetLastError() != 0) { 289 err = GetLastError(); 290 CloseHandle(child_handle); 291 goto error; 292 } 293 CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV; 294 break; 295 296 default: 297 assert(0); 298 return -1; 299 } 300 301 CHILD_STDIO_HANDLE(buffer, i) = child_handle; 302 break; 303 } 304 305 case UV_INHERIT_STREAM: { 306 /* Use an existing stream as the stdio handle for the child. */ 307 HANDLE stream_handle, child_handle; 308 unsigned char crt_flags; 309 uv_stream_t* stream = fdopt.data.stream; 310 311 /* Leech the handle out of the stream. */ 312 if (stream->type == UV_TTY) { 313 stream_handle = ((uv_tty_t*) stream)->handle; 314 crt_flags = FOPEN | FDEV; 315 } else if (stream->type == UV_NAMED_PIPE && 316 stream->flags & UV_HANDLE_CONNECTION) { 317 stream_handle = ((uv_pipe_t*) stream)->handle; 318 crt_flags = FOPEN | FPIPE; 319 } else { 320 stream_handle = INVALID_HANDLE_VALUE; 321 crt_flags = 0; 322 } 323 324 if (stream_handle == NULL || 325 stream_handle == INVALID_HANDLE_VALUE) { 326 /* The handle is already closed, or not yet created, or the stream 327 * type is not supported. */ 328 err = ERROR_NOT_SUPPORTED; 329 goto error; 330 } 331 332 /* Make an inheritable copy of the handle. */ 333 err = uv__duplicate_handle(loop, stream_handle, &child_handle); 334 if (err) 335 goto error; 336 337 CHILD_STDIO_HANDLE(buffer, i) = child_handle; 338 CHILD_STDIO_CRT_FLAGS(buffer, i) = crt_flags; 339 break; 340 } 341 342 default: 343 assert(0); 344 return -1; 345 } 346 } 347 348 *buffer_ptr = buffer; 349 return 0; 350 351 error: 352 uv__stdio_destroy(buffer); 353 return err; 354 } 355 356 357 void uv__stdio_destroy(BYTE* buffer) { 358 int i, count; 359 360 count = CHILD_STDIO_COUNT(buffer); 361 for (i = 0; i < count; i++) { 362 HANDLE handle = CHILD_STDIO_HANDLE(buffer, i); 363 if (handle != INVALID_HANDLE_VALUE) { 364 CloseHandle(handle); 365 } 366 } 367 368 uv__free(buffer); 369 } 370 371 372 void uv__stdio_noinherit(BYTE* buffer) { 373 int i, count; 374 375 count = CHILD_STDIO_COUNT(buffer); 376 for (i = 0; i < count; i++) { 377 HANDLE handle = CHILD_STDIO_HANDLE(buffer, i); 378 if (handle != INVALID_HANDLE_VALUE) { 379 SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); 380 } 381 } 382 } 383 384 385 int uv__stdio_verify(BYTE* buffer, WORD size) { 386 unsigned int count; 387 388 /* Check the buffer pointer. */ 389 if (buffer == NULL) 390 return 0; 391 392 /* Verify that the buffer is at least big enough to hold the count. */ 393 if (size < CHILD_STDIO_SIZE(0)) 394 return 0; 395 396 /* Verify if the count is within range. */ 397 count = CHILD_STDIO_COUNT(buffer); 398 if (count > 256) 399 return 0; 400 401 /* Verify that the buffer size is big enough to hold info for N FDs. */ 402 if (size < CHILD_STDIO_SIZE(count)) 403 return 0; 404 405 return 1; 406 } 407 408 409 WORD uv__stdio_size(BYTE* buffer) { 410 return (WORD) CHILD_STDIO_SIZE(CHILD_STDIO_COUNT((buffer))); 411 } 412 413 414 HANDLE uv__stdio_handle(BYTE* buffer, int fd) { 415 return CHILD_STDIO_HANDLE(buffer, fd); 416 } 417