Skip to content

Commit 78f5bb3

Browse files
committed
Make sure all stdio fds are open. Refactor detach-from-tty code.
Fixes unpleasant behavior in mosh-server when, say, stderr is closed.
1 parent 014025e commit 78f5bb3

File tree

5 files changed

+147
-24
lines changed

5 files changed

+147
-24
lines changed

src/frontend/mosh-client.cc

+4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "crypto.h"
4141
#include "locale_utils.h"
4242
#include "fatal_assert.h"
43+
#include "stdfds.h"
4344

4445
/* These need to be included last because of conflicting defines. */
4546
/*
@@ -108,6 +109,9 @@ int main( int argc, char *argv[] )
108109
#endif
109110
{
110111
unsigned int verbose = 0;
112+
/* Make sure all standard i/o fds are open on something. */
113+
open_stdfds();
114+
111115
/* For security, make sure we don't dump core */
112116
Crypto::disable_dumping_core();
113117

src/frontend/mosh-server.cc

+8-23
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
#include "select.h"
8989
#include "timestamp.h"
9090
#include "fatal_assert.h"
91+
#include "stdfds.h"
9192

9293
#ifndef _PATH_BSHELL
9394
#define _PATH_BSHELL "/bin/sh"
@@ -170,6 +171,9 @@ static string get_SSH_IP( void )
170171

171172
int main( int argc, char *argv[] )
172173
{
174+
/* Make sure all standard i/o fds are open on something. */
175+
open_stdfds();
176+
173177
/* For security, make sure we don't dump core */
174178
Crypto::disable_dumping_core();
175179

@@ -478,35 +482,16 @@ static int run_server( const char *desired_ip, const char *desired_port,
478482
exit( 0 );
479483
}
480484

481-
int master;
482-
483-
/* close file descriptors */
485+
/* Close file descriptors on tty */
484486
if ( verbose == 0 ) {
485-
/* Necessary to properly detach on old versions of sshd (e.g. RHEL/CentOS 5.0). */
486-
int nullfd;
487-
488-
nullfd = open( "/dev/null", O_RDWR );
489-
if ( nullfd == -1 ) {
490-
perror( "open" );
491-
exit( 1 );
492-
}
493-
494-
if ( dup2 ( nullfd, STDIN_FILENO ) < 0 ||
495-
dup2 ( nullfd, STDOUT_FILENO ) < 0 ||
496-
dup2 ( nullfd, STDERR_FILENO ) < 0 ) {
497-
perror( "dup2" );
498-
exit( 1 );
499-
}
500-
501-
if ( close( nullfd ) < 0 ) {
502-
perror( "close" );
503-
exit( 1 );
504-
}
487+
detach_stdfds();
505488
}
506489

507490
char utmp_entry[ 64 ] = { 0 };
508491
snprintf( utmp_entry, 64, "mosh [%ld]", static_cast<long int>( getpid() ) );
509492

493+
int master;
494+
510495
/* Fork child process */
511496
pid_t child = forkpty( &master, NULL, NULL, &window_size );
512497

src/util/Makefile.am

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ AM_CXXFLAGS = $(WARNING_CXXFLAGS) $(PICKY_CXXFLAGS) $(HARDEN_CFLAGS) $(MISC_CXXF
22

33
noinst_LIBRARIES = libmoshutil.a
44

5-
libmoshutil_a_SOURCES = locale_utils.cc locale_utils.h swrite.cc swrite.h dos_assert.h fatal_assert.h select.h select.cc timestamp.h timestamp.cc pty_compat.cc pty_compat.h shared.h
5+
libmoshutil_a_SOURCES = locale_utils.cc locale_utils.h swrite.cc swrite.h dos_assert.h fatal_assert.h select.h select.cc timestamp.h timestamp.cc pty_compat.cc pty_compat.h shared.h stdfds.cc stdfds.h

src/util/stdfds.cc

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
Mosh: the mobile shell
3+
Copyright 2012 Keith Winstein
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
18+
In addition, as a special exception, the copyright holders give
19+
permission to link the code of portions of this program with the
20+
OpenSSL library under certain conditions as described in each
21+
individual source file, and distribute linked combinations including
22+
the two.
23+
24+
You must obey the GNU General Public License in all respects for all
25+
of the code used other than OpenSSL. If you modify file(s) with this
26+
exception, you may extend this exception to your version of the
27+
file(s), but you are not obligated to do so. If you do not wish to do
28+
so, delete this exception statement from your version. If you delete
29+
this exception statement from all source files in the program, then
30+
also delete it here.
31+
*/
32+
33+
#include "config.h"
34+
35+
#include <fcntl.h>
36+
#include <stdio.h>
37+
#include <stdlib.h>
38+
#include <unistd.h>
39+
40+
#ifdef HAVE_PATHS_H
41+
#include <paths.h>
42+
#endif
43+
44+
#include <cstring>
45+
46+
#include "stdfds.h"
47+
48+
#ifndef _PATH_DEVNULL
49+
#define _PATH_DEVNULL "/dev/null"
50+
#endif
51+
52+
void open_stdfds()
53+
{
54+
/* Make sure all standard i/o fds are open on something. */
55+
for ( int fd = 0; fd <= STDERR_FILENO; fd++) {
56+
if ( ::fcntl( fd, F_GETFD ) < 0 ) {
57+
if ( ::open( _PATH_DEVNULL, O_RDWR ) != fd ) {
58+
/* given the circumstances, even writing an error may fail */
59+
const char* stdErr = "cannot open standard file descriptor\n";
60+
if ( ::write( STDERR_FILENO, stdErr, strlen(stdErr) ) < static_cast<ssize_t>( strlen(stdErr) ) ) {
61+
::abort();
62+
}
63+
::exit(1);
64+
}
65+
}
66+
}
67+
}
68+
69+
void detach_stdfds()
70+
{
71+
/* Necessary to properly detach on old versions of sshd (e.g. RHEL/CentOS 5.0). */
72+
int nullfd;
73+
74+
nullfd = ::open( _PATH_DEVNULL, O_RDWR );
75+
if ( nullfd == -1 ) {
76+
::perror( "open" );
77+
::exit( 1 );
78+
}
79+
80+
if ( ::dup2 ( nullfd, STDIN_FILENO ) < 0 ||
81+
::dup2 ( nullfd, STDOUT_FILENO ) < 0 ||
82+
::dup2 ( nullfd, STDERR_FILENO ) < 0 ) {
83+
::perror( "dup2" );
84+
::exit( 1 );
85+
}
86+
87+
if ( nullfd > STDERR_FILENO && ::close( nullfd ) < 0 ) {
88+
/*
89+
* This goes to /dev/null, but do it anyway, because it will
90+
* show up on system call traces.
91+
*/
92+
::perror( "close" );
93+
::exit( 1 );
94+
}
95+
}

src/util/stdfds.h

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
Mosh: the mobile shell
3+
Copyright 2012 Keith Winstein
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
18+
In addition, as a special exception, the copyright holders give
19+
permission to link the code of portions of this program with the
20+
OpenSSL library under certain conditions as described in each
21+
individual source file, and distribute linked combinations including
22+
the two.
23+
24+
You must obey the GNU General Public License in all respects for all
25+
of the code used other than OpenSSL. If you modify file(s) with this
26+
exception, you may extend this exception to your version of the
27+
file(s), but you are not obligated to do so. If you do not wish to do
28+
so, delete this exception statement from your version. If you delete
29+
this exception statement from all source files in the program, then
30+
also delete it here.
31+
*/
32+
33+
#ifndef STDFDS_HPP
34+
#define STDFDS_HPP
35+
36+
void open_stdfds();
37+
void detach_stdfds();
38+
39+
#endif

0 commit comments

Comments
 (0)