Skip to content

Commit 3dc58c9

Browse files
committed
Merge tag 'mm-hotfixes-stable-2026-02-06-12-37' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Pull hotfixes from Andrew Morton: "A couple of late-breaking MM fixes. One against a new-in-this-cycle patch and the other addresses a locking issue which has been there for over a year" * tag 'mm-hotfixes-stable-2026-02-06-12-37' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: mm/memory-failure: reject unsupported non-folio compound page procfs: avoid fetching build ID while holding VMA lock
2 parents bab849a + ae9fd76 commit 3dc58c9

4 files changed

Lines changed: 80 additions & 49 deletions

File tree

fs/proc/task_mmu.c

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,7 @@ static int do_procmap_query(struct mm_struct *mm, void __user *uarg)
656656
struct proc_maps_locking_ctx lock_ctx = { .mm = mm };
657657
struct procmap_query karg;
658658
struct vm_area_struct *vma;
659+
struct file *vm_file = NULL;
659660
const char *name = NULL;
660661
char build_id_buf[BUILD_ID_SIZE_MAX], *name_buf = NULL;
661662
__u64 usize;
@@ -727,21 +728,6 @@ static int do_procmap_query(struct mm_struct *mm, void __user *uarg)
727728
karg.inode = 0;
728729
}
729730

730-
if (karg.build_id_size) {
731-
__u32 build_id_sz;
732-
733-
err = build_id_parse(vma, build_id_buf, &build_id_sz);
734-
if (err) {
735-
karg.build_id_size = 0;
736-
} else {
737-
if (karg.build_id_size < build_id_sz) {
738-
err = -ENAMETOOLONG;
739-
goto out;
740-
}
741-
karg.build_id_size = build_id_sz;
742-
}
743-
}
744-
745731
if (karg.vma_name_size) {
746732
size_t name_buf_sz = min_t(size_t, PATH_MAX, karg.vma_name_size);
747733
const struct path *path;
@@ -775,10 +761,34 @@ static int do_procmap_query(struct mm_struct *mm, void __user *uarg)
775761
karg.vma_name_size = name_sz;
776762
}
777763

764+
if (karg.build_id_size && vma->vm_file)
765+
vm_file = get_file(vma->vm_file);
766+
778767
/* unlock vma or mmap_lock, and put mm_struct before copying data to user */
779768
query_vma_teardown(&lock_ctx);
780769
mmput(mm);
781770

771+
if (karg.build_id_size) {
772+
__u32 build_id_sz;
773+
774+
if (vm_file)
775+
err = build_id_parse_file(vm_file, build_id_buf, &build_id_sz);
776+
else
777+
err = -ENOENT;
778+
if (err) {
779+
karg.build_id_size = 0;
780+
} else {
781+
if (karg.build_id_size < build_id_sz) {
782+
err = -ENAMETOOLONG;
783+
goto out;
784+
}
785+
karg.build_id_size = build_id_sz;
786+
}
787+
}
788+
789+
if (vm_file)
790+
fput(vm_file);
791+
782792
if (karg.vma_name_size && copy_to_user(u64_to_user_ptr(karg.vma_name_addr),
783793
name, karg.vma_name_size)) {
784794
kfree(name_buf);
@@ -798,6 +808,8 @@ static int do_procmap_query(struct mm_struct *mm, void __user *uarg)
798808
out:
799809
query_vma_teardown(&lock_ctx);
800810
mmput(mm);
811+
if (vm_file)
812+
fput(vm_file);
801813
kfree(name_buf);
802814
return err;
803815
}

include/linux/buildid.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
#define BUILD_ID_SIZE_MAX 20
88

99
struct vm_area_struct;
10+
struct file;
11+
1012
int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size);
13+
int build_id_parse_file(struct file *file, unsigned char *build_id, __u32 *size);
1114
int build_id_parse_nofault(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size);
1215
int build_id_parse_buf(const void *buf, unsigned char *build_id, u32 buf_size);
1316

lib/buildid.c

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -279,19 +279,15 @@ static int get_build_id_64(struct freader *r, unsigned char *build_id, __u32 *si
279279
/* enough for Elf64_Ehdr, Elf64_Phdr, and all the smaller requests */
280280
#define MAX_FREADER_BUF_SZ 64
281281

282-
static int __build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
282+
static int __build_id_parse(struct file *file, unsigned char *build_id,
283283
__u32 *size, bool may_fault)
284284
{
285285
const Elf32_Ehdr *ehdr;
286286
struct freader r;
287287
char buf[MAX_FREADER_BUF_SZ];
288288
int ret;
289289

290-
/* only works for page backed storage */
291-
if (!vma->vm_file)
292-
return -EINVAL;
293-
294-
freader_init_from_file(&r, buf, sizeof(buf), vma->vm_file, may_fault);
290+
freader_init_from_file(&r, buf, sizeof(buf), file, may_fault);
295291

296292
/* fetch first 18 bytes of ELF header for checks */
297293
ehdr = freader_fetch(&r, 0, offsetofend(Elf32_Ehdr, e_type));
@@ -319,8 +315,8 @@ static int __build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
319315
return ret;
320316
}
321317

322-
/*
323-
* Parse build ID of ELF file mapped to vma
318+
/**
319+
* build_id_parse_nofault() - Parse build ID of ELF file mapped to vma
324320
* @vma: vma object
325321
* @build_id: buffer to store build id, at least BUILD_ID_SIZE long
326322
* @size: returns actual build id size in case of success
@@ -332,11 +328,14 @@ static int __build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
332328
*/
333329
int build_id_parse_nofault(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size)
334330
{
335-
return __build_id_parse(vma, build_id, size, false /* !may_fault */);
331+
if (!vma->vm_file)
332+
return -EINVAL;
333+
334+
return __build_id_parse(vma->vm_file, build_id, size, false /* !may_fault */);
336335
}
337336

338-
/*
339-
* Parse build ID of ELF file mapped to VMA
337+
/**
338+
* build_id_parse() - Parse build ID of ELF file mapped to VMA
340339
* @vma: vma object
341340
* @build_id: buffer to store build id, at least BUILD_ID_SIZE long
342341
* @size: returns actual build id size in case of success
@@ -348,7 +347,26 @@ int build_id_parse_nofault(struct vm_area_struct *vma, unsigned char *build_id,
348347
*/
349348
int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size)
350349
{
351-
return __build_id_parse(vma, build_id, size, true /* may_fault */);
350+
if (!vma->vm_file)
351+
return -EINVAL;
352+
353+
return __build_id_parse(vma->vm_file, build_id, size, true /* may_fault */);
354+
}
355+
356+
/**
357+
* build_id_parse_file() - Parse build ID of ELF file
358+
* @file: file object
359+
* @build_id: buffer to store build id, at least BUILD_ID_SIZE long
360+
* @size: returns actual build id size in case of success
361+
*
362+
* Assumes faultable context and can cause page faults to bring in file data
363+
* into page cache.
364+
*
365+
* Return: 0 on success; negative error, otherwise
366+
*/
367+
int build_id_parse_file(struct file *file, unsigned char *build_id, __u32 *size)
368+
{
369+
return __build_id_parse(file, build_id, size, true /* may_fault */);
352370
}
353371

354372
/**

mm/memory-failure.c

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2411,31 +2411,29 @@ int memory_failure(unsigned long pfn, int flags)
24112411
* In fact it's dangerous to directly bump up page count from 0,
24122412
* that may make page_ref_freeze()/page_ref_unfreeze() mismatch.
24132413
*/
2414-
if (!(flags & MF_COUNT_INCREASED)) {
2415-
res = get_hwpoison_page(p, flags);
2416-
if (!res) {
2417-
if (is_free_buddy_page(p)) {
2418-
if (take_page_off_buddy(p)) {
2419-
page_ref_inc(p);
2420-
res = MF_RECOVERED;
2421-
} else {
2422-
/* We lost the race, try again */
2423-
if (retry) {
2424-
ClearPageHWPoison(p);
2425-
retry = false;
2426-
goto try_again;
2427-
}
2428-
res = MF_FAILED;
2429-
}
2430-
res = action_result(pfn, MF_MSG_BUDDY, res);
2414+
res = get_hwpoison_page(p, flags);
2415+
if (!res) {
2416+
if (is_free_buddy_page(p)) {
2417+
if (take_page_off_buddy(p)) {
2418+
page_ref_inc(p);
2419+
res = MF_RECOVERED;
24312420
} else {
2432-
res = action_result(pfn, MF_MSG_KERNEL_HIGH_ORDER, MF_IGNORED);
2421+
/* We lost the race, try again */
2422+
if (retry) {
2423+
ClearPageHWPoison(p);
2424+
retry = false;
2425+
goto try_again;
2426+
}
2427+
res = MF_FAILED;
24332428
}
2434-
goto unlock_mutex;
2435-
} else if (res < 0) {
2436-
res = action_result(pfn, MF_MSG_GET_HWPOISON, MF_IGNORED);
2437-
goto unlock_mutex;
2429+
res = action_result(pfn, MF_MSG_BUDDY, res);
2430+
} else {
2431+
res = action_result(pfn, MF_MSG_KERNEL_HIGH_ORDER, MF_IGNORED);
24382432
}
2433+
goto unlock_mutex;
2434+
} else if (res < 0) {
2435+
res = action_result(pfn, MF_MSG_GET_HWPOISON, MF_IGNORED);
2436+
goto unlock_mutex;
24392437
}
24402438

24412439
folio = page_folio(p);

0 commit comments

Comments
 (0)