Exposing /proc
and /dev
exposes some more information and grants more rights to the users inside the jail.
Beware that uids and gids may be different inside and outside the jail. For instance, inside the jail, user "x" may be member of group 123, which in the jail is for "users" while on the system is for "disk". By bind-mounting /dev
, you would grant them access to raw disk devices which would allow them virtually root access and get out of the jail.
I would not bind-mount /dev. Only create a few devices in there that the java application may need (null
, tty
, zero
...) with the proper ownership and rights.
Have you considered linux containers instead of chroot jails which would isolate them more (lxcs are just a step further to chroot jails).
You can bind-mount directories into your chroot root with:
mount -o bind /x/y /chroot/x/y
(see man mount
, section "The bind mounts"). Any access to /chroot/x/y
from now on acts exactly like an access to /x/y
: same file listings, same contents, same inodes.
Note, however, that this puts the entire directory in as-is: a process inside the chroot that can write to the directory will be able to write to the "real" directory outside. If you want to make the mount inside the chroot read-only you need to remount explicitly read-only after the bind:
mount -o remount,ro /chroot/x/y
The original /x/y will remain read-write, but the copy will now be read-only.
To prefer internal copies of files, or to allow writing in some existing files or directories without affecting the originals, you can use a union file system. These let you overlay multiple directory trees on one another, specifying where writes go to and the order that reads are resolved. Common union filesystems for Linux include aufs, Unionfs, and unionfs-fuse. The first two of those are kernel modules, while the last uses FUSE to run a filesystem in user space. The kernel modules are generally faster, but the FUSE version may be easier to set up, although you may want to avoid using external user-space tools from your chroot anyway. You can prepare the union filesystems you want and then chroot into them.
In each case the basic approach is the same, something like:
unionfs-fuse -o cow /jail/bin:/other/bin:/bin /chroot/bin
This creates a union mount in /chroot/bin
which gives the files from /jail/bin
priority if they exist, then try /other/bin/
, and otherwise shows the files from /bin
. -o cow
makes it copy-on-write: attempts to write to, say, /chroot/bin/foo
will copy /bin/foo
to /jail/bin/foo
and save the modifications there. If you don't want that behaviour, leave the option out. The other filesystems have slightly different configurations, but the principle is the same.
Whichever way you set it up, you could then:
chroot /chroot
and have everything work the way you wanted.
Best Answer
The explanation lies in the
mount.fuse
man page:With the
nodev
option, the kernel bans all access to devices in the mounted filesystem. With thenosuid
option, the kernel ignores setuid and setgid attributes. Both options are necessary for security when a filesystem is mounted by a non-root user: otherwise the mounting user could create a setuid root shell or devices letting him access all disks bypassing the filesystem.You'll also want the
allow_other
option if non-root users are to access that filesystem.If you want to restrict which devices are visible in the chroot, then a union mount isn't the way to do that. Instead, leave
dev
off and mount a separate filesystem containing your desired minimal/dev
. You can make that a tmpfs:Instead of a tmpfs, you could bind-mount a directory containing your devices ready to go. You'll need to bind-mount
/dev/pts
to get pseudoterminals in the chroot.