Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions patches/process_mrelease/0001-process-mrelease-syscall.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
From 884a7e5964e06ed93c7771c0d7cf19c09a8946f1 Mon Sep 17 00:00:00 2001
From: Pulsar Bot <pulsar@localhost>
Date: Thu, 13 Aug 2026 11:00:00 +0000
Subject: [PATCH] oom: backport process_mrelease syscall (5.15)

Backport process_mrelease() from Linux 5.15 (syscall nr 448), adapted to
Pulsar's 4.19 CAF base.

The base already has pidfd_get_pid(), find_lock_task_mm(), task_will_free_mem()
and __oom_reap_task_mm(), so the backport reuses those existing primitives.
The mmap_read_lock_killable() API from newer kernels is expressed as the
4.19 equivalent down_read_killable(&mm->mmap_sem).

Also keep the MMF_OOM_SKIP recheck under mmap_sem, matching the upstream fix
for process_mrelease racing with exit_mmap().

Signed-off-by: Pulsar Bot <pulsar@localhost>
---
arch/arm64/include/asm/unistd32.h | 2 ++
include/uapi/asm-generic/unistd.h | 2 ++
mm/oom_kill.c | 48 +++++++++++++++++++++++++++++++++++++++
3 files changed, 52 insertions(+)

diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -837,6 +837,8 @@ __SYSCALL(__NR_pidfd_open, sys_pidfd_open)
__SYSCALL(__NR_process_madvise, sys_process_madvise)
#define __NR_epoll_pwait2 441
__SYSCALL(__NR_epoll_pwait2, compat_sys_epoll_pwait2)
+#define __NR_process_mrelease 448
+__SYSCALL(__NR_process_mrelease, sys_process_mrelease)
#define __NR_futex_waitv 449
__SYSCALL(__NR_futex_waitv, sys_futex_waitv)

/*
* Please add new compat syscalls above this comment and update

diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -754,6 +754,8 @@ __SYSCALL(__NR_process_madvise, sys_process_madvise)
__SC_COMP(__NR_epoll_pwait2, sys_epoll_pwait2, compat_sys_epoll_pwait2)
+#define __NR_process_mrelease 448
+__SYSCALL(__NR_process_mrelease, sys_process_mrelease)
#define __NR_futex_waitv 449
__SYSCALL(__NR_futex_waitv, sys_futex_waitv)

#undef __NR_syscalls
#define __NR_syscalls 450

diff --git a/mm/oom_kill.c b/mm/oom_kill.c
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -829,6 +829,54 @@ static bool task_will_free_mem(struct task_struct *task)

return ret;
}
+
+SYSCALL_DEFINE2(process_mrelease, int, pidfd, unsigned int, flags)
+{
+#ifdef CONFIG_MMU
+ struct mm_struct *mm = NULL;
+ struct task_struct *task;
+ struct task_struct *p;
+ unsigned int f_flags;
+ struct pid *pid;
+ bool reap = false;
+ long ret = 0;
+
+ if (flags)
+ return -EINVAL;
+
+ pid = pidfd_get_pid(pidfd, &f_flags);
+ if (IS_ERR(pid))
+ return PTR_ERR(pid);
+
+ task = get_pid_task(pid, PIDTYPE_TGID);
+ if (!task) {
+ ret = -ESRCH;
+ goto put_pid;
+ }
+
+ /* Make sure to choose a thread which still has an mm during group exit. */
+ p = find_lock_task_mm(task);
+ if (!p) {
+ ret = -ESRCH;
+ goto put_task;
+ }
+
+ mm = p->mm;
+ mmgrab(mm);
+
+ if (task_will_free_mem(p))
+ reap = true;
+ else if (!test_bit(MMF_OOM_SKIP, &mm->flags))
+ ret = -EINVAL;
+ task_unlock(p);
+
+ if (!reap)
+ goto drop_mm;
+
+ if (down_read_killable(&mm->mmap_sem)) {
+ ret = -EINTR;
+ goto drop_mm;
+ }
+
+ /* Serialize with exit_mmap() before walking mm->mmap. */
+ if (!test_bit(MMF_OOM_SKIP, &mm->flags) && !__oom_reap_task_mm(mm))
+ ret = -EAGAIN;
+ up_read(&mm->mmap_sem);
+
+drop_mm:
+ mmdrop(mm);
+put_task:
+ put_task_struct(task);
+put_pid:
+ put_pid(pid);
+ return ret;
+#else
+ return -ENOSYS;
+#endif /* CONFIG_MMU */
+}

static void __oom_kill_process(struct task_struct *victim)
{