diff svr-main.c @ 1870:0dcc5b0d93fa

Make re-exec work with "dropbearmulti dropbear" The re-exec needs to know to use the dropbearmulti binary instead. Add a test for this case.
author Matt Johnston <matt@ucc.asn.au>
date Tue, 01 Feb 2022 22:18:23 +0800
parents adfcdfb161a4
children 2c9d635a1c04
line wrap: on
line diff
--- a/svr-main.c	Tue Feb 01 22:12:25 2022 +0800
+++ b/svr-main.c	Tue Feb 01 22:18:23 2022 +0800
@@ -36,16 +36,20 @@
 static void sigsegv_handler(int);
 static void sigintterm_handler(int fish);
 static void main_inetd(void);
-static void main_noinetd(int argc, char ** argv);
+static void main_noinetd(int argc, char ** argv, const char* multipath);
 static void commonsetup(void);
 
 #if defined(DBMULTI_dropbear) || !DROPBEAR_MULTI
 #if defined(DBMULTI_dropbear) && DROPBEAR_MULTI
-int dropbear_main(int argc, char ** argv)
+int dropbear_main(int argc, char ** argv, const char* multipath)
 #else
 int main(int argc, char ** argv)
 #endif
 {
+#if !DROPBEAR_MULTI
+	const char* multipath = NULL;
+#endif
+
 	_dropbear_exit = svr_dropbear_exit;
 	_dropbear_log = svr_dropbear_log;
 
@@ -80,7 +84,7 @@
 #endif
 
 #if NON_INETD_MODE
-	main_noinetd(argc, argv);
+	main_noinetd(argc, argv, multipath);
 	/* notreached */
 #endif
 
@@ -121,7 +125,7 @@
 #endif /* INETD_MODE */
 
 #if NON_INETD_MODE
-static void main_noinetd(int argc, char ** argv) {
+static void main_noinetd(int argc, char ** argv, const char* multipath) {
 	fd_set fds;
 	unsigned int i, j;
 	int val;
@@ -163,7 +167,11 @@
 	}
 
 #if DROPBEAR_DO_REEXEC
-	execfd = open(argv[0], O_CLOEXEC|O_RDONLY);
+	if (multipath) {
+		execfd = open(multipath, O_CLOEXEC|O_RDONLY);
+	} else {
+		execfd = open(argv[0], O_CLOEXEC|O_RDONLY);
+	}
 	if (execfd < 0) {
 		/* Just fallback to straight fork */
 		TRACE(("Couldn't open own binary %s, disabling re-exec: %s", argv[0], strerror(errno)))
@@ -338,11 +346,20 @@
 
 				if (execfd >= 0) {
 #if DROPBEAR_DO_REEXEC
-					/* Add "-2" to the args and re-execute ourself */
-					char **new_argv = m_malloc(sizeof(char*) * (argc+2));
-					memcpy(new_argv, argv, sizeof(char*) * argc);
-					new_argv[argc] = "-2";
-					new_argv[argc+1] = NULL;
+					/* Add "-2" to the args and re-execute ourself. */
+					char **new_argv = m_malloc(sizeof(char*) * (argc+3));
+					int pos0 = 0, new_argc = argc+1;
+
+					/* We need to specially handle "dropbearmulti dropbear". */
+					if (multipath) {
+						new_argv[0] = (char*)multipath;
+						pos0 = 1;
+						new_argc++;
+					}
+
+					memcpy(&new_argv[pos0], argv, sizeof(char*) * argc);
+					new_argv[new_argc-1] = "-2";
+					new_argv[new_argc] = NULL;
 
 					if ((dup2(childsock, STDIN_FILENO) < 0)) {
 						dropbear_exit("dup2 failed: %s", strerror(errno));