[PATCH 3/3] perf/core: Fix MMAP2 event device with backing files

Adrian Hunter posted 3 patches 3 weeks, 2 days ago
[PATCH 3/3] perf/core: Fix MMAP2 event device with backing files
Posted by Adrian Hunter 3 weeks, 2 days ago
Some file systems like FUSE-based ones or overlayfs may record the backing
file in struct vm_area_struct vm_file, instead of the user file that the
user mmapped.

That causes perf to misreport the device major/minor numbers of the file
system of the file, and the generation of the file, and potentially other
inode details.  There is an existing helper file_user_inode() for that
situation.

Use file_user_inode() instead of file_inode() to get the inode for MMAP2
events.

Example:

  Setup:

    # cd /root
    # mkdir test ; cd test ; mkdir lower upper work merged
    # cp `which cat` lower
    # mount -t overlay overlay -olowerdir=lower,upperdir=upper,workdir=work merged
    # perf record -e cycles:u -- /root/test/merged/cat /proc/self/maps
    ...
    55b2c91d0000-55b2c926b000 r-xp 00018000 00:1a 3419                       /root/test/merged/cat
    ...
    [ perf record: Woken up 1 times to write data ]
    [ perf record: Captured and wrote 0.004 MB perf.data (5 samples) ]
    #
    # stat /root/test/merged/cat
      File: /root/test/merged/cat
      Size: 1127792         Blocks: 2208       IO Block: 4096   regular file
    Device: 0,26    Inode: 3419        Links: 1
    Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
    Access: 2025-09-08 12:23:59.453309624 +0000
    Modify: 2025-09-08 12:23:59.454309624 +0000
    Change: 2025-09-08 12:23:59.454309624 +0000
     Birth: 2025-09-08 12:23:59.453309624 +0000

  Before:

    Device reported 00:02 differs from stat output and /proc/self/maps

    # perf script --show-mmap-events | grep /root/test/merged/cat
             cat     377 [-01]   243.078558: PERF_RECORD_MMAP2 377/377: [0x55b2c91d0000(0x9b000) @ 0x18000 00:02 3419 2068525940]: r-xp /root/test/merged/cat

  After:

    Device reported 00:1a is the same as stat output and /proc/self/maps

    # perf script --show-mmap-events | grep /root/test/merged/cat
             cat     362 [-01]   127.755167: PERF_RECORD_MMAP2 362/362: [0x55ba6e781000(0x9b000) @ 0x18000 00:1a 3419 0]: r-xp /root/test/merged/cat

With respect to stable kernels, overlayfs mmap function ovl_mmap() was
added in v4.19 but file_user_inode() was not added until v6.8 and never
back-ported to stable kernels.  FMODE_BACKING that it depends on was added
in v6.5.  This issue has gone largely unnoticed, so back-porting before
v6.8 is probably not worth it, so put 6.8 as the stable kernel prerequisite
version, although in practice the next long term kernel is 6.12.

Cc: stable@vger.kernel.org # 6.8
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 kernel/events/core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index e203b8d90fd2..9d281785b99e 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -9403,7 +9403,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
 		flags |= MAP_HUGETLB;
 
 	if (file) {
-		struct inode *inode;
+		const struct inode *inode;
 		dev_t dev;
 
 		buf = kmalloc(PATH_MAX, GFP_KERNEL);
@@ -9421,7 +9421,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
 			name = "//toolong";
 			goto cpy_name;
 		}
-		inode = file_inode(vma->vm_file);
+		inode = file_user_inode(vma->vm_file);
 		dev = inode->i_sb->s_dev;
 		ino = inode->i_ino;
 		gen = inode->i_generation;
-- 
2.48.1
Re: [PATCH 3/3] perf/core: Fix MMAP2 event device with backing files
Posted by Amir Goldstein 3 weeks, 2 days ago
On Tue, Sep 9, 2025 at 2:42 PM Adrian Hunter <adrian.hunter@intel.com> wrote:
>
> Some file systems like FUSE-based ones or overlayfs may record the backing
> file in struct vm_area_struct vm_file, instead of the user file that the
> user mmapped.
>
> That causes perf to misreport the device major/minor numbers of the file
> system of the file, and the generation of the file, and potentially other
> inode details.  There is an existing helper file_user_inode() for that
> situation.
>
> Use file_user_inode() instead of file_inode() to get the inode for MMAP2
> events.
>
> Example:
>
>   Setup:
>
>     # cd /root
>     # mkdir test ; cd test ; mkdir lower upper work merged
>     # cp `which cat` lower
>     # mount -t overlay overlay -olowerdir=lower,upperdir=upper,workdir=work merged
>     # perf record -e cycles:u -- /root/test/merged/cat /proc/self/maps
>     ...
>     55b2c91d0000-55b2c926b000 r-xp 00018000 00:1a 3419                       /root/test/merged/cat
>     ...
>     [ perf record: Woken up 1 times to write data ]
>     [ perf record: Captured and wrote 0.004 MB perf.data (5 samples) ]
>     #
>     # stat /root/test/merged/cat
>       File: /root/test/merged/cat
>       Size: 1127792         Blocks: 2208       IO Block: 4096   regular file
>     Device: 0,26    Inode: 3419        Links: 1
>     Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
>     Access: 2025-09-08 12:23:59.453309624 +0000
>     Modify: 2025-09-08 12:23:59.454309624 +0000
>     Change: 2025-09-08 12:23:59.454309624 +0000
>      Birth: 2025-09-08 12:23:59.453309624 +0000
>
>   Before:
>
>     Device reported 00:02 differs from stat output and /proc/self/maps
>
>     # perf script --show-mmap-events | grep /root/test/merged/cat
>              cat     377 [-01]   243.078558: PERF_RECORD_MMAP2 377/377: [0x55b2c91d0000(0x9b000) @ 0x18000 00:02 3419 2068525940]: r-xp /root/test/merged/cat
>
>   After:
>
>     Device reported 00:1a is the same as stat output and /proc/self/maps
>
>     # perf script --show-mmap-events | grep /root/test/merged/cat
>              cat     362 [-01]   127.755167: PERF_RECORD_MMAP2 362/362: [0x55ba6e781000(0x9b000) @ 0x18000 00:1a 3419 0]: r-xp /root/test/merged/cat
>
> With respect to stable kernels, overlayfs mmap function ovl_mmap() was
> added in v4.19 but file_user_inode() was not added until v6.8 and never
> back-ported to stable kernels.  FMODE_BACKING that it depends on was added
> in v6.5.  This issue has gone largely unnoticed, so back-porting before
> v6.8 is probably not worth it, so put 6.8 as the stable kernel prerequisite
> version, although in practice the next long term kernel is 6.12.
>
> Cc: stable@vger.kernel.org # 6.8
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>

Feel free to add
Acked-by: Amir Goldstein <amir73il@gmail.com>

> ---
>  kernel/events/core.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index e203b8d90fd2..9d281785b99e 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -9403,7 +9403,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
>                 flags |= MAP_HUGETLB;
>
>         if (file) {
> -               struct inode *inode;
> +               const struct inode *inode;
>                 dev_t dev;
>
>                 buf = kmalloc(PATH_MAX, GFP_KERNEL);
> @@ -9421,7 +9421,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
>                         name = "//toolong";
>                         goto cpy_name;
>                 }
> -               inode = file_inode(vma->vm_file);
> +               inode = file_user_inode(vma->vm_file);
>                 dev = inode->i_sb->s_dev;
>                 ino = inode->i_ino;
>                 gen = inode->i_generation;
> --
> 2.48.1
>