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