Skip to contentSkip to conversation

procfs: avoid fetching build ID while holding VMA lock

PATCH Applied Andrii Nakryiko 7 participants 13 messages Jan 29 – Feb 11

Subsystems (7)
lore
Share & tools
lore

Andrii Nakryiko

author maintainer
#0 lore raw

PATCH v2 1/1 procfs: avoid fetching build ID while holding VMA lock

Fix PROCMAP_QUERY to fetch optional build ID only after dropping mmap_lock or per-VMA lock, whichever was used to lock VMA under question, to avoid deadlock reported by syzbot:

-> #1 (&mm->mmap_lock){++++}-{4:4}:

        __might_fault+0xed/0x170
        _copy_to_iter+0x118/0x1720
        copy_page_to_iter+0x12d/0x1e0
        filemap_read+0x720/0x10a0
        blkdev_read_iter+0x2b5/0x4e0
        vfs_read+0x7f4/0xae0
        ksys_read+0x12a/0x250
        do_syscall_64+0xcb/0xf80
        entry_SYSCALL_64_after_hwframe+0x77/0x7f

-> #0 (&sb->s_type->i_mutex_key#8){++++}-{4:4}:

        __lock_acquire+0x1509/0x26d0
        lock_acquire+0x185/0x340
        down_read+0x98/0x490
        blkdev_read_iter+0x2a7/0x4e0
        __kernel_read+0x39a/0xa90
        freader_fetch+0x1d5/0xa80
        __build_id_parse.isra.0+0xea/0x6a0
        do_procmap_query+0xd75/0x1050
        procfs_procmap_ioctl+0x7a/0xb0
        __x64_sys_ioctl+0x18e/0x210
        do_syscall_64+0xcb/0xf80
        entry_SYSCALL_64_after_hwframe+0x77/0x7f

other info that might help us debug this:

  Possible unsafe locking scenario:
        CPU0                    CPU1
        ----                    ----
   rlock(&mm->mmap_lock);
                                lock(&sb->s_type->i_mutex_key#8);
                                lock(&mm->mmap_lock);

rlock(&sb->s_type->i_mutex_key#8);

*** DEADLOCK ***

To make this safe, we need to grab file refcount while VMA is still locked, but other than that everything is pretty straightforward. Internal build_id_parse() API assumes VMA is passed, but it only needs the underlying file reference, so just add another variant build_id_parse_file() that expects file passed directly.

Fixes ed5d583a88a9 ("fs/procfs: implement efficient VMA querying API for /proc/<pid>/maps")
Reported-by [email protected]
---
 fs/proc/task_mmu.c      | 42 ++++++++++++++++++++++++++---------------
 include/linux/buildid.h |  3 +++
 lib/buildid.c           | 34 +++++++++++++++++++++++++--------
 3 files changed, 56 insertions(+), 23 deletions(-)
fs/proc/task_mmu.c +27 -15
index 480db575553e..dd3b5cf9f0b7 100644
@@ -656,6 +656,7 @@ static int do_procmap_query(struct mm_struct *mm, void __user *uarg)
 	struct proc_maps_locking_ctx lock_ctx = { .mm = mm };
 	struct procmap_query karg;
 	struct vm_area_struct *vma;
+	struct file *vm_file = NULL;
 	const char *name = NULL;
 	char build_id_buf[BUILD_ID_SIZE_MAX], *name_buf = NULL;
 	__u64 usize;
@@ -727,21 +728,6 @@ static int do_procmap_query(struct mm_struct *mm, void __user *uarg)
 		karg.inode = 0;
 	}
 
-	if (karg.build_id_size) {
-		__u32 build_id_sz;
-
-		err = build_id_parse(vma, build_id_buf, &build_id_sz);
-		if (err) {
-			karg.build_id_size = 0;
-		} else {
-			if (karg.build_id_size < build_id_sz) {
-				err = -ENAMETOOLONG;
-				goto out;
-			}
-			karg.build_id_size = build_id_sz;
-		}
-	}
-
 	if (karg.vma_name_size) {
 		size_t name_buf_sz = min_t(size_t, PATH_MAX, karg.vma_name_size);
 		const struct path *path;
@@ -775,10 +761,34 @@ static int do_procmap_query(struct mm_struct *mm, void __user *uarg)
 		karg.vma_name_size = name_sz;
 	}
 
+	if (karg.build_id_size && vma->vm_file)
+		vm_file = get_file(vma->vm_file);
+
 	/* unlock vma or mmap_lock, and put mm_struct before copying data to user */
 	query_vma_teardown(&lock_ctx);
 	mmput(mm);
 
+	if (karg.build_id_size) {
+		__u32 build_id_sz;
+
+		if (vm_file)
+			err = build_id_parse_file(vm_file, build_id_buf, &build_id_sz);
+		else
+			err = -ENOENT;
+		if (err) {
+			karg.build_id_size = 0;
+		} else {
+			if (karg.build_id_size < build_id_sz) {
+				err = -ENAMETOOLONG;
+				goto out;
+			}
+			karg.build_id_size = build_id_sz;
+		}
+	}
+
+	if (vm_file)
+		fput(vm_file);
+
 	if (karg.vma_name_size && copy_to_user(u64_to_user_ptr(karg.vma_name_addr),
 					       name, karg.vma_name_size)) {
 		kfree(name_buf);
@@ -798,6 +808,8 @@ static int do_procmap_query(struct mm_struct *mm, void __user *uarg)
 out:
 	query_vma_teardown(&lock_ctx);
 	mmput(mm);
+	if (vm_file)
+		fput(vm_file);
 	kfree(name_buf);
 	return err;
 }
include/linux/buildid.h +3 -0
index 831c1b4b626c..7acc06b22fb7 100644
@@ -7,7 +7,10 @@
 #define BUILD_ID_SIZE_MAX 20
 
 struct vm_area_struct;
+struct file;
+
 int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size);
+int build_id_parse_file(struct file *file, unsigned char *build_id, __u32 *size);
 int build_id_parse_nofault(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size);
 int build_id_parse_buf(const void *buf, unsigned char *build_id, u32 buf_size);
 
lib/buildid.c +26 -8
index 818331051afe..9fcbf139bd3a 100644
@@ -279,7 +279,7 @@ static int get_build_id_64(struct freader *r, unsigned char *build_id, __u32 *si
 /* enough for Elf64_Ehdr, Elf64_Phdr, and all the smaller requests */
 #define MAX_FREADER_BUF_SZ 64
 
-static int __build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
+static int __build_id_parse(struct file *file, unsigned char *build_id,
 			    __u32 *size, bool may_fault)
 {
 	const Elf32_Ehdr *ehdr;
@@ -287,11 +287,7 @@ static int __build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
 	char buf[MAX_FREADER_BUF_SZ];
 	int ret;
 
-	/* only works for page backed storage  */
-	if (!vma->vm_file)
-		return -EINVAL;
-
-	freader_init_from_file(&r, buf, sizeof(buf), vma->vm_file, may_fault);
+	freader_init_from_file(&r, buf, sizeof(buf), file, may_fault);
 
 	/* fetch first 18 bytes of ELF header for checks */
 	ehdr = freader_fetch(&r, 0, offsetofend(Elf32_Ehdr, e_type));
@@ -332,7 +328,10 @@ static int __build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
  */
 int build_id_parse_nofault(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size)
 {
-	return __build_id_parse(vma, build_id, size, false /* !may_fault */);
+	if (!vma->vm_file)
+		return -EINVAL;
+
+	return __build_id_parse(vma->vm_file, build_id, size, false /* !may_fault */);
 }
 
 /*
@@ -348,7 +347,26 @@ int build_id_parse_nofault(struct vm_area_struct *vma, unsigned char *build_id,
  */
 int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size)
 {
-	return __build_id_parse(vma, build_id, size, true /* may_fault */);
+	if (!vma->vm_file)
+		return -EINVAL;
+
+	return __build_id_parse(vma->vm_file, build_id, size, true /* may_fault */);
+}
+
+/**
+ * Parse build ID of ELF file
+ * @file:      file object
+ * @build_id: buffer to store build id, at least BUILD_ID_SIZE long
+ * @size:     returns actual build id size in case of success
+ *
+ * Assumes faultable context and can cause page faults to bring in file data
+ * into page cache.
+ *
+ * Return: 0 on success; negative error, otherwise
+ */
+int build_id_parse_file(struct file *file, unsigned char *build_id, __u32 *size)
+{
+	return __build_id_parse(file, build_id, size, true /* may_fault */);
 }
 
 /**
Signature · 1 line
2.47.3
#1 lore raw
kernel test robot noticed the following build warnings:

Hi Andrii,

kernel test robot noticed the following build warnings:

[auto build test WARNING on bpf-next/net]
[also build test WARNING on bpf-next/master bpf/master linus/master v6.19-rc7] [cannot apply to akpm-mm/mm-everything next-20260129]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Andrii-Nakryiko/procfs-avoid-fetching-build-ID-while-holding-VMA-lock/20260130-055639
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git net
patch link:    https://lore.kernel.org/r/20260129215340.3742283-1-andrii%40kernel.org
patch subject: [PATCH v2 mm-stable] procfs: avoid fetching build ID while holding VMA lock
config: nios2-allnoconfig (https://download.01.org/0day-ci/archive/20260130/[email protected]/config)
compiler: nios2-linux-gcc (GCC) 11.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260130/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

>> Warning: lib/buildid.c:348 This comment starts with '/**', but isn't a kernel-doc comment. Refer to Documentation/doc-guide/kernel-doc.rst

* Parse build ID of ELF file

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
#2 lore raw
Quoted 25 lines · kernel test robot

Hi Andrii,

kernel test robot noticed the following build warnings:

[auto build test WARNING on bpf-next/net]
[also build test WARNING on bpf-next/master bpf/master linus/master v6.19-rc7] [cannot apply to akpm-mm/mm-everything next-20260129]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Andrii-Nakryiko/procfs-avoid-fetching-build-ID-while-holding-VMA-lock/20260130-055639
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git net
patch link:    https://lore.kernel.org/r/20260129215340.3742283-1-andrii%40kernel.org
patch subject: [PATCH v2 mm-stable] procfs: avoid fetching build ID while holding VMA lock
config: nios2-allnoconfig (https://download.01.org/0day-ci/archive/20260130/[email protected]/config)
compiler: nios2-linux-gcc (GCC) 11.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260130/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

Quoted 4 lines

All warnings (new ones prefixed by >>):

Quoted 1 line
Quoted 1 line

Warning: lib/buildid.c:348 This comment starts with '/**', but isn't a kernel-doc comment. Refer to Documentation/doc-guide/kernel-doc.rst

* Parse build ID of ELF file

So AI tells me to be a proper kernel-doc comment this should have been:

* build_id_parse_file() - Parse build ID of ELF file

Andrew, should I send v3 or you can just patch it up in-place? Thanks!

Quoted 4 lines

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

maintainer
#3 lore raw
Quoted 7 lines · On Fri, 30 Jan 2026 12:11:31 -0800 Andrii Nakryiko <[email protected]>…
Quoted 7 lines

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

Quoted 8 lines
Quoted 2 lines
Quoted 1 line
Quoted 1 line

Warning: lib/buildid.c:348 This comment starts with '/**', but isn't a kernel-doc comment. Refer to Documentation/doc-guide/kernel-doc.rst

* Parse build ID of ELF file

So AI tells me to be a proper kernel-doc comment this should have been:

* build_id_parse_file() - Parse build ID of ELF file

Andrew, should I send v3 or you can just patch it up in-place? Thanks!

No probs.

The preceding two functions are trying to be kerneldoc but failed. How about this?

lib/buildid.c renamed from lib/buildid.c~procfs-avoid-fetching-build-id-while-holding-vma-lock-fix +5 -5
@@ -315,8 +315,8 @@ out:
 	return ret;
 }
 
-/*
- * Parse build ID of ELF file mapped to vma
+/**
+ * build_id_parse_nofault() - Parse build ID of ELF file mapped to vma
  * @vma:      vma object
  * @build_id: buffer to store build id, at least BUILD_ID_SIZE long
  * @size:     returns actual build id size in case of success
@@ -334,8 +334,8 @@ int build_id_parse_nofault(struct vm_are
 	return __build_id_parse(vma->vm_file, build_id, size, false /* !may_fault */);
 }
 
-/*
- * Parse build ID of ELF file mapped to VMA
+/**
+ * build_id_parse() - Parse build ID of ELF file mapped to VMA
  * @vma:      vma object
  * @build_id: buffer to store build id, at least BUILD_ID_SIZE long
  * @size:     returns actual build id size in case of success
@@ -354,7 +354,7 @@ int build_id_parse(struct vm_area_struct
 }
 
 /**
- * Parse build ID of ELF file
+ * build_id_parse_file() - Parse build ID of ELF file
  * @file:      file object
  * @build_id: buffer to store build id, at least BUILD_ID_SIZE long
  * @size:     returns actual build id size in case of success

_

#4 lore raw
Quoted 15 lines · Andrew Morton
Quoted 12 lines · On Fri, 30 Jan 2026 12:11:31 -0800 Andrii Nakryiko <[email protected]>…
Quoted 9 lines

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

Quoted 1 line
Quoted 1 line

Warning: lib/buildid.c:348 This comment starts with '/**', but isn't a kernel-doc comment. Refer to Documentation/doc-guide/kernel-doc.rst

* Parse build ID of ELF file

So AI tells me to be a proper kernel-doc comment this should have been:

Quoted 10 lines
Quoted 3 lines

* build_id_parse_file() - Parse build ID of ELF file

Andrew, should I send v3 or you can just patch it up in-place? Thanks!

No probs.

The preceding two functions are trying to be kerneldoc but failed. How about this?

yep, LGTM, thanks!

Quoted 35 lines
lib/buildid.c renamed from lib/buildid.c~procfs-avoid-fetching-build-id-while-holding-vma-lock-fix +5 -5
@@ -315,8 +315,8 @@ out:
        return ret;
 }
 
-/*
- * Parse build ID of ELF file mapped to vma
+/**
+ * build_id_parse_nofault() - Parse build ID of ELF file mapped to vma
  * @vma:      vma object
  * @build_id: buffer to store build id, at least BUILD_ID_SIZE long
  * @size:     returns actual build id size in case of success
@@ -334,8 +334,8 @@ int build_id_parse_nofault(struct vm_are
        return __build_id_parse(vma->vm_file, build_id, size, false /* !may_fault */);
 }
 
-/*
- * Parse build ID of ELF file mapped to VMA
+/**
+ * build_id_parse() - Parse build ID of ELF file mapped to VMA
  * @vma:      vma object
  * @build_id: buffer to store build id, at least BUILD_ID_SIZE long
  * @size:     returns actual build id size in case of success
@@ -354,7 +354,7 @@ int build_id_parse(struct vm_area_struct
 }
 
 /**
- * Parse build ID of ELF file
+ * build_id_parse_file() - Parse build ID of ELF file
  * @file:      file object
  * @build_id: buffer to store build id, at least BUILD_ID_SIZE long
  * @size:     returns actual build id size in case of success

_

Reviewed-by on v2 1/1
#5 lore raw
In reply to Andrii Nakryiko
Quoted 49 lines · Andrii Nakryiko

Fix PROCMAP_QUERY to fetch optional build ID only after dropping mmap_lock or per-VMA lock, whichever was used to lock VMA under question, to avoid deadlock reported by syzbot:

-> #1 (&mm->mmap_lock){++++}-{4:4}:

        __might_fault+0xed/0x170
        _copy_to_iter+0x118/0x1720
        copy_page_to_iter+0x12d/0x1e0
        filemap_read+0x720/0x10a0
        blkdev_read_iter+0x2b5/0x4e0
        vfs_read+0x7f4/0xae0
        ksys_read+0x12a/0x250
        do_syscall_64+0xcb/0xf80
        entry_SYSCALL_64_after_hwframe+0x77/0x7f

-> #0 (&sb->s_type->i_mutex_key#8){++++}-{4:4}:

        __lock_acquire+0x1509/0x26d0
        lock_acquire+0x185/0x340
        down_read+0x98/0x490
        blkdev_read_iter+0x2a7/0x4e0
        __kernel_read+0x39a/0xa90
        freader_fetch+0x1d5/0xa80
        __build_id_parse.isra.0+0xea/0x6a0
        do_procmap_query+0xd75/0x1050
        procfs_procmap_ioctl+0x7a/0xb0
        __x64_sys_ioctl+0x18e/0x210
        do_syscall_64+0xcb/0xf80
        entry_SYSCALL_64_after_hwframe+0x77/0x7f

other info that might help us debug this:

  Possible unsafe locking scenario:
        CPU0                    CPU1
        ----                    ----
   rlock(&mm->mmap_lock);
                                lock(&sb->s_type->i_mutex_key#8);
                                lock(&mm->mmap_lock);

rlock(&sb->s_type->i_mutex_key#8);

*** DEADLOCK ***

To make this safe, we need to grab file refcount while VMA is still locked, but other than that everything is pretty straightforward. Internal build_id_parse() API assumes VMA is passed, but it only needs the underlying file reference, so just add another variant build_id_parse_file() that expects file passed directly.

Quoted 5 lines
Fixes ed5d583a88a9 ("fs/procfs: implement efficient VMA querying API for /proc/<pid>/maps")
Reported-by [email protected]
#6 lore raw
In reply to Andrii Nakryiko
kernel test robot noticed the following build warnings:

Hi Andrii,

kernel test robot noticed the following build warnings:

[auto build test WARNING on bpf-next/net]
[also build test WARNING on bpf-next/master bpf/master]
[cannot apply to akpm-mm/mm-everything linus/master v6.16-rc1 next-20260129] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Andrii-Nakryiko/procfs-avoid-fetching-build-ID-while-holding-VMA-lock/20260130-055639
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git net
patch link:    https://lore.kernel.org/r/20260129215340.3742283-1-andrii%40kernel.org
patch subject: [PATCH v2 mm-stable] procfs: avoid fetching build ID while holding VMA lock
config: x86_64-rhel-9.4-ltp (https://download.01.org/0day-ci/archive/20260130/[email protected]/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260130/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

>> Warning: lib/buildid.c:348 This comment starts with '/**', but isn't a kernel-doc comment. Refer to Documentation/doc-guide/kernel-doc.rst

* Parse build ID of ELF file

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
#7 lore raw

PATCH v2 1/1 procfs: avoid fetching build ID while holding VMA lock

In reply to Andrii Nakryiko
Quoted 7 lines · Andrii Nakryiko
fs/proc/task_mmu.c +3 -0
 	/* unlock vma or mmap_lock, and put mm_struct before copying data to user */
 	query_vma_teardown(&lock_ctx);
 	mmput(mm);
 
+	if (karg.build_id_size) {
+		__u32 build_id_sz;
+

fs/proc/task_mmu.c static int do_procmap_query(struct mm_struct *mm, void __user *uarg) · line 783

Quoted 10 lines
fs/proc/task_mmu.c +10 -0
+		if (vm_file)
+			err = build_id_parse_file(vm_file, build_id_buf, &build_id_sz);
+		else
+			err = -ENOENT;
+		if (err) {
+			karg.build_id_size = 0;
+		} else {
+			if (karg.build_id_size < build_id_sz) {
+				err = -ENAMETOOLONG;
+				goto out;

Introduces a double mmput() here.

Quoted 12 lines
fs/proc/task_mmu.c +8 -0
+			}
+			karg.build_id_size = build_id_sz;
+		}
+	}
+
+	if (vm_file)
+		fput(vm_file);
+
 	if (karg.vma_name_size && copy_to_user(u64_to_user_ptr(karg.vma_name_addr),
 					       name, karg.vma_name_size)) {
 		kfree(name_buf);

fs/proc/task_mmu.c static int do_procmap_query(struct mm_struct *mm, void __user *uarg) · line 814

Quoted 7 lines
fs/proc/task_mmu.c +2 -0
@@ -798,6 +808,8 @@ static int do_procmap_query(struct mm_struct *mm, void __user *uarg)
 out:
 	query_vma_teardown(&lock_ctx);
 	mmput(mm);
+	if (vm_file)
+		fput(vm_file);
 	kfree(name_buf);
 	return err;

See:

        https://lore.kernel.org/all/[email protected]/T/#u

Thanks

tglx

#8 lore raw
Quoted 44 lines · Thomas Gleixner
Quoted 7 lines · Andrii Nakryiko
      /* unlock vma or mmap_lock, and put mm_struct before copying data to user */
      query_vma_teardown(&lock_ctx);
      mmput(mm);
fs/proc/task_mmu.c +3 -0
+     if (karg.build_id_size) {
+             __u32 build_id_sz;
+

fs/proc/task_mmu.c static int do_procmap_query(struct mm_struct *mm, void __user *uarg) · line 783

Quoted 10 lines
fs/proc/task_mmu.c +10 -0
+             if (vm_file)
+                     err = build_id_parse_file(vm_file, build_id_buf, &build_id_sz);
+             else
+                     err = -ENOENT;
+             if (err) {
+                     karg.build_id_size = 0;
+             } else {
+                     if (karg.build_id_size < build_id_sz) {
+                             err = -ENAMETOOLONG;
+                             goto out;

Introduces a double mmput() here.

Quoted 12 lines
fs/proc/task_mmu.c +8 -0
+                     }
+                     karg.build_id_size = build_id_sz;
+             }
+     }
+
+     if (vm_file)
+             fput(vm_file);
+
      if (karg.vma_name_size && copy_to_user(u64_to_user_ptr(karg.vma_name_addr),
                                             name, karg.vma_name_size)) {
              kfree(name_buf);

fs/proc/task_mmu.c static int do_procmap_query(struct mm_struct *mm, void __user *uarg) · line 814

Quoted 7 lines
fs/proc/task_mmu.c +2 -0
@@ -798,6 +808,8 @@ static int do_procmap_query(struct mm_struct *mm, void __user *uarg)
 out:
      query_vma_teardown(&lock_ctx);
      mmput(mm);
+     if (vm_file)
+             fput(vm_file);
      kfree(name_buf);
      return err;

See:

Quoted 2 lines
        https://lore.kernel.org/all/[email protected]/T/#u

Ah, silly mistake on my part, thanks for the heads up, I'll send a fix shortly

Quoted 3 lines

Thanks

tglx

#9 lore raw

PATCH 1/1 procfs: Prevent double mmput() in do_procmap_query()

A recent fix moved the build ID evaluation past the mmput() of the success path but kept the error goto unchanged, which ends up in doing another quert_vma_teardown() and another mmput().

Change the goto so it jumps past the mmput() and only puts the file and the buffer.

Fixes b5cbacd7f86f ("procfs: avoid fetching build ID while holding VMA lock")
Reported-by [email protected]
---
 fs/proc/task_mmu.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
fs/proc/task_mmu.c +3 -1
@@ -780,7 +780,7 @@ static int do_procmap_query(struct mm_st
 		} else {
 			if (karg.build_id_size < build_id_sz) {
 				err = -ENAMETOOLONG;
-				goto out;
+				goto out_file;
 			}
 			karg.build_id_size = build_id_sz;
 		}
@@ -808,6 +808,8 @@ static int do_procmap_query(struct mm_st
 out:
 	query_vma_teardown(&lock_ctx);
 	mmput(mm);
+
+out_file:
 	if (vm_file)
 		fput(vm_file);
 	kfree(name_buf);
Reviewed-by on v1 1/1
#10 lore raw

Re: [PATCH] procfs: Prevent double mmput() in do_procmap_query()

Quoted 11 lines · Thomas Gleixner

A recent fix moved the build ID evaluation past the mmput() of the success path but kept the error goto unchanged, which ends up in doing another quert_vma_teardown() and another mmput().

Change the goto so it jumps past the mmput() and only puts the file and the buffer.

Fixes b5cbacd7f86f ("procfs: avoid fetching build ID while holding VMA lock")
Reported-by [email protected]

Sebastian

#11 lore raw

Re: [PATCH] procfs: Prevent double mmput() in do_procmap_query()

Quoted 9 lines · Sebastian Andrzej Siewior
Quoted 7 lines · Thomas Gleixner

A recent fix moved the build ID evaluation past the mmput() of the success path but kept the error goto unchanged, which ends up in doing another quert_vma_teardown() and another mmput().

Change the goto so it jumps past the mmput() and only puts the file and the buffer.

Quoted 7 lines
Quoted 4 lines
Fixes b5cbacd7f86f ("procfs: avoid fetching build ID while holding VMA lock")
Reported-by [email protected]

We raced with Thomas sending the same fix, I see that my patch was staged by Andrew already in [0], just FYI

[0] https://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new.git/tree/patches/procfs-fix-possible-double-mmput-in-do_procmap_query.patch

Quoted 1 line

Sebastian

#12 lore raw

Re: [PATCH] procfs: Prevent double mmput() in do_procmap_query()

Quoted 3 lines · Andrii Nakryiko

We raced with Thomas sending the same fix, I see that my patch was staged by Andrew already in [0], just FYI

This one has a reviewer :)

Sebastian