summaryrefslogtreecommitdiff
path: root/system/easy-kernel/0250-expose-per-process-ksm.patch
diff options
context:
space:
mode:
Diffstat (limited to 'system/easy-kernel/0250-expose-per-process-ksm.patch')
-rw-r--r--system/easy-kernel/0250-expose-per-process-ksm.patch460
1 files changed, 460 insertions, 0 deletions
diff --git a/system/easy-kernel/0250-expose-per-process-ksm.patch b/system/easy-kernel/0250-expose-per-process-ksm.patch
new file mode 100644
index 000000000..0f28daca8
--- /dev/null
+++ b/system/easy-kernel/0250-expose-per-process-ksm.patch
@@ -0,0 +1,460 @@
+From: Oleksandr Natalenko <oleksandr@natalenko.name>
+Date: Mon, 8 May 2023 22:21:53 +0200
+Subject: [PATCH] mm: expose per-process KSM control via syscalls
+
+d7597f59d1d3 added a new API to enable per-process KSM control. It
+however uses prctl, which doesn't allow controlling KSM from outside of
+the current process.
+
+Hence, expose this API via 3 syscalls: process_ksm_enable,
+process_ksm_disable and process_ksm_status. Given sufficient privileges,
+auto-KSM can be enable by another process.
+
+Since these syscalls are not in the upstream kernel, also expose their
+numbers under /sys/kernel/process_ksm so that userspace tooling like
+uksmd knows how to use them.
+
+Signed-off-by: Oleksandr Natalenko <oleksandr@natalenko.name>
+---
+ arch/alpha/kernel/syscalls/syscall.tbl | 3 +
+ arch/arm/tools/syscall.tbl | 3 +
+ arch/arm64/include/asm/unistd.h | 2 +-
+ arch/arm64/include/asm/unistd32.h | 6 +
+ arch/ia64/kernel/syscalls/syscall.tbl | 3 +
+ arch/m68k/kernel/syscalls/syscall.tbl | 3 +
+ arch/microblaze/kernel/syscalls/syscall.tbl | 3 +
+ arch/mips/kernel/syscalls/syscall_n32.tbl | 3 +
+ arch/mips/kernel/syscalls/syscall_n64.tbl | 3 +
+ arch/mips/kernel/syscalls/syscall_o32.tbl | 3 +
+ arch/parisc/kernel/syscalls/syscall.tbl | 3 +
+ arch/powerpc/kernel/syscalls/syscall.tbl | 3 +
+ arch/s390/kernel/syscalls/syscall.tbl | 3 +
+ arch/sh/kernel/syscalls/syscall.tbl | 3 +
+ arch/sparc/kernel/syscalls/syscall.tbl | 3 +
+ arch/x86/entry/syscalls/syscall_32.tbl | 3 +
+ arch/x86/entry/syscalls/syscall_64.tbl | 3 +
+ arch/xtensa/kernel/syscalls/syscall.tbl | 3 +
+ include/linux/syscalls.h | 3 +
+ include/uapi/asm-generic/unistd.h | 11 +-
+ kernel/sys.c | 147 ++++++++++++++++++++
+ kernel/sys_ni.c | 3 +
+ 22 files changed, 218 insertions(+), 2 deletions(-)
+
+diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl
+index ad37569d0..9f4311e21 100644
+--- a/arch/alpha/kernel/syscalls/syscall.tbl
++++ b/arch/alpha/kernel/syscalls/syscall.tbl
+@@ -492,3 +492,6 @@
+ 560 common set_mempolicy_home_node sys_ni_syscall
+ 561 common cachestat sys_cachestat
+ 562 common fchmodat2 sys_fchmodat2
++563 common process_ksm_enable sys_process_ksm_enable
++564 common process_ksm_disable sys_process_ksm_disable
++565 common process_ksm_status sys_process_ksm_status
+diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl
+index c572d6c3d..8d40b3a45 100644
+--- a/arch/arm/tools/syscall.tbl
++++ b/arch/arm/tools/syscall.tbl
+@@ -466,3 +466,6 @@
+ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+ 451 common cachestat sys_cachestat
+ 452 common fchmodat2 sys_fchmodat2
++453 common process_ksm_enable sys_process_ksm_enable
++454 common process_ksm_disable sys_process_ksm_disable
++455 common process_ksm_status sys_process_ksm_status
+diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
+index bd77253b6..f33190f17 100644
+--- a/arch/arm64/include/asm/unistd.h
++++ b/arch/arm64/include/asm/unistd.h
+@@ -39,7 +39,7 @@
+ #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5)
+ #define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800)
+
+-#define __NR_compat_syscalls 453
++#define __NR_compat_syscalls 456
+ #endif
+
+ #define __ARCH_WANT_SYS_CLONE
+diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
+index 78b68311e..8c8b1c749 100644
+--- a/arch/arm64/include/asm/unistd32.h
++++ b/arch/arm64/include/asm/unistd32.h
+@@ -911,6 +911,12 @@ __SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node)
+ __SYSCALL(__NR_cachestat, sys_cachestat)
+ #define __NR_fchmodat2 452
+ __SYSCALL(__NR_fchmodat2, sys_fchmodat2)
++#define __NR_process_ksm_enable 453
++__SYSCALL(__NR_process_ksm_enable, sys_process_ksm_enable)
++#define __NR_process_ksm_disable 454
++__SYSCALL(__NR_process_ksm_disable, sys_process_ksm_disable)
++#define __NR_process_ksm_status 455
++__SYSCALL(__NR_process_ksm_status, sys_process_ksm_status)
+
+ /*
+ * Please add new compat syscalls above this comment and update
+diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl
+index 83d8609ae..2c370b569 100644
+--- a/arch/ia64/kernel/syscalls/syscall.tbl
++++ b/arch/ia64/kernel/syscalls/syscall.tbl
+@@ -373,3 +373,6 @@
+ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+ 451 common cachestat sys_cachestat
+ 452 common fchmodat2 sys_fchmodat2
++453 common process_ksm_enable sys_process_ksm_enable
++454 common process_ksm_disable sys_process_ksm_disable
++455 common process_ksm_status sys_process_ksm_status
+diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl
+index 259ceb125..346033761 100644
+--- a/arch/m68k/kernel/syscalls/syscall.tbl
++++ b/arch/m68k/kernel/syscalls/syscall.tbl
+@@ -452,3 +452,6 @@
+ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+ 451 common cachestat sys_cachestat
+ 452 common fchmodat2 sys_fchmodat2
++453 common process_ksm_enable sys_process_ksm_enable
++454 common process_ksm_disable sys_process_ksm_disable
++455 common process_ksm_status sys_process_ksm_status
+diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl
+index a3798c263..3d550ff34 100644
+--- a/arch/microblaze/kernel/syscalls/syscall.tbl
++++ b/arch/microblaze/kernel/syscalls/syscall.tbl
+@@ -458,3 +458,6 @@
+ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+ 451 common cachestat sys_cachestat
+ 452 common fchmodat2 sys_fchmodat2
++453 common process_ksm_enable sys_process_ksm_enable
++454 common process_ksm_disable sys_process_ksm_disable
++455 common process_ksm_status sys_process_ksm_status
+diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl
+index 152034b8e..49bedc66c 100644
+--- a/arch/mips/kernel/syscalls/syscall_n32.tbl
++++ b/arch/mips/kernel/syscalls/syscall_n32.tbl
+@@ -391,3 +391,6 @@
+ 450 n32 set_mempolicy_home_node sys_set_mempolicy_home_node
+ 451 n32 cachestat sys_cachestat
+ 452 n32 fchmodat2 sys_fchmodat2
++453 n32 process_ksm_enable sys_process_ksm_enable
++454 n32 process_ksm_disable sys_process_ksm_disable
++455 n32 process_ksm_status sys_process_ksm_status
+diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl
+index cb5e757f6..5c17a0a34 100644
+--- a/arch/mips/kernel/syscalls/syscall_n64.tbl
++++ b/arch/mips/kernel/syscalls/syscall_n64.tbl
+@@ -367,3 +367,6 @@
+ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+ 451 n64 cachestat sys_cachestat
+ 452 n64 fchmodat2 sys_fchmodat2
++453 n64 process_ksm_enable sys_process_ksm_enable
++454 n64 process_ksm_disable sys_process_ksm_disable
++455 n64 process_ksm_status sys_process_ksm_status
+diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl
+index 1a646813a..95dbd2c60 100644
+--- a/arch/mips/kernel/syscalls/syscall_o32.tbl
++++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
+@@ -440,3 +440,6 @@
+ 450 o32 set_mempolicy_home_node sys_set_mempolicy_home_node
+ 451 o32 cachestat sys_cachestat
+ 452 o32 fchmodat2 sys_fchmodat2
++453 o32 process_ksm_enable sys_process_ksm_enable
++454 o32 process_ksm_disable sys_process_ksm_disable
++455 o32 process_ksm_status sys_process_ksm_status
+diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl
+index e97c175b5..9b325ef36 100644
+--- a/arch/parisc/kernel/syscalls/syscall.tbl
++++ b/arch/parisc/kernel/syscalls/syscall.tbl
+@@ -451,3 +451,6 @@
+ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+ 451 common cachestat sys_cachestat
+ 452 common fchmodat2 sys_fchmodat2
++453 common process_ksm_enable sys_process_ksm_enable
++454 common process_ksm_disable sys_process_ksm_disable
++455 common process_ksm_status sys_process_ksm_status
+diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl
+index 20e50586e..b62ba0834 100644
+--- a/arch/powerpc/kernel/syscalls/syscall.tbl
++++ b/arch/powerpc/kernel/syscalls/syscall.tbl
+@@ -539,3 +539,6 @@
+ 450 nospu set_mempolicy_home_node sys_set_mempolicy_home_node
+ 451 common cachestat sys_cachestat
+ 452 common fchmodat2 sys_fchmodat2
++453 common process_ksm_enable sys_process_ksm_enable
++454 common process_ksm_disable sys_process_ksm_disable
++455 common process_ksm_status sys_process_ksm_status
+diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl
+index 0122cc156..70165723f 100644
+--- a/arch/s390/kernel/syscalls/syscall.tbl
++++ b/arch/s390/kernel/syscalls/syscall.tbl
+@@ -455,3 +455,6 @@
+ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node sys_set_mempolicy_home_node
+ 451 common cachestat sys_cachestat sys_cachestat
+ 452 common fchmodat2 sys_fchmodat2 sys_fchmodat2
++453 common process_ksm_enable sys_process_ksm_enable sys_process_ksm_enable
++454 common process_ksm_disable sys_process_ksm_disable sys_process_ksm_disable
++455 common process_ksm_status sys_process_ksm_status sys_process_ksm_status
+diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl
+index e90d585c4..80769b880 100644
+--- a/arch/sh/kernel/syscalls/syscall.tbl
++++ b/arch/sh/kernel/syscalls/syscall.tbl
+@@ -455,3 +455,6 @@
+ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+ 451 common cachestat sys_cachestat
+ 452 common fchmodat2 sys_fchmodat2
++453 common process_ksm_enable sys_process_ksm_enable
++454 common process_ksm_disable sys_process_ksm_disable
++455 common process_ksm_status sys_process_ksm_status
+diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl
+index 4ed06c71c..fb3514cce 100644
+--- a/arch/sparc/kernel/syscalls/syscall.tbl
++++ b/arch/sparc/kernel/syscalls/syscall.tbl
+@@ -498,3 +498,6 @@
+ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+ 451 common cachestat sys_cachestat
+ 452 common fchmodat2 sys_fchmodat2
++453 common process_ksm_enable sys_process_ksm_enable
++454 common process_ksm_disable sys_process_ksm_disable
++455 common process_ksm_status sys_process_ksm_status
+diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
+index 2d0b1bd86..80a57f6a8 100644
+--- a/arch/x86/entry/syscalls/syscall_32.tbl
++++ b/arch/x86/entry/syscalls/syscall_32.tbl
+@@ -457,3 +457,6 @@
+ 450 i386 set_mempolicy_home_node sys_set_mempolicy_home_node
+ 451 i386 cachestat sys_cachestat
+ 452 i386 fchmodat2 sys_fchmodat2
++453 i386 process_ksm_enable sys_process_ksm_enable
++454 i386 process_ksm_disable sys_process_ksm_disable
++455 i386 process_ksm_status sys_process_ksm_status
+diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
+index 1d6eee30e..38faca76e 100644
+--- a/arch/x86/entry/syscalls/syscall_64.tbl
++++ b/arch/x86/entry/syscalls/syscall_64.tbl
+@@ -375,6 +375,9 @@
+ 451 common cachestat sys_cachestat
+ 452 common fchmodat2 sys_fchmodat2
+ 453 64 map_shadow_stack sys_map_shadow_stack
++454 common process_ksm_enable sys_process_ksm_enable
++455 common process_ksm_disable sys_process_ksm_disable
++456 common process_ksm_status sys_process_ksm_status
+
+ #
+ # Due to a historical design error, certain syscalls are numbered differently
+diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl
+index fc1a4f3c8..83f5032b2 100644
+--- a/arch/xtensa/kernel/syscalls/syscall.tbl
++++ b/arch/xtensa/kernel/syscalls/syscall.tbl
+@@ -423,3 +423,6 @@
+ 450 common set_mempolicy_home_node sys_set_mempolicy_home_node
+ 451 common cachestat sys_cachestat
+ 452 common fchmodat2 sys_fchmodat2
++453 common process_ksm_enable sys_process_ksm_enable
++454 common process_ksm_disable sys_process_ksm_disable
++455 common process_ksm_status sys_process_ksm_status
+diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
+index 22bc6bc14..da013ad43 100644
+--- a/include/linux/syscalls.h
++++ b/include/linux/syscalls.h
+@@ -799,6 +799,9 @@ asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior);
+ asmlinkage long sys_process_madvise(int pidfd, const struct iovec __user *vec,
+ size_t vlen, int behavior, unsigned int flags);
+ asmlinkage long sys_process_mrelease(int pidfd, unsigned int flags);
++asmlinkage long sys_process_ksm_enable(int pidfd, unsigned int flags);
++asmlinkage long sys_process_ksm_disable(int pidfd, unsigned int flags);
++asmlinkage long sys_process_ksm_status(int pidfd, unsigned int flags);
+ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
+ unsigned long prot, unsigned long pgoff,
+ unsigned long flags);
+diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
+index abe087c53..e393422e2 100644
+--- a/include/uapi/asm-generic/unistd.h
++++ b/include/uapi/asm-generic/unistd.h
+@@ -823,8 +823,17 @@ __SYSCALL(__NR_cachestat, sys_cachestat)
+ #define __NR_fchmodat2 452
+ __SYSCALL(__NR_fchmodat2, sys_fchmodat2)
+
++#define __NR_process_ksm_enable 453
++__SYSCALL(__NR_process_ksm_enable, sys_process_ksm_enable)
++
++#define __NR_process_ksm_disable 454
++__SYSCALL(__NR_process_ksm_disable, sys_process_ksm_disable)
++
++#define __NR_process_ksm_status 455
++__SYSCALL(__NR_process_ksm_status, sys_process_ksm_status)
++
+ #undef __NR_syscalls
+-#define __NR_syscalls 453
++#define __NR_syscalls 456
+
+ /*
+ * 32 bit systems traditionally used different
+diff --git a/kernel/sys.c b/kernel/sys.c
+index 2410e3999..b0841a2dd 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -2727,6 +2727,153 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
+ return error;
+ }
+
++#ifdef CONFIG_KSM
++enum pkc_action {
++ PKSM_ENABLE = 0,
++ PKSM_DISABLE,
++ PKSM_STATUS,
++};
++
++static long do_process_ksm_control(int pidfd, enum pkc_action action)
++{
++ long ret;
++ struct pid *pid;
++ struct task_struct *task;
++ struct mm_struct *mm;
++ unsigned int f_flags;
++
++ pid = pidfd_get_pid(pidfd, &f_flags);
++ if (IS_ERR(pid)) {
++ ret = PTR_ERR(pid);
++ goto out;
++ }
++
++ task = get_pid_task(pid, PIDTYPE_PID);
++ if (!task) {
++ ret = -ESRCH;
++ goto put_pid;
++ }
++
++ /* Require PTRACE_MODE_READ to avoid leaking ASLR metadata. */
++ mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
++ if (IS_ERR_OR_NULL(mm)) {
++ ret = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH;
++ goto release_task;
++ }
++
++ /* Require CAP_SYS_NICE for influencing process performance. */
++ if (!capable(CAP_SYS_NICE)) {
++ ret = -EPERM;
++ goto release_mm;
++ }
++
++ if (mmap_write_lock_killable(mm)) {
++ ret = -EINTR;
++ goto release_mm;
++ }
++
++ switch (action) {
++ case PKSM_ENABLE:
++ ret = ksm_enable_merge_any(mm);
++ break;
++ case PKSM_DISABLE:
++ ret = ksm_disable_merge_any(mm);
++ break;
++ case PKSM_STATUS:
++ ret = !!test_bit(MMF_VM_MERGE_ANY, &mm->flags);
++ break;
++ }
++
++ mmap_write_unlock(mm);
++
++release_mm:
++ mmput(mm);
++release_task:
++ put_task_struct(task);
++put_pid:
++ put_pid(pid);
++out:
++ return ret;
++}
++#endif /* CONFIG_KSM */
++
++SYSCALL_DEFINE2(process_ksm_enable, int, pidfd, unsigned int, flags)
++{
++#ifdef CONFIG_KSM
++ if (flags != 0)
++ return -EINVAL;
++
++ return do_process_ksm_control(pidfd, PKSM_ENABLE);
++#else /* CONFIG_KSM */
++ return -ENOSYS;
++#endif /* CONFIG_KSM */
++}
++
++SYSCALL_DEFINE2(process_ksm_disable, int, pidfd, unsigned int, flags)
++{
++#ifdef CONFIG_KSM
++ if (flags != 0)
++ return -EINVAL;
++
++ return do_process_ksm_control(pidfd, PKSM_DISABLE);
++#else /* CONFIG_KSM */
++ return -ENOSYS;
++#endif /* CONFIG_KSM */
++}
++
++SYSCALL_DEFINE2(process_ksm_status, int, pidfd, unsigned int, flags)
++{
++#ifdef CONFIG_KSM
++ if (flags != 0)
++ return -EINVAL;
++
++ return do_process_ksm_control(pidfd, PKSM_STATUS);
++#else /* CONFIG_KSM */
++ return -ENOSYS;
++#endif /* CONFIG_KSM */
++}
++
++#ifdef CONFIG_KSM
++static ssize_t process_ksm_enable_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ return sprintf(buf, "%u\n", __NR_process_ksm_enable);
++}
++static struct kobj_attribute process_ksm_enable_attr = __ATTR_RO(process_ksm_enable);
++
++static ssize_t process_ksm_disable_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ return sprintf(buf, "%u\n", __NR_process_ksm_disable);
++}
++static struct kobj_attribute process_ksm_disable_attr = __ATTR_RO(process_ksm_disable);
++
++static ssize_t process_ksm_status_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ return sprintf(buf, "%u\n", __NR_process_ksm_status);
++}
++static struct kobj_attribute process_ksm_status_attr = __ATTR_RO(process_ksm_status);
++
++static struct attribute *process_ksm_sysfs_attrs[] = {
++ &process_ksm_enable_attr.attr,
++ &process_ksm_disable_attr.attr,
++ &process_ksm_status_attr.attr,
++ NULL,
++};
++
++static const struct attribute_group process_ksm_sysfs_attr_group = {
++ .attrs = process_ksm_sysfs_attrs,
++ .name = "process_ksm",
++};
++
++static int __init process_ksm_sysfs_init(void)
++{
++ return sysfs_create_group(kernel_kobj, &process_ksm_sysfs_attr_group);
++}
++subsys_initcall(process_ksm_sysfs_init);
++#endif /* CONFIG_KSM */
++
+ SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,
+ struct getcpu_cache __user *, unused)
+ {
+diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
+index e137c1385..2d9772d11 100644
+--- a/kernel/sys_ni.c
++++ b/kernel/sys_ni.c
+@@ -184,6 +184,9 @@ COND_SYSCALL(mincore);
+ COND_SYSCALL(madvise);
+ COND_SYSCALL(process_madvise);
+ COND_SYSCALL(process_mrelease);
++COND_SYSCALL(process_ksm_enable);
++COND_SYSCALL(process_ksm_disable);
++COND_SYSCALL(process_ksm_status);
+ COND_SYSCALL(remap_file_pages);
+ COND_SYSCALL(mbind);
+ COND_SYSCALL(get_mempolicy);