[PATCH] do not mount the same filesystem on the same mount point

2000-09-10 Thread Andries Brouwer

Dear Linus, Al, all:

Below a patch to prevent mounting the same filesystem
repeatedly on the same mount point. This 4-line patch is

+   /* Refuse the same filesystem on the same mount point */
+   retval = -EBUSY;
+   if (nd.mnt && nd.mnt->mnt_sb == sb
+  && nd.mnt->mnt_root == nd.dentry)
+   goto fail;

(If the user really wants to, she can still do this.
This patch is not needed for correctness or security,
but just to prevent the confusion that would arise when
each GUI click mounted the same fs on the same mount point.)

This patch also changes "-t bind" into "--bind",
i.e., recognizes a bind mount by the MS_BIND flags bit
rather than the "bind" type. Mount(8) already supports this.

(I do not think it is necessary to leave the "-t bind"
version for backwards compatibility. It has only existed
since 2.3.99-pre6. For the moment it is #ifdef'ed out.)

Here there is a security aspect: I did not change the
fact that every user can do this, but worry a little
about the fact that she could do this a million times,
running the kernel out of memory. It seems to me that
either capabilities should be required, or the memory
used should be charged to the user.

I also discarded the 0xC0ED magic, making it impossible
to use a pre-0.97 version of mount(8) together with a
2.4 kernel, and freeing up 16 more flag bits, in case
we should need them.

The rest is layout polishing.

Andries

-
diff -u --recursive --new-file ../linux-2.4.0test8/linux/fs/super.c ./linux/fs/super.c
--- ../linux-2.4.0test8/linux/fs/super.cThu Aug 24 14:05:01 2000
+++ ./linux/fs/super.c  Sun Sep 10 20:37:56 2000
@@ -1303,20 +1303,21 @@
  * information (or be NULL).
  *
  * NOTE! As pre-0.97 versions of mount() didn't use this setup, the
- * flags have to have a special 16-bit magic number in the high word:
- * 0xC0ED. If this magic word isn't present, the flags and data info
- * aren't used, as the syscall assumes we are talking to an older
- * version that didn't understand them.
+ * flags used to have a special 16-bit magic number in the high word:
+ * 0xC0ED. If this magic number is present, the high word is discarded.
  */
 long do_mount(char * dev_name, char * dir_name, char *type_page,
- unsigned long new_flags, void *data_page)
+ unsigned long flags, void *data_page)
 {
struct file_system_type * fstype;
struct nameidata nd;
struct vfsmount *mnt = NULL;
struct super_block *sb;
int retval = 0;
-   unsigned long flags = 0;
+
+   /* Discard magic */
+   if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
+   flags &= ~MS_MGC_MSK;
  
/* Basic sanity checks */
 
@@ -1328,21 +1329,25 @@
/* OK, looks good, now let's see what do they want */
 
/* just change the flags? - capabilities are checked in do_remount() */
-   if ((new_flags & (MS_MGC_MSK|MS_REMOUNT)) == (MS_MGC_VAL|MS_REMOUNT))
-   return do_remount(dir_name, new_flags&~(MS_MGC_MSK|MS_REMOUNT),
-   (char *) data_page);
-
-   if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL)
-   flags = new_flags & ~MS_MGC_MSK;
+   if (flags & MS_REMOUNT)
+   return do_remount(dir_name, flags & ~MS_REMOUNT,
+ (char *) data_page);
+
+   /* "mount --bind"? Equivalent to older "mount -t bind" */
+   /* No capabilities? What if users do thousands of these? */
+   if (flags & MS_BIND)
+   return do_loopback(dev_name, dir_name);
 
/* For the rest we need the type */
 
if (!type_page || !memchr(type_page, 0, PAGE_SIZE))
return -EINVAL;
 
+#if 0  /* Can be deleted again. Introduced in patch-2.3.99-pre6 */
/* loopback mount? This is special - requires fewer capabilities */
if (strcmp(type_page, "bind")==0)
return do_loopback(dev_name, dir_name);
+#endif
 
/* for the rest we _really_ need capabilities... */
if (!capable(CAP_SYS_ADMIN))
@@ -1354,7 +1359,8 @@
return -ENODEV;
 
/* ... and mountpoint. Do the lookup first to force automounting. */
-   if (path_init(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_DIRECTORY, ))
+   if (path_init(dir_name,
+ LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_DIRECTORY, ))
retval = path_walk(dir_name, );
if (retval)
goto fs_out;
@@ -1363,7 +1369,7 @@
if (fstype->fs_flags & FS_NOMOUNT)
sb = ERR_PTR(-EINVAL);
else if (fstype->fs_flags & FS_REQUIRES_DEV)
-   sb = get_sb_bdev(fstype, dev_name,flags, data_page);
+   sb = get_sb_bdev(fstype, dev_name, flags, data_page);
else if (fstype->fs_flags & FS_SINGLE)
sb = get_sb_single(fstype, flags, data_page);
else
@@ -1376,6 +1382,13 @@
/* 

[PATCH] do not mount the same filesystem on the same mount point

2000-09-10 Thread Andries Brouwer

Dear Linus, Al, all:

Below a patch to prevent mounting the same filesystem
repeatedly on the same mount point. This 4-line patch is

+   /* Refuse the same filesystem on the same mount point */
+   retval = -EBUSY;
+   if (nd.mnt  nd.mnt-mnt_sb == sb
+   nd.mnt-mnt_root == nd.dentry)
+   goto fail;

(If the user really wants to, she can still do this.
This patch is not needed for correctness or security,
but just to prevent the confusion that would arise when
each GUI click mounted the same fs on the same mount point.)

This patch also changes "-t bind" into "--bind",
i.e., recognizes a bind mount by the MS_BIND flags bit
rather than the "bind" type. Mount(8) already supports this.

(I do not think it is necessary to leave the "-t bind"
version for backwards compatibility. It has only existed
since 2.3.99-pre6. For the moment it is #ifdef'ed out.)

Here there is a security aspect: I did not change the
fact that every user can do this, but worry a little
about the fact that she could do this a million times,
running the kernel out of memory. It seems to me that
either capabilities should be required, or the memory
used should be charged to the user.

I also discarded the 0xC0ED magic, making it impossible
to use a pre-0.97 version of mount(8) together with a
2.4 kernel, and freeing up 16 more flag bits, in case
we should need them.

The rest is layout polishing.

Andries

-
diff -u --recursive --new-file ../linux-2.4.0test8/linux/fs/super.c ./linux/fs/super.c
--- ../linux-2.4.0test8/linux/fs/super.cThu Aug 24 14:05:01 2000
+++ ./linux/fs/super.c  Sun Sep 10 20:37:56 2000
@@ -1303,20 +1303,21 @@
  * information (or be NULL).
  *
  * NOTE! As pre-0.97 versions of mount() didn't use this setup, the
- * flags have to have a special 16-bit magic number in the high word:
- * 0xC0ED. If this magic word isn't present, the flags and data info
- * aren't used, as the syscall assumes we are talking to an older
- * version that didn't understand them.
+ * flags used to have a special 16-bit magic number in the high word:
+ * 0xC0ED. If this magic number is present, the high word is discarded.
  */
 long do_mount(char * dev_name, char * dir_name, char *type_page,
- unsigned long new_flags, void *data_page)
+ unsigned long flags, void *data_page)
 {
struct file_system_type * fstype;
struct nameidata nd;
struct vfsmount *mnt = NULL;
struct super_block *sb;
int retval = 0;
-   unsigned long flags = 0;
+
+   /* Discard magic */
+   if ((flags  MS_MGC_MSK) == MS_MGC_VAL)
+   flags = ~MS_MGC_MSK;
  
/* Basic sanity checks */
 
@@ -1328,21 +1329,25 @@
/* OK, looks good, now let's see what do they want */
 
/* just change the flags? - capabilities are checked in do_remount() */
-   if ((new_flags  (MS_MGC_MSK|MS_REMOUNT)) == (MS_MGC_VAL|MS_REMOUNT))
-   return do_remount(dir_name, new_flags~(MS_MGC_MSK|MS_REMOUNT),
-   (char *) data_page);
-
-   if ((new_flags  MS_MGC_MSK) == MS_MGC_VAL)
-   flags = new_flags  ~MS_MGC_MSK;
+   if (flags  MS_REMOUNT)
+   return do_remount(dir_name, flags  ~MS_REMOUNT,
+ (char *) data_page);
+
+   /* "mount --bind"? Equivalent to older "mount -t bind" */
+   /* No capabilities? What if users do thousands of these? */
+   if (flags  MS_BIND)
+   return do_loopback(dev_name, dir_name);
 
/* For the rest we need the type */
 
if (!type_page || !memchr(type_page, 0, PAGE_SIZE))
return -EINVAL;
 
+#if 0  /* Can be deleted again. Introduced in patch-2.3.99-pre6 */
/* loopback mount? This is special - requires fewer capabilities */
if (strcmp(type_page, "bind")==0)
return do_loopback(dev_name, dir_name);
+#endif
 
/* for the rest we _really_ need capabilities... */
if (!capable(CAP_SYS_ADMIN))
@@ -1354,7 +1359,8 @@
return -ENODEV;
 
/* ... and mountpoint. Do the lookup first to force automounting. */
-   if (path_init(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_DIRECTORY, nd))
+   if (path_init(dir_name,
+ LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_DIRECTORY, nd))
retval = path_walk(dir_name, nd);
if (retval)
goto fs_out;
@@ -1363,7 +1369,7 @@
if (fstype-fs_flags  FS_NOMOUNT)
sb = ERR_PTR(-EINVAL);
else if (fstype-fs_flags  FS_REQUIRES_DEV)
-   sb = get_sb_bdev(fstype, dev_name,flags, data_page);
+   sb = get_sb_bdev(fstype, dev_name, flags, data_page);
else if (fstype-fs_flags  FS_SINGLE)
sb = get_sb_single(fstype, flags, data_page);
else
@@ -1376,6 +1382,13 @@
/* Something was mounted