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 */
uv_disable_stdio_inheritance(void)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
uv__create_stdio_pipe_pair(uv_loop_t * loop,uv_pipe_t * server_pipe,HANDLE * child_pipe_ptr,unsigned int flags)98 static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
99 uv_pipe_t* server_pipe, HANDLE* child_pipe_ptr, unsigned int flags) {
100 char pipe_name[64];
101 SECURITY_ATTRIBUTES sa;
102 DWORD server_access = 0;
103 DWORD client_access = 0;
104 HANDLE child_pipe = INVALID_HANDLE_VALUE;
105 int err;
106 int overlap;
107
108 if (flags & UV_READABLE_PIPE) {
109 /* The server needs inbound access too, otherwise CreateNamedPipe() won't
110 * give us the FILE_READ_ATTRIBUTES permission. We need that to probe the
111 * state of the write buffer when we're trying to shutdown the pipe. */
112 server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND;
113 client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
114 }
115 if (flags & UV_WRITABLE_PIPE) {
116 server_access |= PIPE_ACCESS_INBOUND;
117 client_access |= GENERIC_WRITE | FILE_READ_ATTRIBUTES;
118 }
119
120 /* Create server pipe handle. */
121 err = uv_stdio_pipe_server(loop,
122 server_pipe,
123 server_access,
124 pipe_name,
125 sizeof(pipe_name));
126 if (err)
127 goto error;
128
129 /* Create child pipe handle. */
130 sa.nLength = sizeof sa;
131 sa.lpSecurityDescriptor = NULL;
132 sa.bInheritHandle = TRUE;
133
134 overlap = server_pipe->ipc || (flags & UV_OVERLAPPED_PIPE);
135 child_pipe = CreateFileA(pipe_name,
136 client_access,
137 0,
138 &sa,
139 OPEN_EXISTING,
140 overlap ? FILE_FLAG_OVERLAPPED : 0,
141 NULL);
142 if (child_pipe == INVALID_HANDLE_VALUE) {
143 err = GetLastError();
144 goto error;
145 }
146
147 #ifndef NDEBUG
148 /* Validate that the pipe was opened in the right mode. */
149 {
150 DWORD mode;
151 BOOL r = GetNamedPipeHandleState(child_pipe,
152 &mode,
153 NULL,
154 NULL,
155 NULL,
156 NULL,
157 0);
158 assert(r == TRUE);
159 assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT));
160 }
161 #endif
162
163 /* Do a blocking ConnectNamedPipe. This should not block because we have both
164 * ends of the pipe created. */
165 if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
166 if (GetLastError() != ERROR_PIPE_CONNECTED) {
167 err = GetLastError();
168 goto error;
169 }
170 }
171
172 /* The server end is now readable and/or writable. */
173 if (flags & UV_READABLE_PIPE)
174 server_pipe->flags |= UV_HANDLE_WRITABLE;
175 if (flags & UV_WRITABLE_PIPE)
176 server_pipe->flags |= UV_HANDLE_READABLE;
177
178 *child_pipe_ptr = child_pipe;
179 return 0;
180
181 error:
182 if (server_pipe->handle != INVALID_HANDLE_VALUE) {
183 uv_pipe_cleanup(loop, server_pipe);
184 }
185
186 if (child_pipe != INVALID_HANDLE_VALUE) {
187 CloseHandle(child_pipe);
188 }
189
190 return err;
191 }
192
193
uv__duplicate_handle(uv_loop_t * loop,HANDLE handle,HANDLE * dup)194 static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) {
195 HANDLE current_process;
196
197
198 /* _get_osfhandle will sometimes return -2 in case of an error. This seems to
199 * happen when fd <= 2 and the process' corresponding stdio handle is set to
200 * NULL. Unfortunately DuplicateHandle will happily duplicate (HANDLE) -2, so
201 * this situation goes unnoticed until someone tries to use the duplicate.
202 * Therefore we filter out known-invalid handles here. */
203 if (handle == INVALID_HANDLE_VALUE ||
204 handle == NULL ||
205 handle == (HANDLE) -2) {
206 *dup = INVALID_HANDLE_VALUE;
207 return ERROR_INVALID_HANDLE;
208 }
209
210 current_process = GetCurrentProcess();
211
212 if (!DuplicateHandle(current_process,
213 handle,
214 current_process,
215 dup,
216 0,
217 TRUE,
218 DUPLICATE_SAME_ACCESS)) {
219 *dup = INVALID_HANDLE_VALUE;
220 return GetLastError();
221 }
222
223 return 0;
224 }
225
226
uv__duplicate_fd(uv_loop_t * loop,int fd,HANDLE * dup)227 static int uv__duplicate_fd(uv_loop_t* loop, int fd, HANDLE* dup) {
228 HANDLE handle;
229
230 if (fd == -1) {
231 *dup = INVALID_HANDLE_VALUE;
232 return ERROR_INVALID_HANDLE;
233 }
234
235 handle = uv__get_osfhandle(fd);
236 return uv__duplicate_handle(loop, handle, dup);
237 }
238
239
uv__create_nul_handle(HANDLE * handle_ptr,DWORD access)240 int uv__create_nul_handle(HANDLE* handle_ptr,
241 DWORD access) {
242 HANDLE handle;
243 SECURITY_ATTRIBUTES sa;
244
245 sa.nLength = sizeof sa;
246 sa.lpSecurityDescriptor = NULL;
247 sa.bInheritHandle = TRUE;
248
249 handle = CreateFileW(L"NUL",
250 access,
251 FILE_SHARE_READ | FILE_SHARE_WRITE,
252 &sa,
253 OPEN_EXISTING,
254 0,
255 NULL);
256 if (handle == INVALID_HANDLE_VALUE) {
257 return GetLastError();
258 }
259
260 *handle_ptr = handle;
261 return 0;
262 }
263
264
uv__stdio_create(uv_loop_t * loop,const uv_process_options_t * options,BYTE ** buffer_ptr)265 int uv__stdio_create(uv_loop_t* loop,
266 const uv_process_options_t* options,
267 BYTE** buffer_ptr) {
268 BYTE* buffer;
269 int count, i;
270 int err;
271
272 count = options->stdio_count;
273
274 if (count < 0 || count > 255) {
275 /* Only support FDs 0-255 */
276 return ERROR_NOT_SUPPORTED;
277 } else if (count < 3) {
278 /* There should always be at least 3 stdio handles. */
279 count = 3;
280 }
281
282 /* Allocate the child stdio buffer */
283 buffer = (BYTE*) uv__malloc(CHILD_STDIO_SIZE(count));
284 if (buffer == NULL) {
285 return ERROR_OUTOFMEMORY;
286 }
287
288 /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can clean
289 * up on failure. */
290 CHILD_STDIO_COUNT(buffer) = count;
291 for (i = 0; i < count; i++) {
292 CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
293 CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;
294 }
295
296 for (i = 0; i < count; i++) {
297 uv_stdio_container_t fdopt;
298 if (i < options->stdio_count) {
299 fdopt = options->stdio[i];
300 } else {
301 fdopt.flags = UV_IGNORE;
302 }
303
304 switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |
305 UV_INHERIT_STREAM)) {
306 case UV_IGNORE:
307 /* Starting a process with no stdin/stout/stderr can confuse it. So no
308 * matter what the user specified, we make sure the first three FDs are
309 * always open in their typical modes, e. g. stdin be readable and
310 * stdout/err should be writable. For FDs > 2, don't do anything - all
311 * handles in the stdio buffer are initialized with.
312 * INVALID_HANDLE_VALUE, which should be okay. */
313 if (i <= 2) {
314 DWORD access = (i == 0) ? FILE_GENERIC_READ :
315 FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES;
316
317 err = uv__create_nul_handle(&CHILD_STDIO_HANDLE(buffer, i),
318 access);
319 if (err)
320 goto error;
321
322 CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
323 }
324 break;
325
326 case UV_CREATE_PIPE: {
327 /* Create a pair of two connected pipe ends; one end is turned into an
328 * uv_pipe_t for use by the parent. The other one is given to the
329 * child. */
330 uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream;
331 HANDLE child_pipe = INVALID_HANDLE_VALUE;
332
333 /* Create a new, connected pipe pair. stdio[i]. stream should point to
334 * an uninitialized, but not connected pipe handle. */
335 assert(fdopt.data.stream->type == UV_NAMED_PIPE);
336 assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION));
337 assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER));
338
339 err = uv__create_stdio_pipe_pair(loop,
340 parent_pipe,
341 &child_pipe,
342 fdopt.flags);
343 if (err)
344 goto error;
345
346 CHILD_STDIO_HANDLE(buffer, i) = child_pipe;
347 CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;
348 break;
349 }
350
351 case UV_INHERIT_FD: {
352 /* Inherit a raw FD. */
353 HANDLE child_handle;
354
355 /* Make an inheritable duplicate of the handle. */
356 err = uv__duplicate_fd(loop, fdopt.data.fd, &child_handle);
357 if (err) {
358 /* If fdopt. data. fd is not valid and fd <= 2, then ignore the
359 * error. */
360 if (fdopt.data.fd <= 2 && err == ERROR_INVALID_HANDLE) {
361 CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
362 CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;
363 break;
364 }
365 goto error;
366 }
367
368 /* Figure out what the type is. */
369 switch (GetFileType(child_handle)) {
370 case FILE_TYPE_DISK:
371 CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN;
372 break;
373
374 case FILE_TYPE_PIPE:
375 CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;
376 break;
377
378 case FILE_TYPE_CHAR:
379 case FILE_TYPE_REMOTE:
380 CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
381 break;
382
383 case FILE_TYPE_UNKNOWN:
384 if (GetLastError() != 0) {
385 err = GetLastError();
386 CloseHandle(child_handle);
387 goto error;
388 }
389 CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
390 break;
391
392 default:
393 assert(0);
394 return -1;
395 }
396
397 CHILD_STDIO_HANDLE(buffer, i) = child_handle;
398 break;
399 }
400
401 case UV_INHERIT_STREAM: {
402 /* Use an existing stream as the stdio handle for the child. */
403 HANDLE stream_handle, child_handle;
404 unsigned char crt_flags;
405 uv_stream_t* stream = fdopt.data.stream;
406
407 /* Leech the handle out of the stream. */
408 if (stream->type == UV_TTY) {
409 stream_handle = ((uv_tty_t*) stream)->handle;
410 crt_flags = FOPEN | FDEV;
411 } else if (stream->type == UV_NAMED_PIPE &&
412 stream->flags & UV_HANDLE_CONNECTION) {
413 stream_handle = ((uv_pipe_t*) stream)->handle;
414 crt_flags = FOPEN | FPIPE;
415 } else {
416 stream_handle = INVALID_HANDLE_VALUE;
417 crt_flags = 0;
418 }
419
420 if (stream_handle == NULL ||
421 stream_handle == INVALID_HANDLE_VALUE) {
422 /* The handle is already closed, or not yet created, or the stream
423 * type is not supported. */
424 err = ERROR_NOT_SUPPORTED;
425 goto error;
426 }
427
428 /* Make an inheritable copy of the handle. */
429 err = uv__duplicate_handle(loop, stream_handle, &child_handle);
430 if (err)
431 goto error;
432
433 CHILD_STDIO_HANDLE(buffer, i) = child_handle;
434 CHILD_STDIO_CRT_FLAGS(buffer, i) = crt_flags;
435 break;
436 }
437
438 default:
439 assert(0);
440 return -1;
441 }
442 }
443
444 *buffer_ptr = buffer;
445 return 0;
446
447 error:
448 uv__stdio_destroy(buffer);
449 return err;
450 }
451
452
uv__stdio_destroy(BYTE * buffer)453 void uv__stdio_destroy(BYTE* buffer) {
454 int i, count;
455
456 count = CHILD_STDIO_COUNT(buffer);
457 for (i = 0; i < count; i++) {
458 HANDLE handle = CHILD_STDIO_HANDLE(buffer, i);
459 if (handle != INVALID_HANDLE_VALUE) {
460 CloseHandle(handle);
461 }
462 }
463
464 uv__free(buffer);
465 }
466
467
uv__stdio_noinherit(BYTE * buffer)468 void uv__stdio_noinherit(BYTE* buffer) {
469 int i, count;
470
471 count = CHILD_STDIO_COUNT(buffer);
472 for (i = 0; i < count; i++) {
473 HANDLE handle = CHILD_STDIO_HANDLE(buffer, i);
474 if (handle != INVALID_HANDLE_VALUE) {
475 SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
476 }
477 }
478 }
479
480
uv__stdio_verify(BYTE * buffer,WORD size)481 int uv__stdio_verify(BYTE* buffer, WORD size) {
482 unsigned int count;
483
484 /* Check the buffer pointer. */
485 if (buffer == NULL)
486 return 0;
487
488 /* Verify that the buffer is at least big enough to hold the count. */
489 if (size < CHILD_STDIO_SIZE(0))
490 return 0;
491
492 /* Verify if the count is within range. */
493 count = CHILD_STDIO_COUNT(buffer);
494 if (count > 256)
495 return 0;
496
497 /* Verify that the buffer size is big enough to hold info for N FDs. */
498 if (size < CHILD_STDIO_SIZE(count))
499 return 0;
500
501 return 1;
502 }
503
504
uv__stdio_size(BYTE * buffer)505 WORD uv__stdio_size(BYTE* buffer) {
506 return (WORD) CHILD_STDIO_SIZE(CHILD_STDIO_COUNT((buffer)));
507 }
508
509
uv__stdio_handle(BYTE * buffer,int fd)510 HANDLE uv__stdio_handle(BYTE* buffer, int fd) {
511 return CHILD_STDIO_HANDLE(buffer, fd);
512 }
513