28

I was reading the famous Unix Recovery Legend, and it occurred to me to wonder:

If I had a BusyBox shell open, and the BusyBox binary were itself deleted, would I still be able to use all the commands included in the BusyBox binary?

Clearly I wouldn't be able to use the BB version of those commands from another running shell such as bash, since the BusyBox file itself would be unavailable for bash to open and run. But from within the running instance of BusyBox, it appears to me there could be two methods by which BB would run a command:

  1. It could fork and exec a new instance of BusyBox, calling it using the appropriate name—and reading the BusyBox file from disk to do so.
  2. It could fork and perform some internal logic to run the specified command (for example, by running it as a function call).

If (1) is the way BusyBox works, I would expect that certain BusyBox-provided commands would become unavailable from within a running instance of BB after the BB binary were deleted.

If (2) is how it works, BusyBox could be used even for recovery of a system where BB itself had been deleted—provided there were still a running instance of BusyBox accessible.

Is this documented anywhere? If not, is there a way to safely test it?

  • 2
    is there a way to safely test it? Download the generic x86 openwrt image and attach the image to a new VirtualBox machine – basin Apr 4 '16 at 20:17
  • 2
    And this raises the question, how do Busybox commands continue to work after PATH is unset? Does it assume a default value of PATH? – muru Apr 5 '16 at 1:05
  • 2
    @muru: From the source code (at least for its ash clone) it looks like it treats an unset PATH the same as it would an empty string, so it searches the current directory, and only that. – Henning Makholm Apr 5 '16 at 15:57
  • @HenningMakholm Well, my comment was answered by Gilles' answer. However, it's good to know that - I'd expected only builtins to work. – muru Apr 5 '16 at 16:40
33

By default, BusyBox doesn't do anything special regarding the applets that it has built in (the commands listed with busybox --help).

However, if the FEATURE_SH_STANDALONE and FEATURE_PREFER_APPLETS options are enabled at compile time, then when BusyBox sh¹ executes a command which is a known applet name, it doesn't do the normal PATH lookup, but instead runs its built-in applets through a shortcut:

  • Applets that are declared as “noexec” in the source code are executed as function calls in a forked process. As of BusyBox 1.22, the following applets are noexec: chgrp, chmod, chown, cksum, cp, cut, dd, dos2unix, env, fold, hd, head, hexdump, ln, ls, md5sum, mkfifo, mknod, sha1sum, sha256sum, sha3sum, sha512sum, sort, tac, unix2dos.
  • Applets that are declared as “nofork” in the source code are executed as function calls in the same process. As of BusyBox 1.22, the following applets are nofork: [[, [, basename, cat, dirname, echo, false, fsync, length, logname, mkdir, printenv, printf, pwd, rm, rmdir, seq, sync, test, true, usleep, whoami, yes.
  • Other applets are really executed (with fork and execve), but instead of doing a PATH lookup, BusyBox executes /proc/self/exe, if available (which is normally the case on Linux), and a path defined at compile time otherwise.

This is documented in a bit more detail in docs/nofork_noexec.txt. The applet declarations are in include/applets.src.h in the source code.

Most default configurations turn these features off, so that BusyBox executes external commands like any other shell. Debian turns these features on in both its busybox and busybox-static packages.

So if you have a BusyBox executable compiled with FEATURE_SH_STANDALONE and FEATURE_PREFER_APPLETS, then you can execute all BusyBox commands from a BusyBox shell even if the executable is deleted (except for the applets that are not listed above, if /proc/self/exe is not available).

¹ There are actually two implementations of "sh" in BusyBox — ash and hush — but they behave the same way in this respect.

  • 1
    @Wildcard FEATURE_PREFER_APPLETS and FEATURE_SH_STANDALONE are compile-time flags, enabling or disabling features. The applets are marked nofork and noexec irrespective of which flags were used. Whether or not such markings have any effect depends on FEATURE_PREFER_APPLETS being enabled. Hence, three possible behaviours: 1. FEATURE_PREFER_APPLETS disabled, 2. FEATURE_PREFER_APPLETS enabled and applet is nofork, 3. FEATURE_PREFER_APPLETS enabled and applet is noexec. The third para in the docs explain it nicely. And the last section shows the possible cases. – muru Apr 5 '16 at 2:04
  • 1
    @Wildcard FEATURE_SH_STANDALONE (which requires FEATURE_PREFER_APPLETS). nofork isn't needed. With FEATURE_SH_STANDALONE, /proc/self/exe is used where applicable, so it will work even if BB was deleted. You can test this out with fairly minimal risk on any Debian or Arch Linux systm, run busybox ash, unset PATH, do basin's commands. It works fine. – muru Apr 5 '16 at 2:38
  • 3
    On an Ubuntu 14.04.1 LTS system, Busybox is configured to prefer applets. Since neither cat nor chmod require exec-ing a pathname, you can recover the executable thusly: cat /proc/self/exe > busybox; chmod 755 busybox. – Barefoot IO Apr 5 '16 at 2:40
  • 1
    @forest There's a huge difference: tac requires either a seekable input file which is not always available, or reading the entire input into memory. cat can read its input from start to finish, discarding what it's already processed. It's much easier to implement and it's also much more commonly used, so it makes more sense to optimise that one. – hvd Apr 5 '16 at 7:24
  • 1
    @Wildcard Nofork and noexec are indications set on each applet. FEATURE_xxx is a compile-time option for BusyBox as a whole. The nofork and noexec indications only matter if FEATURE_PREFER_APPLETS is active (at least for the purpose of executing a command in the shell, they're also used in some other contexts). – Gilles 'SO- stop being evil' Apr 5 '16 at 10:01
8

is there a way to safely test it? With the generic x86 openwrt image:

vbox screenshot

Most commands are not built-in, but some are, like echo and printf. A binary file with arbitrary contents can be created using printf, but chmod +x will be a problem.

  • Interesting; are you running that from within BusyBox itself, or some other shell? – Wildcard Apr 4 '16 at 21:23
  • 4
    (Also, would you mind pasting in the text rather than a screenshot?) – Wildcard Apr 4 '16 at 21:23
  • @Wildcard /bin/ash -> busybox . – basin Apr 4 '16 at 21:29
  • 1
    As in Gilles' answer, if FEATURE_SH_STANDALONE is enabled, you won't get this behaviour. The second mv will work perfectly fine. – muru Apr 5 '16 at 2:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.