diff --git a/patches/process_mrelease/0001-process-mrelease-syscall.patch b/patches/process_mrelease/0001-process-mrelease-syscall.patch new file mode 100644 index 0000000..c82fec1 --- /dev/null +++ b/patches/process_mrelease/0001-process-mrelease-syscall.patch @@ -0,0 +1,126 @@ +From 884a7e5964e06ed93c7771c0d7cf19c09a8946f1 Mon Sep 17 00:00:00 2001 +From: Pulsar Bot +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 +--- + 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) + {