arm64: add prctl control for resetting ptrauth keys

Add an arm64-specific prctl to allow a thread to reinitialize its
pointer authentication keys to random values. This can be useful when
exec() is not used for starting new processes, to ensure that different
processes still have different keys.

Signed-off-by: Kristina Martsenko <kristina.martsenko@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
This commit is contained in:
Kristina Martsenko
2018-12-07 18:39:28 +00:00
committed by Will Deacon
parent ccc4381082
commit ba83088565
6 changed files with 71 additions and 0 deletions

View File

@@ -58,6 +58,7 @@ arm64-obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
arm64-obj-$(CONFIG_CRASH_CORE) += crash_core.o
arm64-obj-$(CONFIG_ARM_SDE_INTERFACE) += sdei.o
arm64-obj-$(CONFIG_ARM64_SSBD) += ssbd.o
arm64-obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
obj-y += $(arm64-obj-y) vdso/ probes/
obj-m += $(arm64-obj-m)

View File

@@ -0,0 +1,47 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/errno.h>
#include <linux/prctl.h>
#include <linux/random.h>
#include <linux/sched.h>
#include <asm/cpufeature.h>
#include <asm/pointer_auth.h>
int ptrauth_prctl_reset_keys(struct task_struct *tsk, unsigned long arg)
{
struct ptrauth_keys *keys = &tsk->thread_info.keys_user;
unsigned long addr_key_mask = PR_PAC_APIAKEY | PR_PAC_APIBKEY |
PR_PAC_APDAKEY | PR_PAC_APDBKEY;
unsigned long key_mask = addr_key_mask | PR_PAC_APGAKEY;
if (!system_supports_address_auth() && !system_supports_generic_auth())
return -EINVAL;
if (!arg) {
ptrauth_keys_init(keys);
ptrauth_keys_switch(keys);
return 0;
}
if (arg & ~key_mask)
return -EINVAL;
if (((arg & addr_key_mask) && !system_supports_address_auth()) ||
((arg & PR_PAC_APGAKEY) && !system_supports_generic_auth()))
return -EINVAL;
if (arg & PR_PAC_APIAKEY)
get_random_bytes(&keys->apia, sizeof(keys->apia));
if (arg & PR_PAC_APIBKEY)
get_random_bytes(&keys->apib, sizeof(keys->apib));
if (arg & PR_PAC_APDAKEY)
get_random_bytes(&keys->apda, sizeof(keys->apda));
if (arg & PR_PAC_APDBKEY)
get_random_bytes(&keys->apdb, sizeof(keys->apdb));
if (arg & PR_PAC_APGAKEY)
get_random_bytes(&keys->apga, sizeof(keys->apga));
ptrauth_keys_switch(keys);
return 0;
}