diff options
author | Damien Miller <djm@mindrot.org> | 2010-05-10 11:53:54 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2010-05-10 11:53:54 +1000 |
commit | 22a29880bb324983a997f6bc03484879cae1f912 (patch) | |
tree | c0874752be98e019c58db2d5078bb52ff9cffa1b | |
parent | 85c50d7858424aa38a560142c04c93a70d50dff7 (diff) |
- djm@cvs.openbsd.org 2010/04/23 22:42:05
[session.c]
set stderr to /dev/null for subsystems rather than just closing it.
avoids hangs if a subsystem or shell initialisation writes to stderr.
bz#1750; ok markus@
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | session.c | 83 |
2 files changed, 60 insertions, 28 deletions
@@ -10,6 +10,11 @@ | |||
10 | set "detach_close" flag when registering channel cleanup callbacks. | 10 | set "detach_close" flag when registering channel cleanup callbacks. |
11 | This causes the channel to close normally when its fds close and | 11 | This causes the channel to close normally when its fds close and |
12 | hangs when terminating a mux slave using ~. bz#1758; ok markus@ | 12 | hangs when terminating a mux slave using ~. bz#1758; ok markus@ |
13 | - djm@cvs.openbsd.org 2010/04/23 22:42:05 | ||
14 | [session.c] | ||
15 | set stderr to /dev/null for subsystems rather than just closing it. | ||
16 | avoids hangs if a subsystem or shell initialisation writes to stderr. | ||
17 | bz#1750; ok markus@ | ||
13 | 18 | ||
14 | 20100423 | 19 | 20100423 |
15 | - (dtucker) [configure.ac] Bug #1756: Check for the existence of a lib64 dir | 20 | - (dtucker) [configure.ac] Bug #1756: Check for the existence of a lib64 dir |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: session.c,v 1.252 2010/03/07 11:57:13 dtucker Exp $ */ | 1 | /* $OpenBSD: session.c,v 1.253 2010/04/23 22:42:05 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
4 | * All rights reserved | 4 | * All rights reserved |
@@ -47,6 +47,7 @@ | |||
47 | #include <arpa/inet.h> | 47 | #include <arpa/inet.h> |
48 | 48 | ||
49 | #include <errno.h> | 49 | #include <errno.h> |
50 | #include <fcntl.h> | ||
50 | #include <grp.h> | 51 | #include <grp.h> |
51 | #ifdef HAVE_PATHS_H | 52 | #ifdef HAVE_PATHS_H |
52 | #include <paths.h> | 53 | #include <paths.h> |
@@ -447,6 +448,9 @@ do_exec_no_pty(Session *s, const char *command) | |||
447 | #ifdef USE_PIPES | 448 | #ifdef USE_PIPES |
448 | int pin[2], pout[2], perr[2]; | 449 | int pin[2], pout[2], perr[2]; |
449 | 450 | ||
451 | if (s == NULL) | ||
452 | fatal("do_exec_no_pty: no session"); | ||
453 | |||
450 | /* Allocate pipes for communicating with the program. */ | 454 | /* Allocate pipes for communicating with the program. */ |
451 | if (pipe(pin) < 0) { | 455 | if (pipe(pin) < 0) { |
452 | error("%s: pipe in: %.100s", __func__, strerror(errno)); | 456 | error("%s: pipe in: %.100s", __func__, strerror(errno)); |
@@ -458,33 +462,59 @@ do_exec_no_pty(Session *s, const char *command) | |||
458 | close(pin[1]); | 462 | close(pin[1]); |
459 | return -1; | 463 | return -1; |
460 | } | 464 | } |
461 | if (pipe(perr) < 0) { | 465 | if (s->is_subsystem) { |
462 | error("%s: pipe err: %.100s", __func__, strerror(errno)); | 466 | if ((perr[1] = open(_PATH_DEVNULL, O_WRONLY)) == -1) { |
463 | close(pin[0]); | 467 | error("%s: open(%s): %s", __func__, _PATH_DEVNULL, |
464 | close(pin[1]); | 468 | strerror(errno)); |
465 | close(pout[0]); | 469 | close(pin[0]); |
466 | close(pout[1]); | 470 | close(pin[1]); |
467 | return -1; | 471 | close(pout[0]); |
472 | close(pout[1]); | ||
473 | return -1; | ||
474 | } | ||
475 | perr[0] = -1; | ||
476 | } else { | ||
477 | if (pipe(perr) < 0) { | ||
478 | error("%s: pipe err: %.100s", __func__, | ||
479 | strerror(errno)); | ||
480 | close(pin[0]); | ||
481 | close(pin[1]); | ||
482 | close(pout[0]); | ||
483 | close(pout[1]); | ||
484 | return -1; | ||
485 | } | ||
468 | } | 486 | } |
469 | #else | 487 | #else |
470 | int inout[2], err[2]; | 488 | int inout[2], err[2]; |
471 | 489 | ||
490 | if (s == NULL) | ||
491 | fatal("do_exec_no_pty: no session"); | ||
492 | |||
472 | /* Uses socket pairs to communicate with the program. */ | 493 | /* Uses socket pairs to communicate with the program. */ |
473 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) { | 494 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) { |
474 | error("%s: socketpair #1: %.100s", __func__, strerror(errno)); | 495 | error("%s: socketpair #1: %.100s", __func__, strerror(errno)); |
475 | return -1; | 496 | return -1; |
476 | } | 497 | } |
477 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) { | 498 | if (s->is_subsystem) { |
478 | error("%s: socketpair #2: %.100s", __func__, strerror(errno)); | 499 | if ((err[0] = open(_PATH_DEVNULL, O_WRONLY)) == -1) { |
479 | close(inout[0]); | 500 | error("%s: open(%s): %s", __func__, _PATH_DEVNULL, |
480 | close(inout[1]); | 501 | strerror(errno)); |
481 | return -1; | 502 | close(inout[0]); |
503 | close(inout[1]); | ||
504 | return -1; | ||
505 | } | ||
506 | err[1] = -1; | ||
507 | } else { | ||
508 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) { | ||
509 | error("%s: socketpair #2: %.100s", __func__, | ||
510 | strerror(errno)); | ||
511 | close(inout[0]); | ||
512 | close(inout[1]); | ||
513 | return -1; | ||
514 | } | ||
482 | } | 515 | } |
483 | #endif | 516 | #endif |
484 | 517 | ||
485 | if (s == NULL) | ||
486 | fatal("do_exec_no_pty: no session"); | ||
487 | |||
488 | session_proctitle(s); | 518 | session_proctitle(s); |
489 | 519 | ||
490 | /* Fork the child. */ | 520 | /* Fork the child. */ |
@@ -496,13 +526,15 @@ do_exec_no_pty(Session *s, const char *command) | |||
496 | close(pin[1]); | 526 | close(pin[1]); |
497 | close(pout[0]); | 527 | close(pout[0]); |
498 | close(pout[1]); | 528 | close(pout[1]); |
499 | close(perr[0]); | 529 | if (perr[0] != -1) |
530 | close(perr[0]); | ||
500 | close(perr[1]); | 531 | close(perr[1]); |
501 | #else | 532 | #else |
502 | close(inout[0]); | 533 | close(inout[0]); |
503 | close(inout[1]); | 534 | close(inout[1]); |
504 | close(err[0]); | 535 | close(err[0]); |
505 | close(err[1]); | 536 | if (err[1] != -1) |
537 | close(err[1]); | ||
506 | #endif | 538 | #endif |
507 | return -1; | 539 | return -1; |
508 | case 0: | 540 | case 0: |
@@ -536,7 +568,8 @@ do_exec_no_pty(Session *s, const char *command) | |||
536 | close(pout[1]); | 568 | close(pout[1]); |
537 | 569 | ||
538 | /* Redirect stderr. */ | 570 | /* Redirect stderr. */ |
539 | close(perr[0]); | 571 | if (perr[0] != -1) |
572 | close(perr[0]); | ||
540 | if (dup2(perr[1], 2) < 0) | 573 | if (dup2(perr[1], 2) < 0) |
541 | perror("dup2 stderr"); | 574 | perror("dup2 stderr"); |
542 | close(perr[1]); | 575 | close(perr[1]); |
@@ -547,7 +580,8 @@ do_exec_no_pty(Session *s, const char *command) | |||
547 | * seem to depend on it. | 580 | * seem to depend on it. |
548 | */ | 581 | */ |
549 | close(inout[1]); | 582 | close(inout[1]); |
550 | close(err[1]); | 583 | if (err[1] != -1) |
584 | close(err[1]); | ||
551 | if (dup2(inout[0], 0) < 0) /* stdin */ | 585 | if (dup2(inout[0], 0) < 0) /* stdin */ |
552 | perror("dup2 stdin"); | 586 | perror("dup2 stdin"); |
553 | if (dup2(inout[0], 1) < 0) /* stdout (same as stdin) */ | 587 | if (dup2(inout[0], 1) < 0) /* stdout (same as stdin) */ |
@@ -595,10 +629,6 @@ do_exec_no_pty(Session *s, const char *command) | |||
595 | close(perr[1]); | 629 | close(perr[1]); |
596 | 630 | ||
597 | if (compat20) { | 631 | if (compat20) { |
598 | if (s->is_subsystem) { | ||
599 | close(perr[0]); | ||
600 | perr[0] = -1; | ||
601 | } | ||
602 | session_set_fds(s, pin[1], pout[0], perr[0], 0); | 632 | session_set_fds(s, pin[1], pout[0], perr[0], 0); |
603 | } else { | 633 | } else { |
604 | /* Enter the interactive session. */ | 634 | /* Enter the interactive session. */ |
@@ -615,10 +645,7 @@ do_exec_no_pty(Session *s, const char *command) | |||
615 | * handle the case that fdin and fdout are the same. | 645 | * handle the case that fdin and fdout are the same. |
616 | */ | 646 | */ |
617 | if (compat20) { | 647 | if (compat20) { |
618 | session_set_fds(s, inout[1], inout[1], | 648 | session_set_fds(s, inout[1], inout[1], err[1], 0); |
619 | s->is_subsystem ? -1 : err[1], 0); | ||
620 | if (s->is_subsystem) | ||
621 | close(err[1]); | ||
622 | } else { | 649 | } else { |
623 | server_loop(pid, inout[1], inout[1], err[1]); | 650 | server_loop(pid, inout[1], inout[1], err[1]); |
624 | /* server_loop has closed inout[1] and err[1]. */ | 651 | /* server_loop has closed inout[1] and err[1]. */ |