summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2010-05-10 11:53:54 +1000
committerDamien Miller <djm@mindrot.org>2010-05-10 11:53:54 +1000
commit22a29880bb324983a997f6bc03484879cae1f912 (patch)
treec0874752be98e019c58db2d5078bb52ff9cffa1b
parent85c50d7858424aa38a560142c04c93a70d50dff7 (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--ChangeLog5
-rw-r--r--session.c83
2 files changed, 60 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index f3d5c20eb..45389e49d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
1420100423 1920100423
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
diff --git a/session.c b/session.c
index e032de692..b49d08d60 100644
--- a/session.c
+++ b/session.c
@@ -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]. */