The redirection isn't actually occurring inside chroot
. > /tmp/test
is handled by whatever shell you are using. If you actually passed > /tmp/test
to chroot
, then it would get passed to echo
and you'd see
this is a test > /tmp/test
on your terminal. You shell, of course, isn't getting chroot
ed, so it's perfectly fine with opening /tmp/test
. Then, the shell exec
s the chroot
executable, which calls the chroot
system call and then exec
s into echo
, which finally writes to the fd. All through this, the original file descriptor that your (unchroot
ed) shell opened is never modified, so your chroot
ed echo
is able to write to it.
This is a deliberate feature. A process outside the chroot
is allowed to open files, and then its chroot
ed children can only access those files outside the chroot
that the parent process deigned to pass to them.
If you want the redirection to take place inside the chroot, you need to spawn a shell that knows how to interpret it:
chroot $dir bash -c "echo this is a test > /tmp/test"
The order of operations is now: fork
(with default stdin, stdout, and stderr), exec
chroot
, chroot
(now inside chroot), exec
bash
(knows how to handle redirection), fork
(implementation detail of bash
), open file, exec
echo
(with new stdout).