Andriy Gapon
2016-05-15 13:37:05 UTC
I am curious about the purpose of mountcheckdirs() called when mounting and
unmounting a filesystem.
The function is described as such:
/*
* Scan all active processes and prisons to see if any of them have a current
* or root directory of `olddp'. If so, replace them with the new mount point.
*/
and it seems to be used to "lift" processes and jails to a root of a new
filesystem when it is mounted and to "lower" them onto a covered vnode (if any)
when a filesystem is unmounted.
What's the purpose of those actions?
It's strange that the machinations are done at all, but it is stranger that they
are applied only to processes and jails at exactly a covered vnode and a root
vnode. Anything below in a filesystem's tree is left alone. Is there anything
so very special about being at exactly those points?
IMO, the machinations can have unexpected security consequences.
A little bit of history.
mountcheckdirs() was first added in r22521 (circa 1997) as checkdirs with a
rather non-specific commit message. Initially it was used only when a
filesystem was mounted.
Then, in r73241 (circa 2002) the function was added to dounmount():
The checkdirs() function is called at mount time to find any process
fd_cdir or fd_rdir pointers referencing the covered mountpoint
vnode. It transfers these to point at the root of the new filesystem.
However, this process was not reversed at unmount time, so processes
with a cwd/root at a mount point would unexpectedly lose their
cwd/root following a mount-unmount cycle at that mountpoint.
...
Dounmount() now undoes the actions
taken by checkdirs() at mount time; any process cdir/rdir pointers
that reference the root vnode of the unmounted filesystem are
transferred to the now-uncovered vnode.
unmounting a filesystem.
The function is described as such:
/*
* Scan all active processes and prisons to see if any of them have a current
* or root directory of `olddp'. If so, replace them with the new mount point.
*/
and it seems to be used to "lift" processes and jails to a root of a new
filesystem when it is mounted and to "lower" them onto a covered vnode (if any)
when a filesystem is unmounted.
What's the purpose of those actions?
It's strange that the machinations are done at all, but it is stranger that they
are applied only to processes and jails at exactly a covered vnode and a root
vnode. Anything below in a filesystem's tree is left alone. Is there anything
so very special about being at exactly those points?
IMO, the machinations can have unexpected security consequences.
A little bit of history.
mountcheckdirs() was first added in r22521 (circa 1997) as checkdirs with a
rather non-specific commit message. Initially it was used only when a
filesystem was mounted.
Then, in r73241 (circa 2002) the function was added to dounmount():
The checkdirs() function is called at mount time to find any process
fd_cdir or fd_rdir pointers referencing the covered mountpoint
vnode. It transfers these to point at the root of the new filesystem.
However, this process was not reversed at unmount time, so processes
with a cwd/root at a mount point would unexpectedly lose their
cwd/root following a mount-unmount cycle at that mountpoint.
...
Dounmount() now undoes the actions
taken by checkdirs() at mount time; any process cdir/rdir pointers
that reference the root vnode of the unmounted filesystem are
transferred to the now-uncovered vnode.
--
Andriy Gapon
Andriy Gapon