mirror of
https://github.com/torvalds/linux.git
synced 2026-09-14 16:10:02 +02:00
syscall_user_dispatch: Add kernel.syscall_user_dispatch sysctl
Add a matching sysctl to go with CONFIG_SYSCALL_USER_DISPATCH. kernel.syscall_user_dispatch (default 1 - allow) controls whether userspace may arm syscall user dispatch (both via prctl and ptrace). Disarming is always permitted - same semantics as comparable knobs. Disabling while a task has armed syscall user dispatch does not cause it to become inactive - instead it remains active until the user attempts to disable/re-enable via prctl or ptrace. On the next attempt to re-enable, the prctl/ptrace call fails gracefully. The alternative would cause programs translating non-linux syscalls to interpret those syscalls as linux syscalls, resulting in undefined userland behavior. Signed-off-by: Gregory Price <gourry@gourry.net> Signed-off-by: Thomas Gleixner <tglx@kernel.org> Link: https://patch.msgid.link/20260706140020.873735-3-gourry@gourry.net
This commit is contained in:
parent
ee935e8dc7
commit
5b6e32ba7b
|
|
@ -1402,6 +1402,23 @@ Note that if you change this from 0 to 1, already created segments
|
||||||
without users and with a dead originative process will be destroyed.
|
without users and with a dead originative process will be destroyed.
|
||||||
|
|
||||||
|
|
||||||
|
syscall_user_dispatch
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Controls whether userspace may arm Syscall User Dispatch via
|
||||||
|
``prctl(PR_SET_SYSCALL_USER_DISPATCH, ...)`` or the
|
||||||
|
``PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG`` ptrace request:
|
||||||
|
|
||||||
|
== ===================================================================
|
||||||
|
0 Arming syscall user dispatch is denied with ``-EPERM``. Tasks that
|
||||||
|
already armed it keep it, and disabling it is always permitted.
|
||||||
|
1 (default) Arming syscall user dispatch is permitted.
|
||||||
|
== ===================================================================
|
||||||
|
|
||||||
|
Only present when the kernel is built with ``CONFIG_SYSCALL_USER_DISPATCH``
|
||||||
|
and ``CONFIG_PROC_SYSCTL``.
|
||||||
|
|
||||||
|
|
||||||
sysctl_writes_strict
|
sysctl_writes_strict
|
||||||
====================
|
====================
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,21 +2,22 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 Collabora Ltd.
|
* Copyright (C) 2020 Collabora Ltd.
|
||||||
*/
|
*/
|
||||||
|
#include <linux/elf.h>
|
||||||
#include <linux/entry-common.h>
|
#include <linux/entry-common.h>
|
||||||
#include <linux/sched.h>
|
|
||||||
#include <linux/prctl.h>
|
#include <linux/prctl.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/syscall_user_dispatch.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/uaccess.h>
|
|
||||||
#include <linux/signal.h>
|
|
||||||
#include <linux/elf.h>
|
|
||||||
|
|
||||||
#include <linux/sched/signal.h>
|
#include <linux/sched/signal.h>
|
||||||
#include <linux/sched/task_stack.h>
|
#include <linux/sched/task_stack.h>
|
||||||
|
#include <linux/signal.h>
|
||||||
|
#include <linux/syscall_user_dispatch.h>
|
||||||
|
#include <linux/sysctl.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
#include <asm/syscall.h>
|
#include <asm/syscall.h>
|
||||||
|
|
||||||
|
static bool syscall_user_dispatch_allowed __read_mostly = true;
|
||||||
|
|
||||||
static void trigger_sigsys(struct pt_regs *regs)
|
static void trigger_sigsys(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct kernel_siginfo info;
|
struct kernel_siginfo info;
|
||||||
|
|
@ -102,6 +103,10 @@ static int task_set_syscall_user_dispatch(struct task_struct *task, unsigned lon
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Arming can be denied at runtime via sysctl, disarming is allowed */
|
||||||
|
if (mode != PR_SYS_DISPATCH_OFF && !syscall_user_dispatch_allowed)
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* access_ok() will clear memory tags for tagged addresses
|
* access_ok() will clear memory tags for tagged addresses
|
||||||
* if current has memory tagging enabled.
|
* if current has memory tagging enabled.
|
||||||
|
|
@ -172,3 +177,22 @@ int syscall_user_dispatch_set_config(struct task_struct *task, unsigned long siz
|
||||||
return task_set_syscall_user_dispatch(task, cfg.mode, cfg.offset, cfg.len,
|
return task_set_syscall_user_dispatch(task, cfg.mode, cfg.offset, cfg.len,
|
||||||
(char __user *)(uintptr_t)cfg.selector);
|
(char __user *)(uintptr_t)cfg.selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PROC_SYSCTL
|
||||||
|
static const struct ctl_table syscall_user_dispatch_sysctls[] = {
|
||||||
|
{
|
||||||
|
.procname = "syscall_user_dispatch",
|
||||||
|
.data = &syscall_user_dispatch_allowed,
|
||||||
|
.maxlen = sizeof(syscall_user_dispatch_allowed),
|
||||||
|
.mode = 0644,
|
||||||
|
.proc_handler = proc_dobool,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init syscall_user_dispatch_sysctl_init(void)
|
||||||
|
{
|
||||||
|
register_sysctl_init("kernel", syscall_user_dispatch_sysctls);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
late_initcall(syscall_user_dispatch_sysctl_init);
|
||||||
|
#endif /* CONFIG_PROC_SYSCTL */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user