Created attachment 8316 [details] Busybox .config file Hello, I'm using busybox as provided by the Openwrt project, version 1.31.1. The .config is attached. Busybox is compiled using "musl". In my installation (openwrt), it seems the option "-e" is not parsed correctly: /tmp/rootfs/mnt # busybox nc 192.168.183.1 12345 -e ./foo.sh BusyBox v1.31.1 () multi-call binary. Usage: nc [-iN] [-wN] [-l] [-p PORT] [-f FILE|IPADDR PORT] [-e PROG] […] /tmp/rootfs/mnt # busybox nc -e nc: option requires an argument: e BusyBox v1.31.1 () multi-call binary. […] When busybox is compiled using "glibc", it works (unless POSIXLY_CORRECT is set, then it fails in the same way). People on the Openwrt IRC channel (that basically investigated this bug) argue that it has to do with the "while (optind < argc)" part: if you put "-e" before the IPADDR PORT, nc considers IPADDR PORT as parameters of the program. If you put -e after the IPADDR PORT, then getopt returns EOF when seeing IPADDR PORT and the code handling the "-e" option isn't hit. They also mention how musl getopt is different from the getopt from glibc (regarding reshuffling argv) and it's related. Rémy
Hello, being one of the guys in the #openwrt channel who debugged the problem I want to make the report a bit clearer by adding some details: The overall context is (I'm on 1.30.1, but I hope this doesn't matter; a bit simplified): while ((opt = getopt(argc, argv, ...) > 0) { ... if (... opt == 'e' && optind <= argc) { ... while (optind < argc) { ... optind++ } ... } ... } ... argc -= optind; if (!argc || argc > 2) bb_show_usage(); This depends on getopt() reordering argv, which musl doesn't do. On the following commandline: busybox nc 127.0.0.1 80 -e /bin/sh musl's getopt stops processing (i.e. return EOF) on the first argument to nc (i.e. "127.0.0.1") and then bails out because argc is too big. Doing busybox nc -e /bin/sh 127.0.0.1 80 doesn't work either because the inner while loop eats all further parameters. (traditional nc behaves differently here, it only eats exactly one parameter.) This can be easily reproduced with glibc by setting the env var POSIXLY_CORRECT to 1 (here: Debian with busybox v1.30.1): $ POSIXLY_CORRECT=1 busybox nc 127.0.0.1 80 -e /bin/sh BusyBox v1.30.1 (Debian 1:1.30.1-4) multi-call binary. Usage: nc [-iN] [-wN] [-l] [-p PORT] [-f FILE|IPADDR PORT] [-e PROG] Open a pipe to IP:PORT or FILE -l Listen mode, for inbound connects (use -ll with -e for persistent server) -p PORT Local port -w SEC Connect timeout -i SEC Delay interval for lines sent -f FILE Use file (ala /dev/ttyS0) instead of network -e PROG Run PROG after connect uwe@taurus:~$ busybox nc 127.0.0.1 80 -e /bin/sh nc: can't connect to remote host (127.0.0.1): Connection refused Possible options are: - also only use a single argument for -e - implement -c which passes its single argument to sh -c and so gives all flexibility that -e doesn't have with only a single argument. Best regards Uwe