Skip to content
This repository was archived by the owner on May 4, 2018. It is now read-only.

Commit 359d667

Browse files
committed
unix: sanity-check fds before closing
Ensure that close() system calls don't close stdio file descriptors because that is almost never the intention. This is also a partial workaround for a kernel bug that seems to affect all Linux kernels when stdin is a pipe that gets closed: fd 0 keeps signalling EPOLLHUP but a subsequent call to epoll_ctl(EPOLL_CTL_DEL) fails with EBADF. See nodejs/node-v0.x-archive#6271 for details and a test case.
1 parent 636f205 commit 359d667

16 files changed

+85
-56
lines changed

src/unix/aix.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ int uv_exepath(char* buffer, size_t* size) {
8585
return fd;
8686

8787
res = read(fd, &ps, sizeof(ps));
88-
close(fd);
88+
uv__close(fd);
8989
if (res < 0)
9090
return res;
9191

@@ -179,7 +179,7 @@ int uv_resident_set_memory(size_t* rss) {
179179
*rss = (size_t)psinfo.pr_rssize * 1024;
180180
err = 0;
181181
}
182-
close(fd);
182+
uv__close(fd);
183183

184184
return err;
185185
}
@@ -291,14 +291,14 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
291291
}
292292

293293
if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) {
294-
close(sockfd);
294+
uv__close(sockfd);
295295
return -ENOSYS;
296296
}
297297

298298
ifc.ifc_req = (struct ifreq*)malloc(size);
299299
ifc.ifc_len = size;
300300
if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
301-
close(sockfd);
301+
uv__close(sockfd);
302302
return -ENOSYS;
303303
}
304304

@@ -317,7 +317,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
317317

318318
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
319319
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
320-
close(sockfd);
320+
uv__close(sockfd);
321321
return -ENOSYS;
322322
}
323323

@@ -331,7 +331,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
331331
*addresses = (uv_interface_address_t*)
332332
malloc(*count * sizeof(uv_interface_address_t));
333333
if (!(*addresses)) {
334-
close(sockfd);
334+
uv__close(sockfd);
335335
return -ENOMEM;
336336
}
337337
address = *addresses;
@@ -348,7 +348,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
348348

349349
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
350350
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
351-
close(sockfd);
351+
uv__close(sockfd);
352352
return -ENOSYS;
353353
}
354354

@@ -374,7 +374,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
374374

375375
#undef ADDR_SIZE
376376

377-
close(sockfd);
377+
uv__close(sockfd);
378378
return 0;
379379
}
380380

src/unix/async.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -237,11 +237,11 @@ void uv__async_stop(uv_loop_t* loop, struct uv__async* wa) {
237237
return;
238238

239239
uv__io_stop(loop, &wa->io_watcher, UV__POLLIN);
240-
close(wa->io_watcher.fd);
240+
uv__close(wa->io_watcher.fd);
241241
wa->io_watcher.fd = -1;
242242

243243
if (wa->wfd != -1) {
244-
close(wa->wfd);
244+
uv__close(wa->wfd);
245245
wa->wfd = -1;
246246
}
247247
}

src/unix/core.c

+23-3
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ int uv__socket(int domain, int type, int protocol) {
340340
err = uv__cloexec(sockfd, 1);
341341

342342
if (err) {
343-
close(sockfd);
343+
uv__close(sockfd);
344344
return err;
345345
}
346346

@@ -397,7 +397,7 @@ int uv__accept(int sockfd) {
397397
err = uv__nonblock(peerfd, 1);
398398

399399
if (err) {
400-
close(peerfd);
400+
uv__close(peerfd);
401401
return err;
402402
}
403403

@@ -406,6 +406,26 @@ int uv__accept(int sockfd) {
406406
}
407407

408408

409+
int uv__close(int fd) {
410+
int saved_errno;
411+
int rc;
412+
413+
assert(fd > -1); /* Catch uninitialized io_watcher.fd bugs. */
414+
assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */
415+
416+
saved_errno = errno;
417+
rc = close(fd);
418+
if (rc == -1) {
419+
rc = -errno;
420+
if (rc == -EINTR)
421+
rc = -EINPROGRESS; /* For platform/libc consistency. */
422+
errno = saved_errno;
423+
}
424+
425+
return rc;
426+
}
427+
428+
409429
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
410430

411431
int uv__nonblock(int fd, int set) {
@@ -514,7 +534,7 @@ int uv__dup(int fd) {
514534

515535
err = uv__cloexec(fd, 1);
516536
if (err) {
517-
close(fd);
537+
uv__close(fd);
518538
return err;
519539
}
520540

src/unix/internal.h

+1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ enum {
130130

131131
/* core */
132132
int uv__nonblock(int fd, int set);
133+
int uv__close(int fd);
133134
int uv__cloexec(int fd, int set);
134135
int uv__socket(int domain, int type, int protocol);
135136
int uv__dup(int fd);

src/unix/kqueue.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,6 @@ void uv__fs_event_close(uv_fs_event_t* handle) {
354354
free(handle->filename);
355355
handle->filename = NULL;
356356

357-
close(handle->event_watcher.fd);
357+
uv__close(handle->event_watcher.fd);
358358
handle->event_watcher.fd = -1;
359359
}

src/unix/linux-core.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ int uv__platform_loop_init(uv_loop_t* loop, int default_loop) {
9898
void uv__platform_loop_delete(uv_loop_t* loop) {
9999
if (loop->inotify_fd == -1) return;
100100
uv__io_stop(loop, &loop->inotify_read_watcher, UV__POLLIN);
101-
close(loop->inotify_fd);
101+
uv__close(loop->inotify_fd);
102102
loop->inotify_fd = -1;
103103
}
104104

@@ -309,7 +309,7 @@ int uv_resident_set_memory(size_t* rss) {
309309
n = read(fd, buf, sizeof(buf) - 1);
310310
while (n == -1 && errno == EINTR);
311311

312-
SAVE_ERRNO(close(fd));
312+
uv__close(fd);
313313
if (n == -1)
314314
return -errno;
315315
buf[n] = '\0';

src/unix/linux-inotify.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ static int new_inotify_fd(void) {
8181
err = uv__nonblock(fd, 1);
8282

8383
if (err) {
84-
close(fd);
84+
uv__close(fd);
8585
return err;
8686
}
8787

src/unix/loop.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,12 @@ static void uv__loop_delete(uv_loop_t* loop) {
136136
uv__async_stop(loop, &loop->async_watcher);
137137

138138
if (loop->emfile_fd != -1) {
139-
close(loop->emfile_fd);
139+
uv__close(loop->emfile_fd);
140140
loop->emfile_fd = -1;
141141
}
142142

143143
if (loop->backend_fd != -1) {
144-
close(loop->backend_fd);
144+
uv__close(loop->backend_fd);
145145
loop->backend_fd = -1;
146146
}
147147

src/unix/pipe.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,11 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
9393

9494
out:
9595
if (bound) {
96-
/* unlink() before close() to avoid races. */
96+
/* unlink() before uv__close() to avoid races. */
9797
assert(pipe_fname != NULL);
9898
unlink(pipe_fname);
9999
}
100-
close(sockfd);
100+
uv__close(sockfd);
101101
free((void*)pipe_fname);
102102
return err;
103103
}

src/unix/process.c

+12-10
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ static int uv__process_open_stream(uv_stdio_container_t* container,
231231
if (!(container->flags & UV_CREATE_PIPE) || pipefds[0] < 0)
232232
return 0;
233233

234-
if (close(pipefds[1]))
234+
if (uv__close(pipefds[1]))
235235
if (errno != EINTR && errno != EINPROGRESS)
236236
abort();
237237

@@ -285,8 +285,10 @@ static void uv__process_child_init(const uv_process_options_t* options,
285285
close_fd = pipes[fd][0];
286286
use_fd = pipes[fd][1];
287287

288-
if (use_fd >= 0)
289-
close(close_fd);
288+
if (use_fd >= 0) {
289+
if (close_fd != -1)
290+
uv__close(close_fd);
291+
}
290292
else if (fd >= 3)
291293
continue;
292294
else {
@@ -306,7 +308,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
306308
uv__cloexec(use_fd, 0);
307309
else {
308310
dup2(use_fd, fd);
309-
close(use_fd);
311+
uv__close(use_fd);
310312
}
311313

312314
if (fd <= 2)
@@ -414,8 +416,8 @@ int uv_spawn(uv_loop_t* loop,
414416

415417
if (pid == -1) {
416418
err = -errno;
417-
close(signal_pipe[0]);
418-
close(signal_pipe[1]);
419+
uv__close(signal_pipe[0]);
420+
uv__close(signal_pipe[1]);
419421
goto error;
420422
}
421423

@@ -424,7 +426,7 @@ int uv_spawn(uv_loop_t* loop,
424426
abort();
425427
}
426428

427-
close(signal_pipe[1]);
429+
uv__close(signal_pipe[1]);
428430

429431
process->errorno = 0;
430432
do
@@ -440,7 +442,7 @@ int uv_spawn(uv_loop_t* loop,
440442
else
441443
abort();
442444

443-
close(signal_pipe[0]);
445+
uv__close(signal_pipe[0]);
444446

445447
for (i = 0; i < options->stdio_count; i++) {
446448
err = uv__process_open_stream(options->stdio + i, pipes[i], i == 0);
@@ -465,8 +467,8 @@ int uv_spawn(uv_loop_t* loop,
465467

466468
error:
467469
for (i = 0; i < stdio_count; i++) {
468-
close(pipes[i][0]);
469-
close(pipes[i][1]);
470+
uv__close(pipes[i][0]);
471+
uv__close(pipes[i][1]);
470472
}
471473
free(pipes);
472474

src/unix/signal.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -240,12 +240,12 @@ void uv__signal_loop_cleanup(uv_loop_t* loop) {
240240
}
241241

242242
if (loop->signal_pipefd[0] != -1) {
243-
close(loop->signal_pipefd[0]);
243+
uv__close(loop->signal_pipefd[0]);
244244
loop->signal_pipefd[0] = -1;
245245
}
246246

247247
if (loop->signal_pipefd[1] != -1) {
248-
close(loop->signal_pipefd[1]);
248+
uv__close(loop->signal_pipefd[1]);
249249
loop->signal_pipefd[1] = -1;
250250
}
251251
}

src/unix/stream.c

+18-14
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ static int uv__open_cloexec(const char* path, int flags) {
8585

8686
err = uv__cloexec(fd, 1);
8787
if (err) {
88-
close(fd);
88+
uv__close(fd);
8989
return err;
9090
}
9191

@@ -309,7 +309,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
309309
timeout.tv_nsec = 1;
310310

311311
ret = kevent(kq, filter, 1, events, 1, &timeout);
312-
SAVE_ERRNO(close(kq));
312+
uv__close(kq);
313313

314314
if (ret == -1)
315315
return -errno;
@@ -357,8 +357,8 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
357357
return 0;
358358

359359
fatal4:
360-
close(s->fake_fd);
361-
close(s->int_fd);
360+
uv__close(s->fake_fd);
361+
uv__close(s->int_fd);
362362
s->fake_fd = -1;
363363
s->int_fd = -1;
364364
fatal3:
@@ -467,13 +467,13 @@ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) {
467467
if (loop->emfile_fd == -1)
468468
return -EMFILE;
469469

470-
close(loop->emfile_fd);
470+
uv__close(loop->emfile_fd);
471471

472472
for (;;) {
473473
fd = uv__accept(accept_fd);
474474

475475
if (fd != -1) {
476-
close(fd);
476+
uv__close(fd);
477477
continue;
478478
}
479479

@@ -572,7 +572,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
572572
UV_STREAM_READABLE | UV_STREAM_WRITABLE);
573573
if (err) {
574574
/* TODO handle error */
575-
close(server->accepted_fd);
575+
uv__close(server->accepted_fd);
576576
server->accepted_fd = -1;
577577
return err;
578578
}
@@ -581,7 +581,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
581581
case UV_UDP:
582582
err = uv_udp_open((uv_udp_t*) client, server->accepted_fd);
583583
if (err) {
584-
close(server->accepted_fd);
584+
uv__close(server->accepted_fd);
585585
server->accepted_fd = -1;
586586
return err;
587587
}
@@ -1424,8 +1424,8 @@ void uv__stream_close(uv_stream_t* handle) {
14241424
uv_thread_join(&s->thread);
14251425
uv_sem_destroy(&s->close_sem);
14261426
uv_sem_destroy(&s->async_sem);
1427-
close(s->fake_fd);
1428-
close(s->int_fd);
1427+
uv__close(s->fake_fd);
1428+
uv__close(s->int_fd);
14291429
uv_close((uv_handle_t*) &s->async, uv__stream_osx_cb_close);
14301430

14311431
handle->select = NULL;
@@ -1436,11 +1436,15 @@ void uv__stream_close(uv_stream_t* handle) {
14361436
uv_read_stop(handle);
14371437
uv__handle_stop(handle);
14381438

1439-
close(handle->io_watcher.fd);
1440-
handle->io_watcher.fd = -1;
1439+
if (handle->io_watcher.fd != -1) {
1440+
/* Don't close stdio file descriptors. Nothing good comes from it. */
1441+
if (handle->io_watcher.fd > STDERR_FILENO)
1442+
uv__close(handle->io_watcher.fd);
1443+
handle->io_watcher.fd = -1;
1444+
}
14411445

1442-
if (handle->accepted_fd >= 0) {
1443-
close(handle->accepted_fd);
1446+
if (handle->accepted_fd != -1) {
1447+
uv__close(handle->accepted_fd);
14441448
handle->accepted_fd = -1;
14451449
}
14461450

0 commit comments

Comments
 (0)