summaryrefslogtreecommitdiff
path: root/session.c
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 /session.c
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@
Diffstat (limited to 'session.c')
-rw-r--r--session.c83
1 files changed, 55 insertions, 28 deletions
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]. */