summaryrefslogtreecommitdiff
path: root/usr.bin/ssh
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2004-06-25 18:43:37 +0000
committerDamien Miller <djm@cvs.openbsd.org>2004-06-25 18:43:37 +0000
commitdb01f12fc2b03e122f1fe178593a503773f360c5 (patch)
tree95fa07a781400726862ef82ccca4a329c6a3932e /usr.bin/ssh
parent1fef12e248eccc18fb9e2bc42a25274a6a608ca4 (diff)
fix broken fd handling in the re-exec fallback path, particularly when
/dev/crypto is in use; ok deraadt@ markus@
Diffstat (limited to 'usr.bin/ssh')
-rw-r--r--usr.bin/ssh/sshd.c42
1 files changed, 28 insertions, 14 deletions
diff --git a/usr.bin/ssh/sshd.c b/usr.bin/ssh/sshd.c
index e5670bb4844..d90718d55cf 100644
--- a/usr.bin/ssh/sshd.c
+++ b/usr.bin/ssh/sshd.c
@@ -42,7 +42,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshd.c,v 1.295 2004/06/25 01:16:09 djm Exp $");
+RCSID("$OpenBSD: sshd.c,v 1.296 2004/06/25 18:43:36 djm Exp $");
#include <openssl/dh.h>
#include <openssl/bn.h>
@@ -93,6 +93,12 @@ int deny_severity = LOG_WARNING;
#define O_NOCTTY 0
#endif
+/* Re-exec fds */
+#define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
+#define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2)
+#define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3)
+#define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4)
+
extern char *__progname;
/* Server configuration options. */
@@ -981,7 +987,9 @@ main(int ac, char **av)
if (rexec_flag && (av[0] == NULL || *av[0] != '/'))
fatal("sshd re-exec requires execution with an absolute path");
if (rexeced_flag)
- closefrom(STDERR_FILENO + 3);
+ closefrom(REEXEC_MIN_FREE_FD);
+ else
+ closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
SSLeay_add_all_algorithms();
channel_set_af(IPv4or6);
@@ -1005,7 +1013,7 @@ main(int ac, char **av)
/* Fetch our configuration */
buffer_init(&cfg);
if (rexeced_flag)
- recv_rexec_state(STDERR_FILENO + 2, &cfg);
+ recv_rexec_state(REEXEC_CONFIG_PASS_FD, &cfg);
else
load_server_config(config_file_name, &cfg);
@@ -1167,11 +1175,11 @@ main(int ac, char **av)
startup_pipe = -1;
if (rexeced_flag) {
- close(STDERR_FILENO + 2);
+ close(REEXEC_CONFIG_PASS_FD);
sock_in = sock_out = dup(STDIN_FILENO);
if (!debug_flag) {
- startup_pipe = dup(STDERR_FILENO + 1);
- close(STDERR_FILENO + 1);
+ startup_pipe = dup(REEXEC_STARTUP_PIPE_FD);
+ close(REEXEC_STARTUP_PIPE_FD);
}
} else {
sock_in = dup(STDIN_FILENO);
@@ -1432,6 +1440,7 @@ main(int ac, char **av)
sock_in = newsock;
sock_out = newsock;
log_init(__progname, options.log_level, options.log_facility, log_stderr);
+ close(config_s[0]);
break;
}
}
@@ -1476,35 +1485,40 @@ main(int ac, char **av)
if (rexec_flag) {
int fd;
- debug("rexec newsock %d pipe %d sock %d", newsock,
- startup_pipe, config_s[0]);
+ debug("rexec start in %d out %d newsock %d pipe %d sock %d",
+ sock_in, sock_out, newsock, startup_pipe, config_s[0]);
dup2(newsock, STDIN_FILENO);
dup2(STDIN_FILENO, STDOUT_FILENO);
if (startup_pipe == -1)
- close(STDERR_FILENO + 1);
+ close(REEXEC_STARTUP_PIPE_FD);
else
- dup2(startup_pipe, STDERR_FILENO + 1);
+ dup2(startup_pipe, REEXEC_STARTUP_PIPE_FD);
- dup2(config_s[1], STDERR_FILENO + 2);
+ dup2(config_s[1], REEXEC_CONFIG_PASS_FD);
close(config_s[1]);
+ close(startup_pipe);
+
execv(rexec_argv[0], rexec_argv);
/* Reexec has failed, fall back and continue */
error("rexec of %s failed: %s", rexec_argv[0], strerror(errno));
- recv_rexec_state(STDERR_FILENO + 2, NULL);
+ recv_rexec_state(REEXEC_CONFIG_PASS_FD, NULL);
log_init(__progname, options.log_level,
options.log_facility, log_stderr);
/* Clean up fds */
+ startup_pipe = REEXEC_STARTUP_PIPE_FD;
close(config_s[1]);
- close(STDERR_FILENO + 1);
- close(STDERR_FILENO + 2);
+ close(REEXEC_CONFIG_PASS_FD);
+ newsock = sock_out = sock_in = dup(STDIN_FILENO);
if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
if (fd > STDERR_FILENO)
close(fd);
}
+ debug("rexec cleanup in %d out %d newsock %d pipe %d sock %d",
+ sock_in, sock_out, newsock, startup_pipe, config_s[0]);
}
/*