CVE-2022-49049

mm/secretmem: fix panic when growing a memfd_secret

published February 26, 2025

CVSS
—
EPSS
0%
Percentile
16.5
In the wild
Unconfirmed
What it is

In the Linux kernel, the following vulnerability has been resolved:

mm/secretmem: fix panic when growing a memfd_secret

When one tries to grow an existing memfd_secret with ftruncate, one gets

a panic [1]. For example, doing the following reliably induces the

panic:

fd = memfd_secret();

ftruncate(fd, 10);

ptr = mmap(NULL, 10, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

strcpy(ptr, "123456789");

munmap(ptr, 10);

ftruncate(fd, 20);

The basic reason for this is, when we grow with ftruncate, we call down

into simple_setattr, and then truncate_inode_pages_range, and eventually

we try to zero part of the memory. The normal truncation code does this

via the direct map (i.e., it calls page_address() and hands that to

memset()).

For memfd_secret though, we specifically don't map our pages via the

direct map (i.e. we call set_direct_map_invalid_noflush() on every

fault). So the address returned by page_address() isn't useful, and

when we try to memset() with it we panic.

This patch avoids the panic by implementing a custom setattr for

memfd_secret, which detects resizes specifically (setting the size for

the first time works just fine, since there are no existing pages to try

to zero), and rejects them with EINVAL.

One could argue growing should be supported, but I think that will

require a significantly more lengthy change. So, I propose a minimal

fix for the benefit of stable kernels, and then perhaps to extend

memfd_secret to support growing in a separate patch.

[1]:

BUG: unable to handle page fault for address: ffffa0a889277028

#PF: supervisor write access in kernel mode

#PF: error_code(0x0002) - not-present page

PGD afa01067 P4D afa01067 PUD 83f909067 PMD 83f8bf067 PTE 800ffffef6d88060

Oops: 0002 [#1] PREEMPT SMP DEBUG_PAGEALLOC PTI

CPU: 0 PID: 281 Comm: repro Not tainted 5.17.0-dbg-DEV #1

Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014

RIP: 0010:memset_erms+0x9/0x10

Code: c1 e9 03 40 0f b6 f6 48 b8 01 01 01 01 01 01 01 01 48 0f af c6 f3 48 ab 89 d1 f3 aa 4c 89 c8 c3 90 49 89 f9 40 88 f0 48 89 d1 <f3> aa 4c 89 c8 c3 90 49 89 fa 40 0f b6 ce 48 b8 01 01 01 01 01 01

RSP: 0018:ffffb932c09afbf0 EFLAGS: 00010246

RAX: 0000000000000000 RBX: ffffda63c4249dc0 RCX: 0000000000000fd8

RDX: 0000000000000fd8 RSI: 0000000000000000 RDI: ffffa0a889277028

RBP: ffffb932c09afc00 R08: 0000000000001000 R09: ffffa0a889277028

R10: 0000000000020023 R11: 0000000000000000 R12: ffffda63c4249dc0

R13: ffffa0a890d70d98 R14: 0000000000000028 R15: 0000000000000fd8

FS: 00007f7294899580(0000) GS:ffffa0af9bc00000(0000) knlGS:0000000000000000

CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033

CR2: ffffa0a889277028 CR3: 0000000107ef6006 CR4: 0000000000370ef0

DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000

DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400

Call Trace:

? zero_user_segments+0x82/0x190

truncate_inode_partial_folio+0xd4/0x2a0

truncate_inode_pages_range+0x380/0x830

truncate_setsize+0x63/0x80

simple_setattr+0x37/0x60

notify_change+0x3d8/0x4d0

do_sys_ftruncate+0x162/0x1d0

__x64_sys_ftruncate+0x1c/0x20

do_syscall_64+0x44/0xa0

entry_SYSCALL_64_after_hwframe+0x44/0xae

Modules linked in: xhci_pci xhci_hcd virtio_net net_failover failover virtio_blk virtio_balloon uhci_hcd ohci_pci ohci_hcd evdev ehci_pci ehci_hcd 9pnet_virtio 9p netfs 9pnet

CR2: ffffa0a889277028

[[email protected]: secretmem_iops can be static]

[[email protected]: return EINVAL]

The record
Technical detail
CVSS
Not scored
CVSS v4.0
Not supplied
EPSS
0.00258 · 16.5th percentile
Published
2025-02-26T01:54Z
EPSS history
Timeline
  • 26 FEB 01:54Z
    mm/secretmem: fix panic when growing a memfd_secret
    cvelistv5