Following up Bryan Henderson's idea of invisible mounts and my
conviction that you don't need per-process selection for visibility,
here's a proof of concept patch.

It adds a new mount flag MNT_NOOTHER/MS_NOOTHER.  If this flag is set,
then the mount is only visible to it's "owner".

The owner is set to current->fsuid at mount time (hack).

I tested it with a primitive mount utility (included at the end), and
everything seems to work as expected.

If something like this is acceptable, it would be a perfect
replacement for the current permission based mount hiding in FUSE.

Comments?

Thanks,
Miklos

 fs/namespace.c        |   21 +++++++++++++++++++--
 include/linux/fs.h    |    1 +
 include/linux/mount.h |    2 ++
 3 files changed, 22 insertions(+), 2 deletions(-)

diff -rup orig/linux-2.6.11/fs/namespace.c linux-2.6.11/fs/namespace.c
--- orig/linux-2.6.11/fs/namespace.c    2005-03-04 14:59:24.000000000 +0100
+++ linux-2.6.11/fs/namespace.c 2005-04-21 15:26:03.000000000 +0200
@@ -81,6 +81,15 @@ void free_vfsmnt(struct vfsmount *mnt)
 }
 
 /*
+ * Check if this mount should be skipped or not
+ */
+static inline int mnt_visible(struct vfsmount *mnt)
+{
+       return !(mnt->mnt_flags & MNT_NOOTHER) ||
+               mnt->mnt_uid == current->fsuid;
+}
+
+/*
  * Now, lookup_mnt increments the ref count before returning
  * the vfsmount struct.
  */
@@ -97,7 +106,8 @@ struct vfsmount *lookup_mnt(struct vfsmo
                if (tmp == head)
                        break;
                p = list_entry(tmp, struct vfsmount, mnt_hash);
-               if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry) {
+               if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry &&
+                   mnt_visible(p)) {
                        found = mntget(p);
                        break;
                }
@@ -234,6 +244,7 @@ static int show_vfsmnt(struct seq_file *
                { MNT_NOSUID, ",nosuid" },
                { MNT_NODEV, ",nodev" },
                { MNT_NOEXEC, ",noexec" },
+               { MNT_NOOTHER, ",noother" },
                { 0, NULL }
        };
        struct proc_fs_info *fs_infop;
@@ -252,6 +263,8 @@ static int show_vfsmnt(struct seq_file *
                if (mnt->mnt_flags & fs_infop->flag)
                        seq_puts(m, fs_infop->str);
        }
+       if (mnt->mnt_flags & MNT_NOOTHER)
+               seq_printf(m, ",mnt_uid=%u", mnt->mnt_uid);
        if (mnt->mnt_sb->s_op->show_options)
                err = mnt->mnt_sb->s_op->show_options(m, mnt);
        seq_puts(m, " 0 0\n");
@@ -807,6 +820,8 @@ int do_add_mount(struct vfsmount *newmnt
                goto unlock;
 
        newmnt->mnt_flags = mnt_flags;
+       if (mnt_flags & MNT_NOOTHER)
+               newmnt->mnt_uid = current->fsuid;
        err = graft_tree(newmnt, nd);
 
        if (err == 0 && fslist) {
@@ -1033,7 +1048,9 @@ long do_mount(char * dev_name, char * di
                mnt_flags |= MNT_NODEV;
        if (flags & MS_NOEXEC)
                mnt_flags |= MNT_NOEXEC;
-       flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_ACTIVE);
+       if (flags & MS_NOOTHER)
+               mnt_flags |= MNT_NOOTHER;
+       flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_NOOTHER|MS_ACTIVE);
 
        /* ... and get the mountpoint */
        retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd);
diff -rup orig/linux-2.6.11/include/linux/fs.h linux-2.6.11/include/linux/fs.h
--- orig/linux-2.6.11/include/linux/fs.h        2005-03-04 14:59:29.000000000 
+0100
+++ linux-2.6.11/include/linux/fs.h     2005-04-21 13:32:41.000000000 +0200
@@ -96,6 +96,7 @@ extern int dir_notify_enable;
 #define MS_REMOUNT     32      /* Alter flags of a mounted FS */
 #define MS_MANDLOCK    64      /* Allow mandatory locks on an FS */
 #define MS_DIRSYNC     128     /* Directory modifications are synchronous */
+#define MS_NOOTHER     256
 #define MS_NOATIME     1024    /* Do not update access times. */
 #define MS_NODIRATIME  2048    /* Do not update directory access times */
 #define MS_BIND                4096
diff -rup orig/linux-2.6.11/include/linux/mount.h 
linux-2.6.11/include/linux/mount.h
--- orig/linux-2.6.11/include/linux/mount.h     2004-12-24 22:33:51.000000000 
+0100
+++ linux-2.6.11/include/linux/mount.h  2005-04-21 12:50:42.000000000 +0200
@@ -19,6 +19,7 @@
 #define MNT_NOSUID     1
 #define MNT_NODEV      2
 #define MNT_NOEXEC     4
+#define MNT_NOOTHER    8
 
 struct vfsmount
 {
@@ -31,6 +32,7 @@ struct vfsmount
        struct list_head mnt_child;     /* and going through their mnt_child */
        atomic_t mnt_count;
        int mnt_flags;
+       uid_t mnt_uid;
        int mnt_expiry_mark;            /* true if marked for expiry */
        char *mnt_devname;              /* Name of device e.g. /dev/dsk/hda1 */
        struct list_head mnt_list;

===File ~/cc/mounttest.c====================================
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mount.h>
#include <sys/fsuid.h>

int main(int argc, char *argv[])
{
    if(argc != 6) {
        fprintf(stderr, "usage: %s dev dir type flags opts\n", argv[0]);
        return 1;
    }
    setfsuid(getuid());
    if(mount(argv[1], argv[2], argv[3], atoi(argv[4]), argv[5]) == -1) {
        perror("mount");
        return 1;
    }
    return 0;
}
============================================================
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to