binder: fix UAF when releasing todo list
[GitHub/MotorolaMobilityLLC/kernel-slsi.git] / fs / super.c
index 219f7ca7c5d294403e80ab04b669bebbef71fa5b..589f919ec20b56e369c13cb136607600a48abe61 100644 (file)
@@ -814,7 +814,8 @@ rescan:
 }
 
 /**
- *     do_remount_sb - asks filesystem to change mount options.
+ *     do_remount_sb2 - asks filesystem to change mount options.
+ *     @mnt:   mount we are looking at
  *     @sb:    superblock in question
  *     @sb_flags: revised superblock flags
  *     @data:  the rest of options
@@ -822,7 +823,7 @@ rescan:
  *
  *     Alters the mount options of a mounted file system.
  */
-int do_remount_sb(struct super_block *sb, int sb_flags, void *data, int force)
+int do_remount_sb2(struct vfsmount *mnt, struct super_block *sb, int sb_flags, void *data, int force)
 {
        int retval;
        int remount_ro;
@@ -864,7 +865,16 @@ int do_remount_sb(struct super_block *sb, int sb_flags, void *data, int force)
                }
        }
 
-       if (sb->s_op->remount_fs) {
+       if (mnt && sb->s_op->remount_fs2) {
+               retval = sb->s_op->remount_fs2(mnt, sb, &sb_flags, data);
+               if (retval) {
+                       if (!force)
+                               goto cancel_readonly;
+                       /* If forced remount, go ahead despite any errors */
+                       WARN(1, "forced remount of a %s fs returned %i\n",
+                            sb->s_type->name, retval);
+               }
+       } else if (sb->s_op->remount_fs) {
                retval = sb->s_op->remount_fs(sb, &sb_flags, data);
                if (retval) {
                        if (!force)
@@ -896,12 +906,17 @@ cancel_readonly:
        return retval;
 }
 
+int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
+{
+       return do_remount_sb2(NULL, sb, flags, data, force);
+}
+
 static void do_emergency_remount(struct work_struct *work)
 {
        struct super_block *sb, *p = NULL;
 
        spin_lock(&sb_lock);
-       list_for_each_entry(sb, &super_blocks, s_list) {
+       list_for_each_entry_reverse(sb, &super_blocks, s_list) {
                if (hlist_unhashed(&sb->s_instances))
                        continue;
                sb->s_count++;
@@ -1217,7 +1232,7 @@ struct dentry *mount_single(struct file_system_type *fs_type,
 EXPORT_SYMBOL(mount_single);
 
 struct dentry *
-mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
+mount_fs(struct file_system_type *type, int flags, const char *name, struct vfsmount *mnt, void *data)
 {
        struct dentry *root;
        struct super_block *sb;
@@ -1234,7 +1249,10 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
                        goto out_free_secdata;
        }
 
-       root = type->mount(type, flags, name, data);
+       if (type->mount2)
+               root = type->mount2(mnt, type, flags, name, data);
+       else
+               root = type->mount(type, flags, name, data);
        if (IS_ERR(root)) {
                error = PTR_ERR(root);
                goto out_free_secdata;