arm64: Introduce prctl() options to control the tagged user addresses ABI
It is not desirable to relax the ABI to allow tagged user addresses into the kernel indiscriminately. This patch introduces a prctl() interface for enabling or disabling the tagged ABI with a global sysctl control for preventing applications from enabling the relaxed ABI (meant for testing user-space prctl() return error checking without reconfiguring the kernel). The ABI properties are inherited by threads of the same application and fork()'ed children but cleared on execve(). A Kconfig option allows the overall disabling of the relaxed ABI. The PR_SET_TAGGED_ADDR_CTRL will be expanded in the future to handle MTE-specific settings like imprecise vs precise exceptions. Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Andrey Konovalov <andreyknvl@google.com> Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:

committed by
Will Deacon

vanhempi
2b835e24b5
commit
63f0c60379
@@ -19,6 +19,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/user.h>
|
||||
#include <linux/delay.h>
|
||||
@@ -38,6 +39,7 @@
|
||||
#include <trace/events/power.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/thread_info.h>
|
||||
#include <linux/prctl.h>
|
||||
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/arch_gicv3.h>
|
||||
@@ -307,11 +309,18 @@ static void tls_thread_flush(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void flush_tagged_addr_state(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_ARM64_TAGGED_ADDR_ABI))
|
||||
clear_thread_flag(TIF_TAGGED_ADDR);
|
||||
}
|
||||
|
||||
void flush_thread(void)
|
||||
{
|
||||
fpsimd_flush_thread();
|
||||
tls_thread_flush();
|
||||
flush_ptrace_hw_breakpoint(current);
|
||||
flush_tagged_addr_state();
|
||||
}
|
||||
|
||||
void release_thread(struct task_struct *dead_task)
|
||||
@@ -565,3 +574,67 @@ void arch_setup_new_exec(void)
|
||||
|
||||
ptrauth_thread_init_user(current);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64_TAGGED_ADDR_ABI
|
||||
/*
|
||||
* Control the relaxed ABI allowing tagged user addresses into the kernel.
|
||||
*/
|
||||
static unsigned int tagged_addr_prctl_allowed = 1;
|
||||
|
||||
long set_tagged_addr_ctrl(unsigned long arg)
|
||||
{
|
||||
if (!tagged_addr_prctl_allowed)
|
||||
return -EINVAL;
|
||||
if (is_compat_task())
|
||||
return -EINVAL;
|
||||
if (arg & ~PR_TAGGED_ADDR_ENABLE)
|
||||
return -EINVAL;
|
||||
|
||||
update_thread_flag(TIF_TAGGED_ADDR, arg & PR_TAGGED_ADDR_ENABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long get_tagged_addr_ctrl(void)
|
||||
{
|
||||
if (!tagged_addr_prctl_allowed)
|
||||
return -EINVAL;
|
||||
if (is_compat_task())
|
||||
return -EINVAL;
|
||||
|
||||
if (test_thread_flag(TIF_TAGGED_ADDR))
|
||||
return PR_TAGGED_ADDR_ENABLE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Global sysctl to disable the tagged user addresses support. This control
|
||||
* only prevents the tagged address ABI enabling via prctl() and does not
|
||||
* disable it for tasks that already opted in to the relaxed ABI.
|
||||
*/
|
||||
static int zero;
|
||||
static int one = 1;
|
||||
|
||||
static struct ctl_table tagged_addr_sysctl_table[] = {
|
||||
{
|
||||
.procname = "tagged_addr",
|
||||
.mode = 0644,
|
||||
.data = &tagged_addr_prctl_allowed,
|
||||
.maxlen = sizeof(int),
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = &zero,
|
||||
.extra2 = &one,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static int __init tagged_addr_init(void)
|
||||
{
|
||||
if (!register_sysctl("abi", tagged_addr_sysctl_table))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
core_initcall(tagged_addr_init);
|
||||
#endif /* CONFIG_ARM64_TAGGED_ADDR_ABI */
|
||||
|
Viittaa uudesa ongelmassa
Block a user