diff --git a/src/crypto/prng.h b/src/crypto/prng.h index efcddf0f8..72b42581b 100644 --- a/src/crypto/prng.h +++ b/src/crypto/prng.h @@ -65,7 +65,7 @@ class PRNG { randfile.read( static_cast( dest ), size ); if ( !randfile ) { - throw CryptoException( "Could not read from " + std::string( rdev ) ); + throw CryptoException( "Could not read from " + std::string( rdev ), true ); } } diff --git a/src/frontend/mosh-client.cc b/src/frontend/mosh-client.cc index 5b1a919e4..efe45fb37 100644 --- a/src/frontend/mosh-client.cc +++ b/src/frontend/mosh-client.cc @@ -40,6 +40,7 @@ #include "crypto.h" #include "locale_utils.h" #include "fatal_assert.h" +#include "stdfds.h" /* These need to be included last because of conflicting defines. */ /* @@ -108,6 +109,9 @@ int main( int argc, char *argv[] ) #endif { unsigned int verbose = 0; + /* Make sure all standard i/o fds are open on something. */ + open_stdfds(); + /* For security, make sure we don't dump core */ Crypto::disable_dumping_core(); diff --git a/src/frontend/mosh-server.cc b/src/frontend/mosh-server.cc index f6d2ff3bc..81d00086e 100644 --- a/src/frontend/mosh-server.cc +++ b/src/frontend/mosh-server.cc @@ -88,6 +88,7 @@ #include "select.h" #include "timestamp.h" #include "fatal_assert.h" +#include "stdfds.h" #ifndef _PATH_BSHELL #define _PATH_BSHELL "/bin/sh" @@ -170,6 +171,9 @@ static string get_SSH_IP( void ) int main( int argc, char *argv[] ) { + /* Make sure all standard i/o fds are open on something. */ + open_stdfds(); + /* For security, make sure we don't dump core */ Crypto::disable_dumping_core(); @@ -478,35 +482,16 @@ static int run_server( const char *desired_ip, const char *desired_port, exit( 0 ); } - int master; - - /* close file descriptors */ + /* Close file descriptors on tty */ if ( verbose == 0 ) { - /* Necessary to properly detach on old versions of sshd (e.g. RHEL/CentOS 5.0). */ - int nullfd; - - nullfd = open( "/dev/null", O_RDWR ); - if ( nullfd == -1 ) { - perror( "open" ); - exit( 1 ); - } - - if ( dup2 ( nullfd, STDIN_FILENO ) < 0 || - dup2 ( nullfd, STDOUT_FILENO ) < 0 || - dup2 ( nullfd, STDERR_FILENO ) < 0 ) { - perror( "dup2" ); - exit( 1 ); - } - - if ( close( nullfd ) < 0 ) { - perror( "close" ); - exit( 1 ); - } + detach_stdfds(); } char utmp_entry[ 64 ] = { 0 }; snprintf( utmp_entry, 64, "mosh [%ld]", static_cast( getpid() ) ); + int master; + /* Fork child process */ pid_t child = forkpty( &master, NULL, NULL, &window_size ); diff --git a/src/util/Makefile.am b/src/util/Makefile.am index d189d49f2..bd1bd1cfc 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -2,4 +2,4 @@ AM_CXXFLAGS = $(WARNING_CXXFLAGS) $(PICKY_CXXFLAGS) $(HARDEN_CFLAGS) $(MISC_CXXF noinst_LIBRARIES = libmoshutil.a -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 +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 diff --git a/src/util/stdfds.cc b/src/util/stdfds.cc new file mode 100644 index 000000000..f81ff91db --- /dev/null +++ b/src/util/stdfds.cc @@ -0,0 +1,95 @@ +/* + Mosh: the mobile shell + Copyright 2012 Keith Winstein + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations including + the two. + + You must obey the GNU General Public License in all respects for all + of the code used other than OpenSSL. If you modify file(s) with this + exception, you may extend this exception to your version of the + file(s), but you are not obligated to do so. If you do not wish to do + so, delete this exception statement from your version. If you delete + this exception statement from all source files in the program, then + also delete it here. +*/ + +#include "config.h" + +#include +#include +#include +#include + +#ifdef HAVE_PATHS_H +#include +#endif + +#include + +#include "stdfds.h" + +#ifndef _PATH_DEVNULL +#define _PATH_DEVNULL "/dev/null" +#endif + +void open_stdfds() +{ + /* Make sure all standard i/o fds are open on something. */ + for ( int fd = 0; fd <= STDERR_FILENO; fd++) { + if ( ::fcntl( fd, F_GETFD ) < 0 ) { + if ( ::open( _PATH_DEVNULL, O_RDWR ) != fd ) { + /* given the circumstances, even writing an error may fail */ + const char* stdErr = "cannot open standard file descriptor\n"; + if ( ::write( STDERR_FILENO, stdErr, strlen(stdErr) ) < static_cast( strlen(stdErr) ) ) { + ::abort(); + } + ::exit(1); + } + } + } +} + +void detach_stdfds() +{ + /* Necessary to properly detach on old versions of sshd (e.g. RHEL/CentOS 5.0). */ + int nullfd; + + nullfd = ::open( _PATH_DEVNULL, O_RDWR ); + if ( nullfd == -1 ) { + ::perror( "open" ); + ::exit( 1 ); + } + + if ( ::dup2 ( nullfd, STDIN_FILENO ) < 0 || + ::dup2 ( nullfd, STDOUT_FILENO ) < 0 || + ::dup2 ( nullfd, STDERR_FILENO ) < 0 ) { + ::perror( "dup2" ); + ::exit( 1 ); + } + + if ( nullfd > STDERR_FILENO && ::close( nullfd ) < 0 ) { + /* + * This goes to /dev/null, but do it anyway, because it will + * show up on system call traces. + */ + ::perror( "close" ); + ::exit( 1 ); + } +} diff --git a/src/util/stdfds.h b/src/util/stdfds.h new file mode 100644 index 000000000..cbe5fec0f --- /dev/null +++ b/src/util/stdfds.h @@ -0,0 +1,39 @@ +/* + Mosh: the mobile shell + Copyright 2012 Keith Winstein + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations including + the two. + + You must obey the GNU General Public License in all respects for all + of the code used other than OpenSSL. If you modify file(s) with this + exception, you may extend this exception to your version of the + file(s), but you are not obligated to do so. If you do not wish to do + so, delete this exception statement from your version. If you delete + this exception statement from all source files in the program, then + also delete it here. +*/ + +#ifndef STDFDS_HPP +#define STDFDS_HPP + +void open_stdfds(); +void detach_stdfds(); + +#endif