btrfs: Fix use-after-free when cleaning up fs_devs with a single stale device

"Linux Kernel Mailing List" <[email protected]> Fri, 16 Feb 2018 17:44:23 +0000 (UTC)
Newsgroups gmane.linux.kernel.commits.head
Message-ID <[email protected]>
Web:        https://git.kernel.org/torvalds/c/fd649f10c3d21ee9d7542c609f29978bdf73ab94
Commit:     fd649f10c3d21ee9d7542c609f29978bdf73ab94
Parent:     627e08738e4315458c5df06358ce7a65cfdd635d
Refname:    refs/heads/master
Author:     Nikolay Borisov <[email protected]>
AuthorDate: Tue Jan 30 16:07:37 2018 +0200
Committer:  David Sterba <[email protected]>
CommitDate: Mon Feb 5 17:15:14 2018 +0100

    btrfs: Fix use-after-free when cleaning up fs_devs with a single stale device
    
    Commit 4fde46f0cc71 ("Btrfs: free the stale device") introduced
    btrfs_free_stale_device which iterates the device lists for all
    registered btrfs filesystems and deletes those devices which aren't
    mounted. In a btrfs_devices structure has only 1 device attached to it
    and it is unused then btrfs_free_stale_devices will proceed to also free
    the btrfs_fs_devices struct itself. Currently this leads to a use after
    free since list_for_each_entry will try to perform a check on the
    already freed memory to see if it has to terminate the loop.
    
    The fix is to use 'break' when we know we are freeing the current
    fs_devs.
    
    Fixes: 4fde46f0cc71 ("Btrfs: free the stale device")
    Signed-off-by: Nikolay Borisov <[email protected]>
    Reviewed-by: Anand Jain <[email protected]>
    Signed-off-by: David Sterba <[email protected]>
---
 fs/btrfs/volumes.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index b5036bd69e6a..2ceb924ca0d6 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -645,6 +645,7 @@ static void btrfs_free_stale_devices(const char *path,
 				btrfs_sysfs_remove_fsid(fs_devs);
 				list_del(&fs_devs->list);
 				free_fs_devices(fs_devs);
+				break;
 			} else {
 				fs_devs->num_devices--;
 				list_del(&dev->dev_list);
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html