When chroot()
started to confine processes inside the new root
Writing about the somewhat surprising history of chroot()
did leave me with one question: when did chroot()
start to confine processes inside the new root directory hierarchy?
This is an interesting moment because it marks the point where
chroot()
stops being a little hack to help emulation and instead
turns into a security feature.
(The first use of chroot()
as a security feature seems to be in
the 4.2BSD ftpd
, as covered in the first entry.
I can't be completely sure of this because I can't find an easily
searchable version of the tuhs.org 4.1c
BSD tree.)
Early versions of chroot()
appear to be trivially escapable by
things like 'cd /; cd ..
', which puts you in the parent of the
nominal root directory. A version of the chroot()
system call
that did not allow this appears in 4.1c BSD; you can see the code
in namei()
.
Unlike the 4BSD version of the same code,
this code specifically checks to see if you are trying to look up
'..
' at the chroot root directory, and remaps the result if you
are.
I don't know for sure why this change appeared in 4.1c BSD, but
it's possible to speculate. The 4BSD namei()
is essentially the
same as the V7 namei()
, but the 4.1c BSD namei()
is significantly
changed in several ways (for example, it has a lot more comments).
4.1c BSD is the first appearance of two significant changes related
to namei()
; it's when BSD introduced both a rename()
system
call and the BSD FFS. It also seems
to have seen a significant reorganization of the kernel source code
away from its previous V7-like appearance. So I suspect that when
the BSD people were changing namei()
around anyways because of
other changes, they noticed and fixed the chroot escape. With the
chroot escape fixed, it was then used as a security feature in the
4.2BSD ftpd
.
(The history portion of the Wikipedia page on chroot
is no help, because
it's clearly wrong unless you creatively reinterpret what it's
saying. chroot()
was not 'added' to BSD at any point, because BSD
inherited it from V7 from the start. This bit of history appears
to come from the references section of FreeBSD's
Jails: Confining the omnipotent root (via) from 2000 and may refer either
to the addition of a chroot(2)
manpage or the namei()
changes.)
Sidebar: The peculiar history of chroot()
documentation
In V7, as I discovered, chroot()
is documented
in the chdir()
manpage. However, while 32V, 3BSD, and 4BSD all
still have the chroot()
system call, documentation for it has
disappeared from their chdir()
manpages. A chroot()
manpage
(re)appears only in 4.1c BSD.
The 32V chdir()
manpage seems to be the V7 manpage with the
chroot()
documentation removed (and it definitely isn't the V6
chdir()
manpage). It may be that the chroot()
stuff was removed
because the 32V people thought it was a hack that was better off
not being documented, or maybe 32V got their manpages from an earlier
version of V7 that didn't have the chroot()
addition.
|
|