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.
This commit is contained in:
Matt Johnston 2022-02-01 22:18:23 +08:00
parent a95ca34a10
commit 3939321750
6 changed files with 94 additions and 51 deletions

9
.github/multiwrapper vendored Executable file
View File

@ -0,0 +1,9 @@
#!/bin/sh
# symlink this to dropbear/dbclient/dropbearkey next to dropbearmulti
# good enough for testing purposes.
DIR=$(dirname $0)
PROG=$(basename $0)
exec $DIR/dropbearmulti $PROG "$@"

View File

@ -22,37 +22,42 @@ jobs:
- name: multi binary
multi: 1
multilink: 1
- name: bundled libtom, bionic , no writev()
# test can use an older distro with bundled libtommath
os: ubuntu-18.04
configure_flags: --enable-bundled-libtom --enable-werror
# NOWRITEV is unrelated, test here to save a job
nowritev: 1
# our tests expect >= python3.7
runcheck: 'no'
# - name: multi binary, dropbearmulti argv0
# multi: 1
# multiwrapper: 1
- name: linux clang
cc: clang
# - name: bundled libtom, bionic , no writev()
# # test can use an older distro with bundled libtommath
# os: ubuntu-18.04
# configure_flags: --enable-bundled-libtom --enable-werror
# # NOWRITEV is unrelated, test here to save a job
# nowritev: 1
# # our tests expect >= python3.7
# runcheck: 'no'
- name: macos 10.15
os: macos-10.15
cc: clang
# OS X says daemon() and utmp are deprecated
extracflags: -Wno-deprecated-declarations
runcheck: 'no'
apt: 'no'
# fails with:
# .../ranlib: file: libtomcrypt.a(cbc_setiv.o) has no symbols
ranlib: ranlib -no_warning_for_no_symbols
# - name: linux clang
# cc: clang
- name: macos 11
os: macos-11
cc: clang
extracflags: -Wno-deprecated-declarations
runcheck: 'no'
apt: 'no'
ranlib: ranlib -no_warning_for_no_symbols
# - name: macos 10.15
# os: macos-10.15
# cc: clang
# # OS X says daemon() and utmp are deprecated
# extracflags: -Wno-deprecated-declarations
# runcheck: 'no'
# apt: 'no'
# # fails with:
# # .../ranlib: file: libtomcrypt.a(cbc_setiv.o) has no symbols
# ranlib: ranlib -no_warning_for_no_symbols
# - name: macos 11
# os: macos-11
# cc: clang
# extracflags: -Wno-deprecated-declarations
# runcheck: 'no'
# apt: 'no'
# ranlib: ranlib -no_warning_for_no_symbols
# # Fuzzers run standalone. A bit superfluous with cifuzz, but
# # good to run the whole corpus to keep it working.
@ -102,9 +107,16 @@ jobs:
run: make -j3
- name: multilink
if: ${{ matrix.multi }}
if: ${{ matrix.multilink }}
run: make multilink
- name: multi wrapper script
if: ${{ matrix.multiwrapper }}
run: |
cp .github/multiwrapper dropbear
cp .github/multiwrapper dbclient
cp .github/multiwrapper dropbearkey
- name: makefuzz
run: make fuzzstandalone
if: ${{ matrix.fuzz }}

View File

@ -23,20 +23,15 @@
* SOFTWARE. */
#include "includes.h"
#include "dbutil.h"
/* definitions are cleanest if we just put them here */
int dropbear_main(int argc, char ** argv);
int cli_main(int argc, char ** argv);
int dropbearkey_main(int argc, char ** argv);
int dropbearconvert_main(int argc, char ** argv);
int scp_main(int argc, char ** argv);
static int runprog(const char *progname, int argc, char ** argv, int *match) {
static int runprog(const char *multipath,
const char *progname, int argc, char ** argv, int *match) {
*match = DROPBEAR_SUCCESS;
#ifdef DBMULTI_dropbear
if (strcmp(progname, "dropbear") == 0) {
return dropbear_main(argc, argv);
return dropbear_main(argc, argv, multipath);
}
#endif
#ifdef DBMULTI_dbclient
@ -72,7 +67,7 @@ int main(int argc, char ** argv) {
int match, res;
/* figure which form we're being called as */
const char* progname = basename(argv[i]);
res = runprog(progname, argc-i, &argv[i], &match);
res = runprog(argv[0], progname, argc-i, &argv[i], &match);
if (match == DROPBEAR_SUCCESS) {
return res;
}

View File

@ -99,4 +99,12 @@ int fd_read_pending(int fd);
#define DROPBEAR_FD_ZERO(fds) FD_ZERO(fds)
#endif
/* dropbearmulti entry points */
int dropbear_main(int argc, char ** argv, const char * multipath);
int cli_main(int argc, char ** argv);
int dropbearkey_main(int argc, char ** argv);
int dropbearconvert_main(int argc, char ** argv);
int scp_main(int argc, char ** argv);
#endif /* DROPBEAR_DBUTIL_H_ */

View File

@ -36,16 +36,20 @@ static void sigchld_handler(int dummy);
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 @@ int main(int argc, char ** argv)
#endif
#if NON_INETD_MODE
main_noinetd(argc, argv);
main_noinetd(argc, argv, multipath);
/* notreached */
#endif
@ -121,7 +125,7 @@ static void main_inetd() {
#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 @@ static void main_noinetd(int argc, char ** argv) {
}
#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 @@ static void main_noinetd(int argc, char ** argv) {
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));

View File

@ -19,7 +19,8 @@ def dropbear(request):
yield None
return
args = [opt.dropbear,
# split so that "dropbearmulti dropbear" works
args = opt.dropbear.split() + [
"-p", LOCALADDR, # bind locally only
"-r", opt.hostkey,
"-p", opt.port,
@ -43,9 +44,10 @@ def dropbear(request):
def dbclient(request, *args, **kwargs):
opt = request.config.option
host = opt.remote or LOCALADDR
base_args = [opt.dbclient, "-y", host, "-p", opt.port]
# split so that "dropbearmulti dbclient" works
base_args = opt.dbclient.split() + ["-y", host, "-p", opt.port]
if opt.user:
full_args.extend(['-l', opt.user])
base_args.extend(['-l', opt.user])
full_args = base_args + list(args)
bg = kwargs.get("background")
if "background" in kwargs: