Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Fwd: BadBunny: UFFDIO_COPY shmem killpriv bypass leading to local privilege escalation
       [not found] <CAGBKPgOm8q-8_rwyRPEmSj8JXdh_GaK1Q8vpJ=j-+yA0SgcNQw@mail.gmail.com>
@ 2026-08-07 10:40 ` vova tokarev
  2026-08-07 14:14   ` Pedro Falcato
  0 siblings, 1 reply; 9+ messages in thread
From: vova tokarev @ 2026-08-07 10:40 UTC (permalink / raw)
  To: akpm; +Cc: security, linux-mm

[-- Attachment #1: Type: text/plain, Size: 4141 bytes --]

Hi,

It's been almost two months since I sent this report, and I haven't
heard back. I'd really appreciate any feedback when you get a chance.

I've rechecked both mainline master and stable 6.12.95 -- the
vulnerability remains unfixed in both trees:

1. mm/shmem.c: shmem_mfill_atomic_pte() (6.12) / shmem_mfill_filemap_add()
   (7.x) still adds pages to the page cache without calling file_modified()
   or __remove_privs(). Writing to a SUID binary on tmpfs via UFFDIO_COPY
   preserves the setuid bit.

2. mm/userfaultfd.c: I noticed commit 85668fda932a added retry state
   tracking on master, but MFILL_RETRY_STATE_VMA_FLAGS still does not
   include VMA_WRITE_BIT -- the mprotect TOCTOU remains exploitable.

This is a deterministic local privilege escalation (no race timing
needed for the killpriv bypass), affects every kernel since 4.11
(8+ years), and works on any system with userfaultfd + tmpfs (the
default on virtually all distributions).

I have a full working PoC that gets uid=0 from uid=1000 reliably.
Happy to provide any additional information if needed.

Thanks,
Vladimir


---------- Forwarded message ---------
From: vova tokarev <vladimirelitokarev@gmail.com>
Date: Tue, Jun 16, 2026 at 12:37 PM
Subject: BadBunny: UFFDIO_COPY shmem killpriv bypass leading to local
privilege escalation
To: <security@kernel.org>


Hi,

I found a local privilege escalation (BadBunny) in the userfaultfd +
shmem subsystems that affects all Linux kernels from 4.11 to 7.1
(every major distribution: Ubuntu, Debian, Fedora, RHEL, SUSE, Arch,
Android, ChromeOS, and any system with CONFIG_USERFAULTFD=y and a
tmpfs/shmem mount).

Two bugs are chained:

1. TOCTOU in UFFDIO_COPY retry path (mm/userfaultfd.c):
   mfill_retry_state_changed() does not re-validate VM_WRITE after
   dropping and re-acquiring the mmap lock in mfill_copy_folio_retry().
   A concurrent mprotect(PROT_READ) installs a writable PTE into a
   now-read-only VMA.

2. Missing killpriv in shmem UFFDIO_COPY (mm/shmem.c):
   shmem_mfill_filemap_add() adds pages to the shmem page cache
   without calling file_modified()/killpriv. This preserves SUID/SGID
   bits when file content is replaced via UFFDIO_COPY, unlike normal
   write() which strips them.

NOTE: The killpriv bypass (Bug 2) does not require
unprivileged userfaultfd and works even with vm.unprivileged_userfaultfd=0,
since UFFDIO_COPY on shmem is available to any process that can open
a tmpfs file O_RDWR and call userfaultfd with UFFD_USER_MODE_ONLY.

An unprivileged user can replace the content of a SUID-root binary on
tmpfs via UFFDIO_COPY while preserving its setuid permission, then
execute it to obtain root.

The attack is deterministic (no timing dependency for the killpriv
bypass), requires no heap spraying, and bypasses all modern kernel
mitigations (KASLR, SMEP, SMAP, CFI, PAC, heap hardening).

Affected versions: Linux 4.11+ (since shmem UFFDIO_COPY support,
    commit 4c27fe4c4c84 "userfaultfd: shmem: add shmem_mcopy_atomic_pte")
Confirmed on: 7.1.0 (aarch64)
Affected distros: All major distributions (Ubuntu, Debian, Fedora,
    RHEL, SUSE, Arch, Android, ChromeOS) that have CONFIG_USERFAULTFD=y
    and tmpfs mounted (virtually all Linux systems)

Attached files:
  - bad_bunny.c                           Full LPE exploit (uid=1000 to
uid=0) Build: gcc -static -O2 -pthread
  - suidhelper.c                            Standalone SUID payload binary
Build: gcc -static -O2
  - uffdio_copy_lpe_report.md     Detailed writeup with root cause,
reproduction steps, and suggested fix
  - badbunny_demo.mp4             PoC demo clip

The PoC (bad_bunny.c) sets up a SUID target on tmpfs, drops to
uid=1000, uses UFFDIO_COPY to replace the binary content with
suidhelper (which does setuid(0) + execve("/bin/sh")), and executes
it to get uid=0 euid=0 gid=0 egid=0. No physical hardware needed.

Suggested fix: Add file_modified() call in shmem_mfill_filemap_add()
to strip SUID/SGID on content modification, matching the normal write
path behavior.

Thank you,
Vladimir Tokarev

[-- Attachment #2: Type: text/html, Size: 5627 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: BadBunny: UFFDIO_COPY shmem killpriv bypass leading to local privilege escalation
  2026-08-07 10:40 ` Fwd: BadBunny: UFFDIO_COPY shmem killpriv bypass leading to local privilege escalation vova tokarev
@ 2026-08-07 14:14   ` Pedro Falcato
  2026-08-08  9:13     ` vova tokarev
  0 siblings, 1 reply; 9+ messages in thread
From: Pedro Falcato @ 2026-08-07 14:14 UTC (permalink / raw)
  To: vova tokarev; +Cc: akpm, security, linux-mm

On Fri, Aug 07, 2026 at 01:40:41PM +0300, vova tokarev wrote:
> Hi,
> 
> It's been almost two months since I sent this report, and I haven't
> heard back. I'd really appreciate any feedback when you get a chance.
> 
> I've rechecked both mainline master and stable 6.12.95 -- the
> vulnerability remains unfixed in both trees:
> 
> 1. mm/shmem.c: shmem_mfill_atomic_pte() (6.12) / shmem_mfill_filemap_add()
>    (7.x) still adds pages to the page cache without calling file_modified()
>    or __remove_privs(). Writing to a SUID binary on tmpfs via UFFDIO_COPY
>    preserves the setuid bit.
> 
> 2. mm/userfaultfd.c: I noticed commit 85668fda932a added retry state
>    tracking on master, but MFILL_RETRY_STATE_VMA_FLAGS still does not
>    include VMA_WRITE_BIT -- the mprotect TOCTOU remains exploitable.
> 
> This is a deterministic local privilege escalation (no race timing
> needed for the killpriv bypass), affects every kernel since 4.11
> (8+ years), and works on any system with userfaultfd + tmpfs (the
> default on virtually all distributions).
> 
> I have a full working PoC that gets uid=0 from uid=1000 reliably.
> Happy to provide any additional information if needed.
> 
> Thanks,
> Vladimir
> 
> 
> ---------- Forwarded message ---------
> From: vova tokarev <vladimirelitokarev@gmail.com>
> Date: Tue, Jun 16, 2026 at 12:37 PM
> Subject: BadBunny: UFFDIO_COPY shmem killpriv bypass leading to local
> privilege escalation
> To: <security@kernel.org>
> 
> 
> Hi,
> 
> I found a local privilege escalation (BadBunny) in the userfaultfd +
> shmem subsystems that affects all Linux kernels from 4.11 to 7.1
> (every major distribution: Ubuntu, Debian, Fedora, RHEL, SUSE, Arch,
> Android, ChromeOS, and any system with CONFIG_USERFAULTFD=y and a
> tmpfs/shmem mount).
> 
> Two bugs are chained:
> 
> 1. TOCTOU in UFFDIO_COPY retry path (mm/userfaultfd.c):
>    mfill_retry_state_changed() does not re-validate VM_WRITE after
>    dropping and re-acquiring the mmap lock in mfill_copy_folio_retry().
>    A concurrent mprotect(PROT_READ) installs a writable PTE into a
>    now-read-only VMA.

This sounds like a bug, but not really exploitable.

> 
> 2. Missing killpriv in shmem UFFDIO_COPY (mm/shmem.c):
>    shmem_mfill_filemap_add() adds pages to the shmem page cache
>    without calling file_modified()/killpriv. This preserves SUID/SGID
>    bits when file content is replaced via UFFDIO_COPY, unlike normal
>    write() which strips them.
> 
> NOTE: The killpriv bypass (Bug 2) does not require
> unprivileged userfaultfd and works even with vm.unprivileged_userfaultfd=0,
> since UFFDIO_COPY on shmem is available to any process that can open
> a tmpfs file O_RDWR and call userfaultfd with UFFD_USER_MODE_ONLY.

Who made the suid file world-writable? Note that this is not a bug, page
fault paths don't clear the suid bit either.

> 
> An unprivileged user can replace the content of a SUID-root binary on
> tmpfs via UFFDIO_COPY while preserving its setuid permission, then
> execute it to obtain root.
> 
> The attack is deterministic (no timing dependency for the killpriv
> bypass), requires no heap spraying, and bypasses all modern kernel
> mitigations (KASLR, SMEP, SMAP, CFI, PAC, heap hardening).
> 
> Affected versions: Linux 4.11+ (since shmem UFFDIO_COPY support,
>     commit 4c27fe4c4c84 "userfaultfd: shmem: add shmem_mcopy_atomic_pte")

This sounds like a bug, but not really exploitable.
> Confirmed on: 7.1.0 (aarch64)
> Affected distros: All major distributions (Ubuntu, Debian, Fedora,
>     RHEL, SUSE, Arch, Android, ChromeOS) that have CONFIG_USERFAULTFD=y
>     and tmpfs mounted (virtually all Linux systems)
> 
> Attached files:
>   - bad_bunny.c                           Full LPE exploit (uid=1000 to
> uid=0) Build: gcc -static -O2 -pthread
>   - suidhelper.c                            Standalone SUID payload binary
> Build: gcc -static -O2
>   - uffdio_copy_lpe_report.md     Detailed writeup with root cause,
> reproduction steps, and suggested fix
>   - badbunny_demo.mp4             PoC demo clip
> 
> The PoC (bad_bunny.c) sets up a SUID target on tmpfs, drops to

Since the exploit isn't public, I assume you set up the tmpfs file as root
and world writable. This is not an LPE.


-- 
Pedro


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: BadBunny: UFFDIO_COPY shmem killpriv bypass leading to local privilege escalation
  2026-08-07 14:14   ` Pedro Falcato
@ 2026-08-08  9:13     ` vova tokarev
  2026-08-08 12:17       ` Pedro Falcato
  0 siblings, 1 reply; 9+ messages in thread
From: vova tokarev @ 2026-08-08  9:13 UTC (permalink / raw)
  To: Pedro Falcato; +Cc: akpm, security, linux-mm

[-- Attachment #1: Type: text/plain, Size: 7045 bytes --]

Pedro,

Thanks for the review. Let me address both points.

On the page fault comparison:

UFFDIO_COPY is not comparable to a page fault. Page faults serve
existing page cache content (read-like). UFFDIO_COPY adds new,

user-controlled content to the shmem page cache (write-like).

The correct comparison is to write(), which calls file_modified()

-> __remove_privs() to strip SUID/SGID.


This is exactly the reasoning used when fallocate() was fixed

across XFS (commit fbe7e5200365), ext4, and f2fs to call

file_modified(). The XFS commit message says:

"as various fallocate modes can change the file contents [...]

we should drop file privileges like suid just like we do for a

regular write()"

UFFDIO_COPY on shmem changes file contents.

It should drop file privileges like suid, just like write().


On the PoC setup and exploitability:

The PoC uses mode 04777 for simplicity of demonstration,

but the underlying bug is a killpriv invariant violation:

every VFS write path calls file_modified() to strip SUID on

content modification, but shmem_mfill_filemap_add() does not.

The killpriv mechanism is defense-in-depth - if file permissions

alone were sufficient to protect SUID, the kernel wouldn't bother

stripping SUID on write(). But it does, because writable SUID files

 do occur in practice (group-writable SUID binaries, POSIX ACLs,

 container shared mounts, chained with a separate write-access bug).


For precedent: CVE-2023-0386 (overlayfs copy-up preserving SUID

 across namespaces) is the same class of bug - a kernel code path

 that modifies or copies file content without stripping SUID -

and was scored CVSS 7.8 and added to CISA's KEV catalog.

The fallocate killpriv fixes were backported to all stable trees.


Additionally, this path is available even with

vm.unprivileged_userfaultfd=0, since UFFD_USER_MODE_ONLY

bypasses the privilege check (userfaultfd_syscall_allowed()

returns true unconditionally for USER_MODE_ONLY).

The kernel considers this path safe for unprivileged use,

yet it skips killpriv.


*On the fix:*

Regardless of how we classify severity, the fix is trivial and makes

UFFDIO_COPY consistent with every other write path -

add file_modified() to shmem_mfill_filemap_add().

I'm happy to submit a patch if you'd like.


Best regards,

Vladimir

On Fri, Aug 7, 2026 at 5:14 PM Pedro Falcato <pfalcato@suse.de> wrote:

> On Fri, Aug 07, 2026 at 01:40:41PM +0300, vova tokarev wrote:
> > Hi,
> >
> > It's been almost two months since I sent this report, and I haven't
> > heard back. I'd really appreciate any feedback when you get a chance.
> >
> > I've rechecked both mainline master and stable 6.12.95 -- the
> > vulnerability remains unfixed in both trees:
> >
> > 1. mm/shmem.c: shmem_mfill_atomic_pte() (6.12) /
> shmem_mfill_filemap_add()
> >    (7.x) still adds pages to the page cache without calling
> file_modified()
> >    or __remove_privs(). Writing to a SUID binary on tmpfs via UFFDIO_COPY
> >    preserves the setuid bit.
> >
> > 2. mm/userfaultfd.c: I noticed commit 85668fda932a added retry state
> >    tracking on master, but MFILL_RETRY_STATE_VMA_FLAGS still does not
> >    include VMA_WRITE_BIT -- the mprotect TOCTOU remains exploitable.
> >
> > This is a deterministic local privilege escalation (no race timing
> > needed for the killpriv bypass), affects every kernel since 4.11
> > (8+ years), and works on any system with userfaultfd + tmpfs (the
> > default on virtually all distributions).
> >
> > I have a full working PoC that gets uid=0 from uid=1000 reliably.
> > Happy to provide any additional information if needed.
> >
> > Thanks,
> > Vladimir
> >
> >
> > ---------- Forwarded message ---------
> > From: vova tokarev <vladimirelitokarev@gmail.com>
> > Date: Tue, Jun 16, 2026 at 12:37 PM
> > Subject: BadBunny: UFFDIO_COPY shmem killpriv bypass leading to local
> > privilege escalation
> > To: <security@kernel.org>
> >
> >
> > Hi,
> >
> > I found a local privilege escalation (BadBunny) in the userfaultfd +
> > shmem subsystems that affects all Linux kernels from 4.11 to 7.1
> > (every major distribution: Ubuntu, Debian, Fedora, RHEL, SUSE, Arch,
> > Android, ChromeOS, and any system with CONFIG_USERFAULTFD=y and a
> > tmpfs/shmem mount).
> >
> > Two bugs are chained:
> >
> > 1. TOCTOU in UFFDIO_COPY retry path (mm/userfaultfd.c):
> >    mfill_retry_state_changed() does not re-validate VM_WRITE after
> >    dropping and re-acquiring the mmap lock in mfill_copy_folio_retry().
> >    A concurrent mprotect(PROT_READ) installs a writable PTE into a
> >    now-read-only VMA.
>
> This sounds like a bug, but not really exploitable.
>
> >
> > 2. Missing killpriv in shmem UFFDIO_COPY (mm/shmem.c):
> >    shmem_mfill_filemap_add() adds pages to the shmem page cache
> >    without calling file_modified()/killpriv. This preserves SUID/SGID
> >    bits when file content is replaced via UFFDIO_COPY, unlike normal
> >    write() which strips them.
> >
> > NOTE: The killpriv bypass (Bug 2) does not require
> > unprivileged userfaultfd and works even with
> vm.unprivileged_userfaultfd=0,
> > since UFFDIO_COPY on shmem is available to any process that can open
> > a tmpfs file O_RDWR and call userfaultfd with UFFD_USER_MODE_ONLY.
>
> Who made the suid file world-writable? Note that this is not a bug, page
> fault paths don't clear the suid bit either.
>
> >
> > An unprivileged user can replace the content of a SUID-root binary on
> > tmpfs via UFFDIO_COPY while preserving its setuid permission, then
> > execute it to obtain root.
> >
> > The attack is deterministic (no timing dependency for the killpriv
> > bypass), requires no heap spraying, and bypasses all modern kernel
> > mitigations (KASLR, SMEP, SMAP, CFI, PAC, heap hardening).
> >
> > Affected versions: Linux 4.11+ (since shmem UFFDIO_COPY support,
> >     commit 4c27fe4c4c84 "userfaultfd: shmem: add shmem_mcopy_atomic_pte")
>
> This sounds like a bug, but not really exploitable.
> > Confirmed on: 7.1.0 (aarch64)
> > Affected distros: All major distributions (Ubuntu, Debian, Fedora,
> >     RHEL, SUSE, Arch, Android, ChromeOS) that have CONFIG_USERFAULTFD=y
> >     and tmpfs mounted (virtually all Linux systems)
> >
> > Attached files:
> >   - bad_bunny.c                           Full LPE exploit (uid=1000 to
> > uid=0) Build: gcc -static -O2 -pthread
> >   - suidhelper.c                            Standalone SUID payload
> binary
> > Build: gcc -static -O2
> >   - uffdio_copy_lpe_report.md     Detailed writeup with root cause,
> > reproduction steps, and suggested fix
> >   - badbunny_demo.mp4             PoC demo clip
> >
> > The PoC (bad_bunny.c) sets up a SUID target on tmpfs, drops to
>
> Since the exploit isn't public, I assume you set up the tmpfs file as root
> and world writable. This is not an LPE.
>
>
> --
> Pedro
>

[-- Attachment #2: Type: text/html, Size: 19325 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: BadBunny: UFFDIO_COPY shmem killpriv bypass leading to local privilege escalation
  2026-08-08  9:13     ` vova tokarev
@ 2026-08-08 12:17       ` Pedro Falcato
  2026-08-10  4:05         ` Matthew Wilcox
  0 siblings, 1 reply; 9+ messages in thread
From: Pedro Falcato @ 2026-08-08 12:17 UTC (permalink / raw)
  To: vova tokarev
  Cc: akpm, security, linux-mm, Alexander Viro, Christian Brauner,
	Jan Kara, Kees Cook, Matthew Wilcox, linux-fsdevel

I'm adding a bunch of fs people that might have opinions about this. Please
see the rest of the thread below.

On Sat, Aug 08, 2026 at 12:13:06PM +0300, vova tokarev wrote:
> Pedro,
> 
> Thanks for the review. Let me address both points.
> 
> On the page fault comparison:
> 
> UFFDIO_COPY is not comparable to a page fault. Page faults serve
> existing page cache content (read-like). UFFDIO_COPY adds new,

A page fault can also write to the page cache. On MAP_SHARED mappings.

> 
> user-controlled content to the shmem page cache (write-like).
> 
> The correct comparison is to write(), which calls file_modified()
> 
> -> __remove_privs() to strip SUID/SGID.
> 
> 
> This is exactly the reasoning used when fallocate() was fixed
> 
> across XFS (commit fbe7e5200365), ext4, and f2fs to call
> 
> file_modified(). The XFS commit message says:
> 
> "as various fallocate modes can change the file contents [...]
> 
> we should drop file privileges like suid just like we do for a
> 
> regular write()"

I can't speak for fallocate, or other system calls. As far as I'm aware,
this is a best-effort kind of thing. As I said, writing to a MAP_SHARED
mapping does not clear the setuid bit. It's a super trivial thing to do,
too. But it's not a problem because setuid executables are not world-writable.

I simply don't think this can feasibly be a security boundary, considering
how much it has been historically screwed up, and how the second-most basic
way to write to a file Just Bypasses It. I also don't know a single setuid
program that's packaged as 04777. Do you?

> 
> UFFDIO_COPY on shmem changes file contents.
> 
> It should drop file privileges like suid, just like write().
> 
> 
> On the PoC setup and exploitability:
> 
> The PoC uses mode 04777 for simplicity of demonstration,
> 
> but the underlying bug is a killpriv invariant violation:
> 
> every VFS write path calls file_modified() to strip SUID on
> 
> content modification, but shmem_mfill_filemap_add() does not.
> 
> The killpriv mechanism is defense-in-depth - if file permissions
> 
> alone were sufficient to protect SUID, the kernel wouldn't bother
> 
> stripping SUID on write(). But it does, because writable SUID files
> 
>  do occur in practice (group-writable SUID binaries, POSIX ACLs,
> 
>  container shared mounts, chained with a separate write-access bug).
> 
> 
> For precedent: CVE-2023-0386 (overlayfs copy-up preserving SUID
> 
>  across namespaces) is the same class of bug - a kernel code path
> 
>  that modifies or copies file content without stripping SUID -
> 
> and was scored CVSS 7.8 and added to CISA's KEV catalog.
> 
> The fallocate killpriv fixes were backported to all stable trees.
> 
> 
> Additionally, this path is available even with
> 
> vm.unprivileged_userfaultfd=0, since UFFD_USER_MODE_ONLY
> 
> bypasses the privilege check (userfaultfd_syscall_allowed()
> 
> returns true unconditionally for USER_MODE_ONLY).
> 
> The kernel considers this path safe for unprivileged use,
> 
> yet it skips killpriv.
> 
> 
> *On the fix:*
> 
> Regardless of how we classify severity, the fix is trivial and makes
> 
> UFFDIO_COPY consistent with every other write path -
> 
> add file_modified() to shmem_mfill_filemap_add().
> 
> I'm happy to submit a patch if you'd like.
> 
> 
> Best regards,
> 
> Vladimir
> 
> On Fri, Aug 7, 2026 at 5:14 PM Pedro Falcato <pfalcato@suse.de> wrote:
> 
> > On Fri, Aug 07, 2026 at 01:40:41PM +0300, vova tokarev wrote:
> > > Hi,
> > >
> > > It's been almost two months since I sent this report, and I haven't
> > > heard back. I'd really appreciate any feedback when you get a chance.
> > >
> > > I've rechecked both mainline master and stable 6.12.95 -- the
> > > vulnerability remains unfixed in both trees:
> > >
> > > 1. mm/shmem.c: shmem_mfill_atomic_pte() (6.12) /
> > shmem_mfill_filemap_add()
> > >    (7.x) still adds pages to the page cache without calling
> > file_modified()
> > >    or __remove_privs(). Writing to a SUID binary on tmpfs via UFFDIO_COPY
> > >    preserves the setuid bit.
> > >
> > > 2. mm/userfaultfd.c: I noticed commit 85668fda932a added retry state
> > >    tracking on master, but MFILL_RETRY_STATE_VMA_FLAGS still does not
> > >    include VMA_WRITE_BIT -- the mprotect TOCTOU remains exploitable.
> > >
> > > This is a deterministic local privilege escalation (no race timing
> > > needed for the killpriv bypass), affects every kernel since 4.11
> > > (8+ years), and works on any system with userfaultfd + tmpfs (the
> > > default on virtually all distributions).
> > >
> > > I have a full working PoC that gets uid=0 from uid=1000 reliably.
> > > Happy to provide any additional information if needed.
> > >
> > > Thanks,
> > > Vladimir
> > >
> > >
> > > ---------- Forwarded message ---------
> > > From: vova tokarev <vladimirelitokarev@gmail.com>
> > > Date: Tue, Jun 16, 2026 at 12:37 PM
> > > Subject: BadBunny: UFFDIO_COPY shmem killpriv bypass leading to local
> > > privilege escalation
> > > To: <security@kernel.org>
> > >
> > >
> > > Hi,
> > >
> > > I found a local privilege escalation (BadBunny) in the userfaultfd +
> > > shmem subsystems that affects all Linux kernels from 4.11 to 7.1
> > > (every major distribution: Ubuntu, Debian, Fedora, RHEL, SUSE, Arch,
> > > Android, ChromeOS, and any system with CONFIG_USERFAULTFD=y and a
> > > tmpfs/shmem mount).
> > >
> > > Two bugs are chained:
> > >
> > > 1. TOCTOU in UFFDIO_COPY retry path (mm/userfaultfd.c):
> > >    mfill_retry_state_changed() does not re-validate VM_WRITE after
> > >    dropping and re-acquiring the mmap lock in mfill_copy_folio_retry().
> > >    A concurrent mprotect(PROT_READ) installs a writable PTE into a
> > >    now-read-only VMA.
> >
> > This sounds like a bug, but not really exploitable.
> >
> > >
> > > 2. Missing killpriv in shmem UFFDIO_COPY (mm/shmem.c):
> > >    shmem_mfill_filemap_add() adds pages to the shmem page cache
> > >    without calling file_modified()/killpriv. This preserves SUID/SGID
> > >    bits when file content is replaced via UFFDIO_COPY, unlike normal
> > >    write() which strips them.
> > >
> > > NOTE: The killpriv bypass (Bug 2) does not require
> > > unprivileged userfaultfd and works even with
> > vm.unprivileged_userfaultfd=0,
> > > since UFFDIO_COPY on shmem is available to any process that can open
> > > a tmpfs file O_RDWR and call userfaultfd with UFFD_USER_MODE_ONLY.
> >
> > Who made the suid file world-writable? Note that this is not a bug, page
> > fault paths don't clear the suid bit either.
> >
> > >
> > > An unprivileged user can replace the content of a SUID-root binary on
> > > tmpfs via UFFDIO_COPY while preserving its setuid permission, then
> > > execute it to obtain root.
> > >
> > > The attack is deterministic (no timing dependency for the killpriv
> > > bypass), requires no heap spraying, and bypasses all modern kernel
> > > mitigations (KASLR, SMEP, SMAP, CFI, PAC, heap hardening).
> > >
> > > Affected versions: Linux 4.11+ (since shmem UFFDIO_COPY support,
> > >     commit 4c27fe4c4c84 "userfaultfd: shmem: add shmem_mcopy_atomic_pte")
> >
> > This sounds like a bug, but not really exploitable.
> > > Confirmed on: 7.1.0 (aarch64)
> > > Affected distros: All major distributions (Ubuntu, Debian, Fedora,
> > >     RHEL, SUSE, Arch, Android, ChromeOS) that have CONFIG_USERFAULTFD=y
> > >     and tmpfs mounted (virtually all Linux systems)
> > >
> > > Attached files:
> > >   - bad_bunny.c                           Full LPE exploit (uid=1000 to
> > > uid=0) Build: gcc -static -O2 -pthread
> > >   - suidhelper.c                            Standalone SUID payload
> > binary
> > > Build: gcc -static -O2
> > >   - uffdio_copy_lpe_report.md     Detailed writeup with root cause,
> > > reproduction steps, and suggested fix
> > >   - badbunny_demo.mp4             PoC demo clip
> > >
> > > The PoC (bad_bunny.c) sets up a SUID target on tmpfs, drops to
> >
> > Since the exploit isn't public, I assume you set up the tmpfs file as root
> > and world writable. This is not an LPE.
> >
> >
> > --
> > Pedro
> >

-- 
Pedro


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: BadBunny: UFFDIO_COPY shmem killpriv bypass leading to local privilege escalation
  2026-08-08 12:17       ` Pedro Falcato
@ 2026-08-10  4:05         ` Matthew Wilcox
  2026-08-11  9:21           ` Christian Brauner
  0 siblings, 1 reply; 9+ messages in thread
From: Matthew Wilcox @ 2026-08-10  4:05 UTC (permalink / raw)
  To: Pedro Falcato
  Cc: vova tokarev, akpm, security, linux-mm, Alexander Viro,
	Christian Brauner, Jan Kara, Kees Cook, linux-fsdevel

On Sat, Aug 08, 2026 at 01:17:09PM +0100, Pedro Falcato wrote:
> I'm adding a bunch of fs people that might have opinions about this. Please
> see the rest of the thread below.
> 
> On Sat, Aug 08, 2026 at 12:13:06PM +0300, vova tokarev wrote:
> > Pedro,
> > 
> > Thanks for the review. Let me address both points.
> > 
> > On the page fault comparison:
> > 
> > UFFDIO_COPY is not comparable to a page fault. Page faults serve
> > existing page cache content (read-like). UFFDIO_COPY adds new,
> 
> A page fault can also write to the page cache. On MAP_SHARED mappings.
> 
> > 
> > user-controlled content to the shmem page cache (write-like).
> > 
> > The correct comparison is to write(), which calls file_modified()
> > 
> > -> __remove_privs() to strip SUID/SGID.
> > 
> > 
> > This is exactly the reasoning used when fallocate() was fixed
> > 
> > across XFS (commit fbe7e5200365), ext4, and f2fs to call
> > 
> > file_modified(). The XFS commit message says:
> > 
> > "as various fallocate modes can change the file contents [...]
> > 
> > we should drop file privileges like suid just like we do for a
> > 
> > regular write()"
> 
> I can't speak for fallocate, or other system calls. As far as I'm aware,
> this is a best-effort kind of thing. As I said, writing to a MAP_SHARED
> mapping does not clear the setuid bit. It's a super trivial thing to do,
> too. But it's not a problem because setuid executables are not world-writable.

I mean, you're right.  But maybe we should make a bit more of an effort?
I wouldn't like to see this used as part of a chain of exploits, and I
can just about see a path where a confused actor manages to create an
04777 executable.

All the tmpfs on my system are mounted nosuid, and many of them noexec too:

willy@deadly:~$ mount |grep tmp |wc -l
8
willy@deadly:~$ mount |grep tmp |grep nosuid |wc -l
8
willy@deadly:~$ mount |grep tmp |grep noexec |wc -l
4

This certainly isn't a hair-on-fire situation, it's just a place we
could do slightly better.  Not so much BadBunny as MildlyMisbehavingMicrobe



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: BadBunny: UFFDIO_COPY shmem killpriv bypass leading to local privilege escalation
  2026-08-10  4:05         ` Matthew Wilcox
@ 2026-08-11  9:21           ` Christian Brauner
  2026-08-11 11:16             ` vova tokarev
  0 siblings, 1 reply; 9+ messages in thread
From: Christian Brauner @ 2026-08-11  9:21 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Pedro Falcato, vova tokarev, akpm, security, linux-mm,
	Alexander Viro, Jan Kara, Kees Cook, linux-fsdevel

On Mon, Aug 10, 2026 at 05:05:44AM +0100, Matthew Wilcox wrote:
> On Sat, Aug 08, 2026 at 01:17:09PM +0100, Pedro Falcato wrote:
> > I'm adding a bunch of fs people that might have opinions about this. Please
> > see the rest of the thread below.
> > 
> > On Sat, Aug 08, 2026 at 12:13:06PM +0300, vova tokarev wrote:
> > > Pedro,
> > > 
> > > Thanks for the review. Let me address both points.
> > > 
> > > On the page fault comparison:
> > > 
> > > UFFDIO_COPY is not comparable to a page fault. Page faults serve
> > > existing page cache content (read-like). UFFDIO_COPY adds new,
> > 
> > A page fault can also write to the page cache. On MAP_SHARED mappings.
> > 
> > > 
> > > user-controlled content to the shmem page cache (write-like).
> > > 
> > > The correct comparison is to write(), which calls file_modified()
> > > 
> > > -> __remove_privs() to strip SUID/SGID.
> > > 
> > > 
> > > This is exactly the reasoning used when fallocate() was fixed
> > > 
> > > across XFS (commit fbe7e5200365), ext4, and f2fs to call
> > > 
> > > file_modified(). The XFS commit message says:
> > > 
> > > "as various fallocate modes can change the file contents [...]
> > > 
> > > we should drop file privileges like suid just like we do for a
> > > 
> > > regular write()"
> > 
> > I can't speak for fallocate, or other system calls. As far as I'm aware,
> > this is a best-effort kind of thing. As I said, writing to a MAP_SHARED
> > mapping does not clear the setuid bit. It's a super trivial thing to do,
> > too. But it's not a problem because setuid executables are not world-writable.
> 
> I mean, you're right.  But maybe we should make a bit more of an effort?
> I wouldn't like to see this used as part of a chain of exploits, and I
> can just about see a path where a confused actor manages to create an
> 04777 executable.
> 
> All the tmpfs on my system are mounted nosuid, and many of them noexec too:
> 
> willy@deadly:~$ mount |grep tmp |wc -l
> 8
> willy@deadly:~$ mount |grep tmp |grep nosuid |wc -l
> 8
> willy@deadly:~$ mount |grep tmp |grep noexec |wc -l
> 4
> 
> This certainly isn't a hair-on-fire situation, it's just a place we
> could do slightly better.  Not so much BadBunny as MildlyMisbehavingMicrobe

Let's not drag Bad Bunny's good name into kernel development. ;)


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: BadBunny: UFFDIO_COPY shmem killpriv bypass leading to local privilege escalation
  2026-08-11  9:21           ` Christian Brauner
@ 2026-08-11 11:16             ` vova tokarev
  2026-08-11 15:56               ` Pedro Falcato
  2026-08-11 16:12               ` Lorenzo Stoakes (ARM)
  0 siblings, 2 replies; 9+ messages in thread
From: vova tokarev @ 2026-08-11 11:16 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Matthew Wilcox, Pedro Falcato, akpm, security, linux-mm,
	Alexander Viro, Jan Kara, Kees Cook, linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 3978 bytes --]

Matthew, Christian, Pedro,

Lol - fair point, I'll keep the reggaeton references out of future
commit messages.

Agreed on severity - but this is a
killpriv invariant violation, and the kernel has treated those as
security fixes worth backporting before.

1. The fallocate killpriv fixes (XFS fbe7e5200365, ext4, f2fs) are
   exact precedent: same reasoning ("can change the file contents [...]
   should drop file privileges like suid just like we do for a regular
   write()"), same one-line fix, and they went through the security fix
   process with CVE assignment and stable backports.

2. CVE-2023-0386 (overlayfs SUID preservation) -- same bug class,
   CVSS 7.8, CISA KEV.

3. If permissions alone protected SUID, write() wouldn't strip it.
   killpriv exists for POSIX ACLs granting write to non-owners,
   group-writable SUID, container shared mounts, and chaining with
   other write-access bugs.

4. This path is reachable unprivileged even with
   vm.unprivileged_userfaultfd=0 (UFFD_USER_MODE_ONLY bypasses it).

5. Pedro's point that MAP_SHARED faults also skip killpriv isn't a
   counterargument -- it's another instance of the same class. We can
   fix them independently.

Given that the fallocate killpriv fixes went through the security fix
process (CVE + stable backport), should this follow the same path?
Happy to send the patch either way.

Thanks,
Vladimir

On Tue, Aug 11, 2026 at 12:21 PM Christian Brauner <brauner@kernel.org>
wrote:

> On Mon, Aug 10, 2026 at 05:05:44AM +0100, Matthew Wilcox wrote:
> > On Sat, Aug 08, 2026 at 01:17:09PM +0100, Pedro Falcato wrote:
> > > I'm adding a bunch of fs people that might have opinions about this.
> Please
> > > see the rest of the thread below.
> > >
> > > On Sat, Aug 08, 2026 at 12:13:06PM +0300, vova tokarev wrote:
> > > > Pedro,
> > > >
> > > > Thanks for the review. Let me address both points.
> > > >
> > > > On the page fault comparison:
> > > >
> > > > UFFDIO_COPY is not comparable to a page fault. Page faults serve
> > > > existing page cache content (read-like). UFFDIO_COPY adds new,
> > >
> > > A page fault can also write to the page cache. On MAP_SHARED mappings.
> > >
> > > >
> > > > user-controlled content to the shmem page cache (write-like).
> > > >
> > > > The correct comparison is to write(), which calls file_modified()
> > > >
> > > > -> __remove_privs() to strip SUID/SGID.
> > > >
> > > >
> > > > This is exactly the reasoning used when fallocate() was fixed
> > > >
> > > > across XFS (commit fbe7e5200365), ext4, and f2fs to call
> > > >
> > > > file_modified(). The XFS commit message says:
> > > >
> > > > "as various fallocate modes can change the file contents [...]
> > > >
> > > > we should drop file privileges like suid just like we do for a
> > > >
> > > > regular write()"
> > >
> > > I can't speak for fallocate, or other system calls. As far as I'm
> aware,
> > > this is a best-effort kind of thing. As I said, writing to a MAP_SHARED
> > > mapping does not clear the setuid bit. It's a super trivial thing to
> do,
> > > too. But it's not a problem because setuid executables are not
> world-writable.
> >
> > I mean, you're right.  But maybe we should make a bit more of an effort?
> > I wouldn't like to see this used as part of a chain of exploits, and I
> > can just about see a path where a confused actor manages to create an
> > 04777 executable.
> >
> > All the tmpfs on my system are mounted nosuid, and many of them noexec
> too:
> >
> > willy@deadly:~$ mount |grep tmp |wc -l
> > 8
> > willy@deadly:~$ mount |grep tmp |grep nosuid |wc -l
> > 8
> > willy@deadly:~$ mount |grep tmp |grep noexec |wc -l
> > 4
> >
> > This certainly isn't a hair-on-fire situation, it's just a place we
> > could do slightly better.  Not so much BadBunny as
> MildlyMisbehavingMicrobe
>
> Let's not drag Bad Bunny's good name into kernel development. ;)
>

[-- Attachment #2: Type: text/html, Size: 4944 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: BadBunny: UFFDIO_COPY shmem killpriv bypass leading to local privilege escalation
  2026-08-11 11:16             ` vova tokarev
@ 2026-08-11 15:56               ` Pedro Falcato
  2026-08-11 16:12               ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 9+ messages in thread
From: Pedro Falcato @ 2026-08-11 15:56 UTC (permalink / raw)
  To: vova tokarev
  Cc: Christian Brauner, Matthew Wilcox, akpm, security, linux-mm,
	Alexander Viro, Jan Kara, Kees Cook, linux-fsdevel

On Tue, Aug 11, 2026 at 02:16:31PM +0300, vova tokarev wrote:
> Matthew, Christian, Pedro,
> 
> Lol - fair point, I'll keep the reggaeton references out of future
> commit messages.
> 
> Agreed on severity - but this is a
> killpriv invariant violation, and the kernel has treated those as
> security fixes worth backporting before.
> 
> 1. The fallocate killpriv fixes (XFS fbe7e5200365, ext4, f2fs) are
>    exact precedent: same reasoning ("can change the file contents [...]
>    should drop file privileges like suid just like we do for a regular
>    write()"), same one-line fix, and they went through the security fix
>    process with CVE assignment and stable backports.
> 
> 2. CVE-2023-0386 (overlayfs SUID preservation) -- same bug class,
>    CVSS 7.8, CISA KEV.

I don't see how this is related. It looks like an entirely different bug.

> 
> 3. If permissions alone protected SUID, write() wouldn't strip it.
>    killpriv exists for POSIX ACLs granting write to non-owners,
>    group-writable SUID, container shared mounts, and chaining with
>    other write-access bugs.
> 
> 4. This path is reachable unprivileged even with
>    vm.unprivileged_userfaultfd=0 (UFFD_USER_MODE_ONLY bypasses it).
> 
> 5. Pedro's point that MAP_SHARED faults also skip killpriv isn't a
>    counterargument -- it's another instance of the same class. We can
>    fix them independently.

Again, I don't think this is a real issue. I'm happy to be proven wrong
though. Otherwise, I don't see why we should care about this, especially
in MM. All of these helpers (file_modified(), etc) require the inode lock
which, if taken with the mmap_lock/vma lock held, will result in lock
inversion; so you need to implement awkward retry loops everywhere (pin file,
release the VMA lock/mmap lock, grab inode lock, call file_modified(),
unlock inode, retry). And I don't think you can ever specify sane semantics
for mmap (but, again, who the heck cares).

I'm sure this was all a great idea in the UNIX of old in the 1980s and 90s,
I don't think this is particularly important these days. I can theorize some
particularly weird scenarios (what if file is group-writable, but setuid (so
the owner "blessed" it); group writes, setuid should no longer bless it), but
we're much closer to a world where suid is no longer a thing, than a world
where suid (and the UNIX model for users, groups) is this important.


-- 
Pedro


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: BadBunny: UFFDIO_COPY shmem killpriv bypass leading to local privilege escalation
  2026-08-11 11:16             ` vova tokarev
  2026-08-11 15:56               ` Pedro Falcato
@ 2026-08-11 16:12               ` Lorenzo Stoakes (ARM)
  1 sibling, 0 replies; 9+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-08-11 16:12 UTC (permalink / raw)
  To: vova tokarev
  Cc: Christian Brauner, Matthew Wilcox, Pedro Falcato, akpm, security,
	linux-mm, Alexander Viro, Jan Kara, Kees Cook, linux-fsdevel

On Tue, Aug 11, 2026 at 02:16:31PM +0300, vova tokarev wrote:
> Matthew, Christian, Pedro,
>
> Lol - fair point, I'll keep the reggaeton references out of future
> commit messages.
>
> Agreed on severity - but this is a
> killpriv invariant violation, and the kernel has treated those as
> security fixes worth backporting before.
>
> 1. The fallocate killpriv fixes (XFS fbe7e5200365, ext4, f2fs) are
>    exact precedent: same reasoning ("can change the file contents [...]
>    should drop file privileges like suid just like we do for a regular
>    write()"), same one-line fix, and they went through the security fix
>    process with CVE assignment and stable backports.
>
> 2. CVE-2023-0386 (overlayfs SUID preservation) -- same bug class,
>    CVSS 7.8, CISA KEV.
>
> 3. If permissions alone protected SUID, write() wouldn't strip it.
>    killpriv exists for POSIX ACLs granting write to non-owners,
>    group-writable SUID, container shared mounts, and chaining with
>    other write-access bugs.
>
> 4. This path is reachable unprivileged even with
>    vm.unprivileged_userfaultfd=0 (UFFD_USER_MODE_ONLY bypasses it).
>
> 5. Pedro's point that MAP_SHARED faults also skip killpriv isn't a
>    counterargument -- it's another instance of the same class. We can
>    fix them independently.
>
> Given that the fallocate killpriv fixes went through the security fix
> process (CVE + stable backport), should this follow the same path?
> Happy to send the patch either way.
>
> Thanks,
> Vladimir

Please don't send what sounds exactly like an undisclosed AI-generated
'summary' type email.

https://docs.kernel.org/process/coding-assistants.html
https://docs.kernel.org/process/generated-content.html

I really wonder if this summary email trend (never ever saw it before LLMs
came into being) is just there to workslop people into providing the next
LLM prompt...

Please don't send top-posted email quoting everything below it - at least
put in the bare minimum effort required to see how kernel discussions have
functioned for the past 3+ decades.

Especially if you are looking to assign some silly name to an alleged
vulnerability.

I _hate_ how this stuff has impacted the mailing list.

--
Cheers, Lorenzo


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-08-11 16:12 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <CAGBKPgOm8q-8_rwyRPEmSj8JXdh_GaK1Q8vpJ=j-+yA0SgcNQw@mail.gmail.com>
2026-08-07 10:40 ` Fwd: BadBunny: UFFDIO_COPY shmem killpriv bypass leading to local privilege escalation vova tokarev
2026-08-07 14:14   ` Pedro Falcato
2026-08-08  9:13     ` vova tokarev
2026-08-08 12:17       ` Pedro Falcato
2026-08-10  4:05         ` Matthew Wilcox
2026-08-11  9:21           ` Christian Brauner
2026-08-11 11:16             ` vova tokarev
2026-08-11 15:56               ` Pedro Falcato
2026-08-11 16:12               ` Lorenzo Stoakes (ARM)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox