I need to (temporarily) jail a non-privileged user.

I tried something like:

sudo chroot --userspec=mcon:users /wherever/chroottarget /bin/bash -i

This almost works, but it doesn't set env vars (while "sudo" does!), so I get the error:

bash: /root/.bashrc: Permission denied

How can I solve the problem? (NOTE: the above command should be inside a bash script)

UPDATE: I found a (rather convolute) way to do what I need:

sudo bash -c "HOME=<jailed home> chroot --userspec=<user>:<group> <chroottarget> /bin/bash -i"

Ideally I should read HOME from jailed /etc/passwd, along with all other environment (take them from jailed /etc/profile), this "solution" will keep intact all variables in the caller environment.

Is there a better way?

2 Answers 2


How about by calling chroot() and setuid() syscalls via a C program?

A simple C program example:

Pre-requisite for executing this simple C program (feel free to add steps for copying /etc/profile, /etc/passwd and/or whatever else you need to setup your environment, into /tmp):

You've copied over /bin/*, /usr/bin/*, /lib* into /tmp already.

For example, using the following set of commands:

~$ sudo cp -rH /bin/ /tmp/

~$ mkdir /tmp/usr/

~$ sudo cp -rH /usr/bin/ /tmp/usr/

~$ sudo cp -rH /lib* /tmp/

 * \file chrooted_user_is_non_root.c
 * DISCLAIMER: Notice how I do not check return values/perform any error
 * checks. This code snippet is for illustration purposes only and not
 * meant to be used in production.
 * Inspired by:
 * https://stackoverflow.com/a/3946135/4726668

#include <unistd.h>
#include <stdlib.h>

int main (void)
  chdir ("/tmp");
  chroot ("/tmp");
  setuid (1000); // Set to a non-privileged user id.
  system ("ls -id /"); // If inode number of / is not 2, then you are *most likely* inside chroot.
  system ("id"); // If this prints non-zero uid, then you are not root.
  return 0;

Notice the difference in output when you run this program with and without sudo:

~$ gcc chrooted_user_is_non_root.c -o chrooted_user_is_non_root.elf
~$ sudo ./chrooted_user_is_non_root.elf
2883585 /
uid=1000 gid=0 groups=0
~$ ./chrooted_user_is_non_root.elf
2 /
uid=1000(user_foo) gid=1000(user_foo) groups=1000(user_foo),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),122(lpadmin),135(lxd),136(sambashare)

As mentioned in the code comment, the above code snippet was inpired by https://stackoverflow.com/a/3946135/4726668


You need to change the environment variable $HOME to match the user's.

export HOME=/home/user-name

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .