]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
UBUNTU: SAUCE: overlayfs: fix reference count mismatch
authorAndrea Righi <andrea.righi@canonical.com>
Thu, 22 Jun 2023 09:37:00 +0000 (11:37 +0200)
committerStefan Bader <stefan.bader@canonical.com>
Wed, 9 Aug 2023 10:02:08 +0000 (12:02 +0200)
BugLink: https://bugs.launchpad.net/bugs/2016398
Opened files reported in /proc/pid/map_files can be shows with the wrong
mount point using overlayfs with filesystem namspaces.

This incorrect behavior is fixed:

  UBUNTU: SAUCE: overlayfs: fix incorrect mnt_id of files opened from map_files

However, the fix introduced a new regression, the reference to the
original file stored in vma->vm_prfile is not properly released when
vma->vm_prfile is replaced with a new file.

This can cause a reference counter unbalance, leading errors such as
"target is busy" when trying to unmount overlayfs, even if the
filesystem has not active reference.

Fix by properly releasing the original file stored in vm_prfile.

Fixes: 508fdae3f62dd ("UBUNTU: SAUCE: overlayfs: fix incorrect mnt_id of files opened from map_files")
Signed-off-by: Andrea Righi <andrea.righi@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Acked-by: Roxana Nicolescu <roxana.nicolescu@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
fs/overlayfs/file.c

index e3c6834d8d0f1eff79d0a0b72c620209fd6deb8a..6230364ae4b41b74c4c1fbf4d395996bee274c5c 100644 (file)
@@ -504,16 +504,33 @@ static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync)
  *
  * See also mm/prfile.c
  */
+#ifdef CONFIG_MMU
 static void ovl_vm_prfile_set(struct vm_area_struct *vma,
                              struct file *file)
 {
        get_file(file);
-       vma->vm_prfile = file;
-#ifndef CONFIG_MMU
+       swap(vma->vm_prfile, file);
+       /* Drop reference count from previous file value */
+       if (file)
+               fput(file);
+}
+#else
+static void ovl_vm_prfile_set(struct vm_area_struct *vma,
+                             struct file *file)
+{
+       struct file *vm_region_file = file;
+
        get_file(file);
-       vma->vm_region->vm_prfile = file;
-#endif
+       get_file(vm_region_file);
+       swap(vma->vm_prfile, file);
+       swap(vma->vm_region->vm_prfile, vm_region_file);
+       /* Drop reference count from previous file values */
+       if (file)
+               fput(file);
+       if (vm_region_file)
+               fput(vm_region_file);
 }
+#endif
 
 static int ovl_mmap(struct file *file, struct vm_area_struct *vma)
 {