Running a command with a different root folder (Linux)
Tags: docker, bash, linux
Published: 2022-07-17 21:00:20

You can run a command with a different root folder with the `chroot` command. Let's try it out.

## Listing dependencies

First, let's get the library dependencies of `sh`, `echo`, `cat`, and `pwd`:

```
$ ldd /bin/sh /bin/echo /bin/cat /bin/pwd
/bin/sh:
        linux-vdso.so.1 (0x00007ffd8b764000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f415d09f000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f415d2d4000)
/bin/echo:
        linux-vdso.so.1 (0x00007ffd04383000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3120c73000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3120e90000)
/bin/cat:
        linux-vdso.so.1 (0x00007fffe1d7a000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcf49a42000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fcf49c60000)
/bin/pwd:
        linux-vdso.so.1 (0x00007fffdbfad000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f60ec35c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f60ec57a000)
```

[(more about `ldd` here)](https://dev.to/tallesl/find-library-dependencies-of-a-binary-file-linux-3njf)

## Creating a new custom root

Now let's create a barebones root filesystem for those commands to work, with their respective libraries:

```
$ mkdir customroot/
$ mkdir customroot/bin/ customroot/lib/ customroot/lib64/

$ cp /bin/sh /bin/echo /bin/cat /bin/pwd customroot/bin/

$ cp /lib/x86_64-linux-gnu/libc.so.6 customroot/lib/
$ cp /lib64/ld-linux-x86-64.so.2 customroot/lib64/
```

## Running a new shell on with the custom root

Now running our shell with `customroot` folder as the root:

```
$ sudo chroot customroot/ sh

# echo "Hello World!" > hello.txt
# cat hello.txt
Hello World!

# pwd
/

# ls
sh: 4: ls: not found

# exit
```

Notice `pwd` outputting `/` as expected, and `ls` not running since with didn't copy its binaries (and dependencies).

## Creating a custom Debian root

Copying each binary file and it's dependencies as done above is cumbersome. What if we could generate a complete base root filesystem in an easier way? `debootstrap` to the rescue!


```
$ sudo apt install debootstrap
$ sudo debootstrap bionic customdebroot
```

Now let's run a new shell with our new root:

```
$ sudo chroot customdebroot/ bash

# pwd
/

# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
```

Let's install some package:

```
# apt install dict

# which dict
/usr/bin/dict

# dict nintendo
1 definition found

From The Free On-line Dictionary of Computing (30 December 2018) [foldoc]:

  Nintendo
  
     <company, games> A Japanese {video game} hardware manufacturer
     and software publisher.  Nintendo started by making playing
     cards, but was later dominant in video games throughout the
     1980s and early 1990s worldwide.  They make lots of games
     consoles including the Gameboy, Gameboy Advance SP, DS, DS
     Lite and the Wii.
  
     {Nintendo home (http://nintendo.com/)}.
  
     (2008-03-08)
```

Back to our original shell with the 'real' root:

```
# exit

$ file customdebroot/usr/bin/dict
customdebroot/usr/bin/dict: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=1ae2d6542c13f51dcaaf6510a18e1b4bf49cf7c8, stripped
```

`dict` was only installed on our custom Debian root as expected.