patch-2.4.0-test9 linux/fs/super.c

Next file: linux/fs/udf/ialloc.c
Previous file: linux/fs/smbfs/inode.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test8/linux/fs/super.c linux/fs/super.c
@@ -483,6 +483,7 @@
 	{ NFS_MOUNT_NOCTO, ",nocto", "" },
 	{ NFS_MOUNT_NOAC, ",noac", "" },
 	{ NFS_MOUNT_NONLM, ",nolock", ",lock" },
+	{ NFS_MOUNT_BROKEN_SUID, ",broken_suid", "" },
 	{ 0, NULL, NULL }
 };
 
@@ -1303,20 +1304,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 +1330,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 +1360,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 +1370,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 +1383,13 @@
 	/* Something was mounted here while we slept */
 	while(d_mountpoint(nd.dentry) && follow_down(&nd.mnt, &nd.dentry))
 		;
+
+	/* 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;
+
 	retval = -ENOENT;
 	if (!nd.dentry->d_inode)
 		goto fail;
@@ -1403,7 +1417,7 @@
 }
 
 asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
-			  unsigned long new_flags, void * data)
+			  unsigned long flags, void * data)
 {
 	int retval;
 	unsigned long data_page;
@@ -1423,14 +1437,18 @@
 	retval = copy_mount_options (dev_name, &dev_page);
 	if (retval < 0)
 		goto out2;
+
 	retval = copy_mount_options (data, &data_page);
-	if (retval >= 0) {
-		lock_kernel();
-		retval = do_mount((char*)dev_page,dir_page,(char*)type_page,
-				      new_flags, (void*)data_page);
-		unlock_kernel();
-		free_page(data_page);
-	}
+	if (retval < 0)
+		goto out3;
+
+	lock_kernel();
+	retval = do_mount((char*)dev_page, dir_page, (char*)type_page,
+			  flags, (void*)data_page);
+	unlock_kernel();
+	free_page(data_page);
+
+out3:
 	free_page(dev_page);
 out2:
 	putname(dir_page);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)