This patch causes /proc/mounts to only display entries for mountpoints
within the current process root. This makes df and friends behave more
nicely in a chroot jail or with rootfs.
Most of the logic in proc_check_root() is moved to a new function,
is_namespace_subdir(), which checks whether the given mount/dentry
refers to a subdirectory of the process root directory in the current
namespace. show_vfsmount() now returns without adding an output line if
is_namespace_subdir() returns false for a given mountpoint.
Paul
diff -Naur -X /mnt/elbrus/home/pmenage/dontdiff linux-2.5.24/fs/namespace.c linux-2.5.24-mounts/fs/namespace.c
--- linux-2.5.24/fs/namespace.c Wed Jun 26 01:07:20 2002
+++ linux-2.5.24-mounts/fs/namespace.c Wed Jun 26 01:17:42 2002
@@ -38,6 +38,36 @@
return tmp & hash_mask;
}
+/* Check whether the given mount/dentry is contained within our root */
+int is_namespace_subdir(struct vfsmount *vfsmnt, struct dentry *dentry) {
+
+ struct vfsmount *our_vfsmnt;
+ struct dentry *our_root;
+ int res = 0;
+
+ spin_lock(&dcache_lock); /* also protects access to current->fs */
+
+ our_vfsmnt = current->fs->rootmnt;
+ our_root = current->fs->root;
+
+ while(vfsmnt != our_vfsmnt) {
+ if(vfsmnt == vfsmnt->mnt_parent)
+ goto out;
+ dentry = vfsmnt->mnt_mountpoint;
+ vfsmnt = vfsmnt->mnt_parent;
+ }
+
+ if(!is_subdir(dentry, our_root))
+ goto out;
+
+ res = 1;
+ out:
+ spin_unlock(&dcache_lock);
+ return res;
+}
+
+
+
struct vfsmount *alloc_vfsmnt(char *name)
{
struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL);
@@ -212,6 +242,9 @@
struct proc_fs_info *fs_infop;
char *path_buf, *path;
+ if(!is_namespace_subdir(mnt, mnt->mnt_root))
+ return 0;
+
path_buf = (char *) __get_free_page(GFP_KERNEL);
if (!path_buf)
return -ENOMEM;
diff -Naur -X /mnt/elbrus/home/pmenage/dontdiff linux-2.5.24/fs/proc/base.c linux-2.5.24-mounts/fs/proc/base.c
--- linux-2.5.24/fs/proc/base.c Tue Jun 18 19:11:46 2002
+++ linux-2.5.24-mounts/fs/proc/base.c Wed Jun 26 01:19:01 2002
@@ -265,42 +265,19 @@
static int proc_check_root(struct inode *inode)
{
- struct dentry *de, *base, *root;
- struct vfsmount *our_vfsmnt, *vfsmnt, *mnt;
+ struct dentry *root;
+ struct vfsmount *mnt;
int res = 0;
if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */
return -ENOENT;
- read_lock(¤t->fs->lock);
- our_vfsmnt = mntget(current->fs->rootmnt);
- base = dget(current->fs->root);
- read_unlock(¤t->fs->lock);
- spin_lock(&dcache_lock);
- de = root;
- mnt = vfsmnt;
+ if(!is_namespace_subdir(mnt, root))
+ res = -EACCES;
- while (vfsmnt != our_vfsmnt) {
- if (vfsmnt == vfsmnt->mnt_parent)
- goto out;
- de = vfsmnt->mnt_mountpoint;
- vfsmnt = vfsmnt->mnt_parent;
- }
-
- if (!is_subdir(de, base))
- goto out;
- spin_unlock(&dcache_lock);
-
-exit:
- dput(base);
- mntput(our_vfsmnt);
dput(root);
mntput(mnt);
return res;
-out:
- spin_unlock(&dcache_lock);
- res = -EACCES;
- goto exit;
}
static int proc_permission(struct inode *inode, int mask)
diff -Naur -X /mnt/elbrus/home/pmenage/dontdiff linux-2.5.24/include/linux/namespace.h linux-2.5.24-mounts/include/linux/namespace.h
--- linux-2.5.24/include/linux/namespace.h Tue Jun 18 19:11:55 2002
+++ linux-2.5.24-mounts/include/linux/namespace.h Tue Jun 25 19:35:25 2002
@@ -43,5 +43,6 @@
atomic_inc(&namespace->count);
}
+extern int is_namespace_subdir(struct vfsmount *, struct dentry *);
#endif
#endif
On Tue, 2 Jul 2002, Paul Menage wrote:
>
> This patch causes /proc/mounts to only display entries for mountpoints
> within the current process root. This makes df and friends behave more
> nicely in a chroot jail or with rootfs.
>
> Most of the logic in proc_check_root() is moved to a new function,
> is_namespace_subdir(), which checks whether the given mount/dentry
> refers to a subdirectory of the process root directory in the current
> namespace. show_vfsmount() now returns without adding an output line if
> is_namespace_subdir() returns false for a given mountpoint.
That looks nice, but keep in mind that behaviour of getmntent(3) in chroot
jails is a traditional misfeature. Hopefully nothing important relies on it,
but...
As far as I'm concerned patch (and behaviour change) are fine. Let's do it
and see if anybody screams...
On Tue, Jul 02, 2002 at 01:37:22PM -0700, Paul Menage wrote:
>
> This patch causes /proc/mounts to only display entries for mountpoints
> within the current process root. This makes df and friends behave more
> nicely in a chroot jail or with rootfs.
nice feature, also helps chrooted installation work much smoother.
Richard
On Tue, Jul 02, 2002 at 01:37:22PM -0700, Paul Menage wrote:
| This patch causes /proc/mounts to only display entries for mountpoints
| within the current process root. This makes df and friends behave more
| nicely in a chroot jail or with rootfs.
|
| Most of the logic in proc_check_root() is moved to a new function,
| is_namespace_subdir(), which checks whether the given mount/dentry
| refers to a subdirectory of the process root directory in the current
| namespace. show_vfsmount() now returns without adding an output line if
| is_namespace_subdir() returns false for a given mountpoint.
Has anyone managed to back-port this patch to 2.4.18 or 2.4.19?
I've run into an inconsistency that I can't figure out. The variable
"vfsmnt" turns up undefined. Normally I'd think that would be due to
it being added in the new base code. But in this case the patch is
deleting it. OK, so that could be because the older code has another
reference to it that the newer code doesn't have, so the patch didn't
account for that. But in this case, there's more to it than that.
In this part of the patch:
| diff -Naur -X /mnt/elbrus/home/pmenage/dontdiff linux-2.5.24/fs/proc/base.c linux-2.5.24-mounts/fs/proc/base.c
| --- linux-2.5.24/fs/proc/base.c Tue Jun 18 19:11:46 2002
| +++ linux-2.5.24-mounts/fs/proc/base.c Wed Jun 26 01:19:01 2002
| @@ -265,42 +265,19 @@
|
| static int proc_check_root(struct inode *inode)
| {
| - struct dentry *de, *base, *root;
| - struct vfsmount *our_vfsmnt, *vfsmnt, *mnt;
| + struct dentry *root;
| + struct vfsmount *mnt;
The above deletes the definition of "vfsmnt". Then 3 lines down from
here, there is code used for context which has "vfsmnt" in used. So
if this patch applies, it would be causing "vfsmnt" to be undefined
and also expecting it to be used. If all uses of "vfsmnt" are moved
to another file, I would think the line below, which references the
address of it in the call to proc_root_link() would also be moved.
Anyone know what's going on with this?
| int res = 0;
|
| if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */
| return -ENOENT;
| - read_lock(¤t->fs->lock);
| - our_vfsmnt = mntget(current->fs->rootmnt);
| - base = dget(current->fs->root);
| - read_unlock(¤t->fs->lock);
|
| - spin_lock(&dcache_lock);
| - de = root;
| - mnt = vfsmnt;
| + if(!is_namespace_subdir(mnt, root))
| + res = -EACCES;
|
| - while (vfsmnt != our_vfsmnt) {
| - if (vfsmnt == vfsmnt->mnt_parent)
| - goto out;
| - de = vfsmnt->mnt_mountpoint;
| - vfsmnt = vfsmnt->mnt_parent;
| - }
| -
| - if (!is_subdir(de, base))
| - goto out;
| - spin_unlock(&dcache_lock);
| -
| -exit:
| - dput(base);
| - mntput(our_vfsmnt);
| dput(root);
| mntput(mnt);
| return res;
| -out:
| - spin_unlock(&dcache_lock);
| - res = -EACCES;
| - goto exit;
| }
|
| static int proc_permission(struct inode *inode, int mask)
[remainder of patch snipped]
--
-----------------------------------------------------------------
| Phil Howard - KA9WGN | Dallas | http://linuxhomepage.com/ |
| [email protected] | Texas, USA | http://phil.ipal.org/ |
-----------------------------------------------------------------