feat: Support PAC(Pointer Authentication Code) for linux kernel

Signed-off-by: Haryslee <lihao189@huawei.com>
This commit is contained in:
Haryslee
2024-01-15 20:48:21 +08:00
parent 142c86dd17
commit 4aecc74281
18 changed files with 1094 additions and 0 deletions
+1
View File
@@ -8,5 +8,6 @@
./code_sign
./container_escape_detection
./module_sample
./pac/
As for the specific use of the licenses, please refer to the relevant description in the documents.
+3
View File
@@ -66,6 +66,7 @@ Note:If the text contains special characters, please escape them according to th
<policyitem type="compatibility" name="GPL" path="container_escape_detection/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="compatibility" name="GPL" path="tzdriver/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="compatibility" name="GPL" path="module_sample/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="compatibility" name="GPL" path="pac/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="license" name="GPL" path="newip/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="license" name="GPL" path="xpm/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
@@ -75,6 +76,7 @@ Note:If the text contains special characters, please escape them according to th
<policyitem type="license" name="GPL" path="code_sign/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="license" name="GPL" path="container_escape_detection/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="license" name="GPL" path="module_sample/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="license" name="GPL" path="tzdriver/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="license" name="GPL" path="pac/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="copyright" name="Huawei Technologies Co." path="tzdriver/.*" rule="may" group="defaultGroup" filefilter="copyrightPolicyFilter" desc="Copyright information"/>
@@ -97,6 +99,7 @@ Note:If the text contains special characters, please escape them according to th
<filteritem type="filepath" name="newip/figures/.*"/>
<filteritem type="filepath" name="xpm/figures/.*"/>
<filteritem type="filepath" name="qos_auth/figures/.*"/>
<filteritem type="filepath" name="ucollection/figures/.*"/>
<filteritem type="filepath" name="tzdriver/figures/.*"/>
<filteritem type="filepath" name="pac/figures/.*"/>
Executable
+12
View File
@@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright (c) 2023 Huawei Device Co., Ltd.
#
# Makefile for the Linux PAC module.
#
obj-$(CONFIG_ARM64_PTR_AUTH_EXT) += src/pointer_auth_key.o
obj-$(CONFIG_ARM64_PTR_AUTH_EXT) += src/asm_pointer_auth_key.o
obj-$(CONFIG_ARM64_PTR_AUTH_DATA_FIELD) += src/pointer_auth_context.o
obj-$(CONFIG_ARM64_PTR_AUTH_DATA_FIELD) += src/asm_pointer_auth_context.o
obj-$(CONFIG_CONSTRUCTORS) += src/asm_pointer_auth_constructors.o
+67
View File
@@ -0,0 +1,67 @@
## 背景
现阶段,内存安全漏洞是对计算机系统安全最严重的威胁。从漏洞利用的角度分析,借助常见的攻击手段,包括利用缓冲区溢出等实现JOP/ROP攻击,攻击者可以实现控制流劫持,最终导致任意代码执行,这严重摧毁了一个系统的安全性。另一方面,在攻击者利用内存漏洞做提权的过程中,通常会修改指向关键数据(如Cred)的数据指针,这类攻击被归纳为DOP攻击,同样会对系统安全产生严重威胁。
因此,系统需要高效的漏洞防利用机制,以保护系统的控制流完整性和数据流完整性,这对于提升系统的安全竞争力具有重要意义。当前,从安全性角度,对于系统安全主流的JOP/ROP/DOP攻击,PAC机制均能实现有效防护。
## PACPointer Authentication Code)模块
PAC模块利用ARMv8.3-a架构提供的PAC特性,基于linux内核提供PAC相关的特性支持,包括密钥管理、数据和指针签名验签,以及任务切换上下文、异常中断上下文的PAC保护机制。PAC主要功能实现如下:
### 1.密钥管理
ARMv8.3-a指令集引入了硬件安全特性PAC,用于保护内存中指针和其他数据的完整性。原理是:ARM硬件基于QARMA密码算法,将被保护的指针或数据、用于签名的密钥和盐值作为输入,计算输出一个MAC值,对于指针来说,将有效的MAC值存放在指针的未使用高位,对于数据来说,需要另开辟内存用于保存MAC值。
<img src="./figures/pac.png" width=600 alt="PAC原理"/>
Linux内核的密钥管理分为用户态密钥和内核态密钥,示意图如下:
![密钥管理](figures/key.png)
### 2.关键数据和指针保护
Linux内核可以利用PAC模块对任务切换上下文、异常中断上下文中的关键字段进行保护,防止在上下文切换的过程中,攻击者利用内存漏洞提权修改关键字段,最终导致任意代码执行。
![linux context保护](figures/pac_context.png)
## 目录
PAC主要代码目录结构如下:
```
# 代码路径 /kernel/linux/common_modules/pac
├── config # 关键数据、指针标记配置文件
├── figures # ReadMe 内嵌图例
├── include # PAC头文件
├── src # PAC代码
└── Makefile
```
## 配置指导
1. PAC使能
`CONFIG_ARM64_PTR_AUTH=y`
2. 密钥使能
`CONFIG_ARM64_PTR_AUTH_EXT=y`
3. 关键数据和指针保护使能
`CONFIG_ARM64_PTR_AUTH_DATA_PTR=y`
`CONFIG_ARM64_PTR_AUTH_DATA_FIELD=y`
4. 前向CFI使能
`CONFIG_ARM64_PTR_AUTH_FWD_CFI=y`
## 相关仓
[内核子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/%E5%86%85%E6%A0%B8%E5%AD%90%E7%B3%BB%E7%BB%9F.md)
[kernel_linux_5.10](https://gitee.com/openharmony/kernel_linux_5.10)
[kernel_linux_config](https://gitee.com/openharmony/kernel_linux_config)
[kernel_linux_build](https://gitee.com/openharmony/kernel_linux_build)
+41
View File
@@ -0,0 +1,41 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2023 Huawei Device Co., Ltd.
#
set -e
OHOS_SOURCE_ROOT=$1
KERNEL_BUILD_ROOT=$2
PRODUCT_NAME=$3
KERNEL_VERSION=$4
PAC_SOURCE_ROOT=$OHOS_SOURCE_ROOT/kernel/linux/common_modules/pac
function main()
{
pushd .
if [ ! -d " $KERNEL_BUILD_ROOT/arch/arm64/pac/src" ]; then
mkdir -p $KERNEL_BUILD_ROOT/arch/arm64/pac/src
fi
if [ ! -d " $KERNEL_BUILD_ROOT/arch/arm64/pac/config" ]; then
mkdir -p $KERNEL_BUILD_ROOT/arch/arm64/pac/config
fi
cd $KERNEL_BUILD_ROOT/arch/arm64/pac
ln -s -f $(realpath --relative-to=$KERNEL_BUILD_ROOT/arch/arm64/pac $PAC_SOURCE_ROOT)/Makefile ./Makefile
cd $KERNEL_BUILD_ROOT/arch/arm64/pac/config
ln -s -f $(realpath --relative-to=$KERNEL_BUILD_ROOT/arch/arm64/pac/config $PAC_SOURCE_ROOT/config)/config.txt ./config.txt
cd $KERNEL_BUILD_ROOT/arch/arm64/pac/src
ln -s -f $(realpath --relative-to=$KERNEL_BUILD_ROOT/arch/arm64/pac/src $PAC_SOURCE_ROOT/src)/* ./
cd $KERNEL_BUILD_ROOT/arch/arm64/include/asm
ln -s -f $(realpath --relative-to=$KERNEL_BUILD_ROOT/arch/arm64/include/asm $PAC_SOURCE_ROOT/include)/* ./
popd
}
main
+56
View File
@@ -0,0 +1,56 @@
struct.task_struct mm
struct.task_struct real_parent
struct.task_struct sched_task_group
struct.task_struct files
struct.task_struct nsproxy
struct.task_struct ptracer_cred
struct.task_struct real_cred
struct.task_struct cred
struct.task_struct security
struct.task_struct splice_pipe
struct.task_struct fs
struct.cred session_keyring
struct.cred process_keyring
struct.cred thread_keyring
struct.cred request_key_auth
struct.cred security
struct.cred user
struct.cred user_ns
struct.cred group_info
struct.super_block s_root
struct.super_block s_xattr
struct.super_block s_d_op
struct.super_block s_vop
struct.super_block s_security
struct.mount mnt_parent
struct.mount mnt_mountpoint
struct.mount mnt_mp
struct.vfsmount mnt_root
struct.vfsmount mnt_sb
struct.inode i_op
struct.inode i_sb
struct.inode i_verity_info
struct.inode i_security
struct.inode i_mapping
struct.dentry d_parent
struct.dentry d_inode
struct.dentry d_op
struct.dentry d_sb
struct.selinux_state status_page
struct.selinux_state avc
struct.selinux_state policy
struct.avc_entry xp_node
struct.shmid_kernel shm_file
struct.file f_security
struct.msg_msg security
struct.kern_ipc_perm security
struct.lsm_info blobs
struct.sock_fprog filter
struct.nsproxy mnt_ns
struct.nsproxy pid_ns_for_children
struct.nsproxy net_ns
struct.nsproxy uts_ns
struct.nsproxy ipc_ns
struct.nsproxy time_ns
struct.nsproxy time_ns_for_children
struct.nsproxy cgroup_ns
View File
View File
View File
+172
View File
@@ -0,0 +1,172 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#ifndef __ASM_POINTER_AUTH_CONTEXT_H
#define __ASM_POINTER_AUTH_CONTEXT_H
#include <asm/asm-offsets.h>
#include <asm/sysreg.h>
/* Compute and store hash value of cpu context. */
.macro sign_thread_context_common, tmp1=x0, tmp2=x1, tmp3=x2
pacga \tmp2, \tmp1, \tmp2
pacga \tmp2, \tmp3, \tmp2
str \tmp2, [\tmp1, CPU_CONTEXT_PAC_HASH]
.endm
/* Compute and auth hash value of cpu context. */
.macro auth_thread_context_common, tmp1=x0, tmp2=x1, tmp3=x2
pacga \tmp2, \tmp1, \tmp2
pacga \tmp2, \tmp3, \tmp2
ldr \tmp3, [\tmp1, CPU_CONTEXT_PAC_HASH]
cmp \tmp2, \tmp3
b.ne .Lthread_context_pac_panic\@
b .Lauth_thread_context_done\@
.Lthread_context_pac_panic\@:
adrp x0, .Lthread_context_pac_str
add x0, x0, :lo12:.Lthread_context_pac_str
bl panic
.Lauth_thread_context_done\@:
.endm
/* Compute and store hash value of the regs. */
.macro sign_exception_context_common, tmp1=x0, tmp2=x1, tmp3=x2, tmp4=x3, tmp5=x4, tmp6=x5, tmp7=x6
pacga \tmp2, \tmp1, \tmp2
pacga \tmp2, \tmp3, \tmp2
pacga \tmp2, \tmp4, \tmp2
pacga \tmp2, \tmp5, \tmp2
pacga \tmp2, \tmp6, \tmp2
pacga \tmp2, \tmp7, \tmp2
str \tmp2, [\tmp1, S_PAC_HASH]
.endm
/* Compute and auth hash value of the regs. */
.macro auth_exception_context_common, tmp1=x0, tmp2=x1, tmp3=x2, tmp4=x3, tmp5=x4, tmp6=x5, tmp7=x6
pacga \tmp2, \tmp1, \tmp2
pacga \tmp2, \tmp3, \tmp2
pacga \tmp2, \tmp4, \tmp2
pacga \tmp2, \tmp5, \tmp2
pacga \tmp2, \tmp6, \tmp2
pacga \tmp2, \tmp7, \tmp2
ldr \tmp3, [\tmp1, S_PAC_HASH]
cmp \tmp2, \tmp3
b.ne .Lpt_regs_pac_panic\@
b .Lauth_exception_context_done\@
.Lpt_regs_pac_panic\@:
adrp x0, .Lpt_regs_pac_panic_str
add x0, x0, :lo12:.Lpt_regs_pac_panic_str
bl panic
.Lauth_exception_context_done\@:
.endm
.Lpt_regs_pac_panic_str:
.asciz "Failed to match pac hash of exception context!\n"
.align 2
.Lthread_context_pac_str:
.asciz "Failed to match pac hash of cpu context!\n"
.align 2
.macro pac_cpu_context sign_or_auth
.if \sign_or_auth == 0
/* x0: base of curr task */
mov x2, x0
.else
/* x1: base of next task */
mov x2, x1
.endif
add x2, x2, #THREAD_CPU_CONTEXT
/* sign sp, lr of cpu context. */
mov x3, lr
mov x4, x9
.if \sign_or_auth == 0
sign_thread_context_common x2, x3, x4
.else
auth_thread_context_common x2, x3, x4
.endif
.endm
.macro sign_cpu_context sign=0
pac_cpu_context \sign
.endm
.macro auth_cpu_context auth=1
pac_cpu_context \auth
.endm
.macro prepare_compat_pt_regs, sign_or_auth
/* base of pt_regs */
mov x23, sp
mov x24, #0
mov x25, #0
/* sign lr, sp, pc, pstate of compat task */
mov x26, x14
mov x27, x13
mrs x20, elr_el1
.if \sign_or_auth == 0
mrs x21, spsr_el1
.else
mov x21, x22
.endif
.endm
.macro prepare_pt_regs, el, sign_or_auth
/* base of pt_regs */
mov x23, sp
/* sign x16, x17, lr, sp, pc, pstate of task */
mov x24, x16
mov x25, x17
.if \sign_or_auth == 0
mov x26, lr
.else
ldr x26, [x23, #S_LR]
.endif
.if \el == 0
mrs x27, sp_el0
.else
add x27, x23, #S_FRAME_SIZE
.endif
mrs x20, elr_el1
.if \sign_or_auth == 0
mrs x21, spsr_el1
.else
mov x21, x22
.endif
.endm
.macro pac_pt_regs, el, sign_or_auth
.if \el == 0
/* Test the task is in the mode of 32-bit or 64-bit */
mrs x23, spsr_el1
mov x24, #(PSR_MODE32_BIT | PSR_MODE_MASK)
mov x25, #(PSR_MODE32_BIT | PSR_MODE_EL0t)
and x23, x23, x24
sub x23, x23, x25
cbnz x23, .Lis_not_compat_task\@
/* Task in 32-bit mode */
prepare_compat_pt_regs \sign_or_auth
b .Lpac_handle\@
.endif
/* Task in 64-bit mode */
.Lis_not_compat_task\@:
prepare_pt_regs \el, \sign_or_auth
/* Call the sign or auth function. */
.Lpac_handle\@:
.if \sign_or_auth == 0
sign_exception_context_common x23, x24, x25, x26, x27, x20, x21
.else
auth_exception_context_common x23, x24, x25, x26, x27, x20, x21
.endif
.endm
.macro sign_pt_regs, el, sign=0
pac_pt_regs \el, \sign
.endm
.macro auth_pt_regs, el, auth=1
pac_pt_regs \el, \auth
.endm
#endif /* __ASM_POINTER_AUTH_CONTEXT_H */
+64
View File
@@ -0,0 +1,64 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*
* Pointer authentication keys initialisation.
*/
#ifndef __ASM_POINTER_AUTH_KEY_H
#define __ASM_POINTER_AUTH_KEY_H
#include <asm/alternative.h>
#include <asm/asm-offsets.h>
#include <asm/cpucaps.h>
#include <asm/sysreg.h>
.macro __ptrauth_address_keys_install_kernel tmp1, tmp2, tmp3
ldp \tmp2, \tmp3, [\tmp1, #PTRAUTH_KERNEL_KEY_APIB]
msr_s SYS_APIBKEYLO_EL1, \tmp2
msr_s SYS_APIBKEYHI_EL1, \tmp3
adr_l \tmp1, kernel_common_keys
ldp \tmp2, \tmp3, [\tmp1, #PTRAUTH_KERNEL_KEY_APIA]
msr_s SYS_APIAKEYLO_EL1, \tmp2
msr_s SYS_APIAKEYHI_EL1, \tmp3
ldp \tmp2, \tmp3, [\tmp1, #PTRAUTH_KERNEL_KEY_APDA]
msr_s SYS_APDAKEYLO_EL1, \tmp2
msr_s SYS_APDAKEYHI_EL1, \tmp3
ldp \tmp2, \tmp3, [\tmp1, #PTRAUTH_KERNEL_KEY_APDB]
msr_s SYS_APDBKEYLO_EL1, \tmp2
msr_s SYS_APDBKEYHI_EL1, \tmp3
.endm
.macro __ptrauth_generic_key_install_kernel tmp1, tmp2, tmp3
ldp \tmp2, \tmp3, [\tmp1, #PTRAUTH_KERNEL_KEY_APGA]
msr_s SYS_APGAKEYLO_EL1, \tmp2
msr_s SYS_APGAKEYHI_EL1, \tmp3
.endm
.macro ptrauth_keys_install_kernel_all tsk, tmp1, tmp2, tmp3
mov \tmp1, #THREAD_KEYS_KERNEL
add \tmp1, \tsk, \tmp1
alternative_if_not ARM64_HAS_ADDRESS_AUTH
b .Lno_addr_auth\@
alternative_else_nop_endif
__ptrauth_address_keys_install_kernel \tmp1, \tmp2, \tmp3
.Lno_addr_auth\@:
alternative_if ARM64_HAS_GENERIC_AUTH
__ptrauth_generic_key_install_kernel \tmp1, \tmp2, \tmp3
alternative_else_nop_endif
isb
.endm
.macro __ptrauth_keys_install_kernel_all tsk, tmp1, tmp2, tmp3
mov \tmp1, #THREAD_KEYS_KERNEL
add \tmp1, \tsk, \tmp1
__ptrauth_address_keys_install_kernel \tmp1, \tmp2, \tmp3
__ptrauth_generic_key_install_kernel \tmp1, \tmp2, \tmp3
.endm
#endif
+88
View File
@@ -0,0 +1,88 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#ifndef __POINTER_AUTH_COMMON_H__
#define __POINTER_AUTH_COMMON_H__
#define is_addr_error(addr) (((addr) >> 48) ^ 0xffff)
#define pauth_sign(type, key, addr, mod) \
pauth_common(pac, type, key, addr, mod)
#define pauth_validate(type, key, addr, mod) \
pauth_common(aut, type, key, addr, mod)
#define pauth_strip(type, addr) \
({ \
const void *__addr = (addr); \
\
asm ("xpac" #type " %0\n" : "+r" (__addr)); \
(typeof (addr))__addr; \
})
#define pauth_hash(addr, mod) ((unsigned int) (pauth_pacga(addr, mod) >> 32))
#define pauth_common(prefix, type, key, addr, mod) \
({ \
const void *__addr = (addr); \
unsigned long __mod = (unsigned long)(mod); \
\
if (__builtin_constant_p(mod) && (__mod == 0)) \
asm (#prefix #type "z" #key " %0\n" : "+r" (__addr)); \
else \
asm (#prefix #type #key " %0, %1\n" : "+r" (__addr) : \
"r" (__mod)); \
(typeof (addr))(__addr); \
})
#define pauth_get_raw_data(addr) \
({ \
const void *__addr; \
asm ("mov %0, %1\n" : "=&r" (__addr) : \
"r" (addr)); \
(void *)(__addr); \
})
#define pauth_sign_function(fun, mod, key) \
({ \
const void *__fun = (fun); \
unsigned long __mod = (unsigned long)(mod); \
asm ("paci" #key " %0, %1\n" : "+r" (__fun) : \
"r" (__mod)); \
(void *)(__fun); \
})
#define pauth_pacda(addr, mod) pauth_common(pac, d, a, addr, mod)
#define pauth_pacdb(addr, mod) pauth_common(pac, d, b, addr, mod)
#define pauth_pacia(addr, mod) pauth_common(pac, i, a, addr, mod)
#define pauth_pacib(addr, mod) pauth_common(pac, i, b, addr, mod)
#define pauth_pacga(addr, mod) \
({ \
const void *__addr = (addr); \
unsigned long __mod = (unsigned long)(mod); \
unsigned long __pac; \
\
asm ("pacga %0, %1, %2\n" : "=r" (__pac) : "r" (__addr), \
"r" (__mod)); \
__pac; \
})
#define pauth_autda(addr, mod) pauth_common(aut, d, a, addr, mod)
#define pauth_autdb(addr, mod) pauth_common(aut, d, b, addr, mod)
#define pauth_autia(addr, mod) pauth_common(aut, i, a, addr, mod)
#define pauth_autib(addr, mod) pauth_common(aut, i, b, addr, mod)
#define pauth_xpacd(addr) pauth_strip(d, addr)
#define pauth_xpaci(addr) pauth_strip(i, addr)
#endif /* __POINTER_AUTH_COMMON_H__ */
+119
View File
@@ -0,0 +1,119 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#ifndef __POINTER_AUTH_CONTEXT_H
#define __POINTER_AUTH_CONTEXT_H
struct pt_regs;
enum pac_pt_regs {
REGS_X16 = 0,
REGS_X17,
REGS_LR,
REGS_SP,
REGS_PC,
REGS_PSTATE,
};
void sign_thread_context(void *cpu_context);
void auth_thread_context(void *cpu_context);
void sign_exception_context_asm(void *regs);
void auth_exception_context_asm(void *regs);
int set_exception_context_register_asm(void *regs, int offset, u64 val);
#ifdef CONFIG_COMPAT
void sign_compat_exception_context_asm(void *regs);
void auth_compat_exception_context_asm(void *regs);
int set_compat_exception_context_register_asm(void *regs, int offset, u64 val);
#else
static inline void sign_compat_exception_context_asm(void *regs)
{
}
static inline void auth_compat_exception_context_asm(void *regs)
{
}
static inline int set_compat_exception_context_register_asm(void *regs, int offset, u64 val)
{
return 0;
}
#endif
static inline void sign_compat_exception_context_unsafe(void *regs)
{
return sign_compat_exception_context_asm(regs);
}
static inline void auth_compat_exception_context_unsafe(void *regs)
{
return auth_compat_exception_context_asm(regs);
}
static inline void sign_exception_context_unsafe(void *regs)
{
if (compat_user_mode((struct pt_regs *)regs)) {
sign_compat_exception_context_asm(regs);
} else {
sign_exception_context_asm(regs);
}
}
static inline void auth_exception_context_unsafe(void *regs)
{
if (compat_user_mode((struct pt_regs *)regs)) {
auth_compat_exception_context_asm(regs);
} else {
auth_exception_context_asm(regs);
}
}
#define resign_compat_exception_context_start(regs) \
do { \
unsigned long irq_flags; \
local_irq_save(irq_flags); \
auth_compat_exception_context_asm(regs);
#define resign_compat_exception_context_end(regs) \
sign_compat_exception_context_asm(regs); \
local_irq_restore(irq_flags); \
} while (0)
#define resign_exception_context_start(regs) \
do { \
unsigned long irq_flags; \
local_irq_save(irq_flags); \
auth_exception_context_unsafe(regs);
#define resign_exception_context_end(regs) \
sign_exception_context_unsafe(regs); \
local_irq_restore(irq_flags); \
} while (0)
#define sign_exception_context_start(regs) \
do { \
unsigned long irq_flags; \
local_irq_save(irq_flags);
#define sign_exception_context_end(regs) \
sign_exception_context_unsafe(regs); \
local_irq_restore(irq_flags); \
} while (0)
void sign_compat_exception_context(void *regs);
void auth_compat_exception_context(void *regs);
void sign_exception_context(void *regs);
void auth_exception_context(void *regs);
int set_compat_exception_context_register(void *regs, enum pac_pt_regs regs_enum, u64 val);
void set_compat_exception_context_register_index(struct pt_regs *regs, int index, u64 val);
int set_exception_context_register(void *regs, enum pac_pt_regs regs_enum, u64 val);
void set_exception_context_register_index(struct pt_regs *regs, int index, u64 val);
#endif /* __POINTER_AUTH_CONTEXT_H */
+26
View File
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/assembler.h>
.pushsection ".init.text", "ax"
SYM_CODE_START(init_constructors)
mov x21, x30
adrp x19, __ctors_end
adrp x20, __ctors_start
add x19, x19, #:lo12:__ctors_end
add x20, x20, #:lo12:__ctors_start
cmp x20, x19
b.cs 4f
3: ldr x8, [x20], #8
blr x8
cmp x20, x19
b.cc 3b
4: mov x30, x21
ret
SYM_CODE_END(init_constructors)
+246
View File
@@ -0,0 +1,246 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#include "asm/asm_pointer_auth_context.h"
#include <asm/asm-offsets.h>
#include <asm/sysreg.h>
#include <linux/linkage.h>
#ifdef CONFIG_COMPAT
/* Obtain the regs of compat task to sign or authenticate. */
.macro ldr_compat_pt_regs
mov x1, #0
mov x2, #0
/* load lr, sp, pc, pstate of compat task */
ldr x3, [x0, #S_COMPAT_LR]
ldr x4, [x0, #S_COMPAT_SP]
ldr x5, [x0, #S_PC]
ldr x6, [x0, #S_PSTATE]
.endm
#endif
/* Obtain the regs of task to sign or authenticate. */
.macro ldr_pt_regs
/* load x16, x17, lr, sp, pc, pstate of task */
ldp x1, x2, [x0, #S_X16]
ldr x3, [x0, #S_LR]
ldr x4, [x0, #S_SP]
ldr x5, [x0, #S_PC]
ldr x6, [x0, #S_PSTATE]
.endm
/*
* Register sign_thread_context for AArch64.
* void sign_thread_context(struct cpu_context *cpu_context)
* On entry:
* x0: the pointer of cpu_context
*/
SYM_FUNC_START(sign_thread_context)
mrs x9, daif
msr daifset, #0x2
ldr x1, [x0, #CPU_CONTEXT_PC]
ldr x2, [x0, #CPU_CONTEXT_SP]
sign_thread_context_common
msr daif, x9
ret
SYM_FUNC_END(sign_thread_context)
/*
* Register auth_thread_context for AArch64.
* void auth_thread_context(struct cpu_context *cpu_context)
* On entry:
* x0: the pointer of cpu_context
*/
SYM_FUNC_START(auth_thread_context)
stp x29, x30, [sp, #-16]!
mov x29, sp
mrs x9, daif
msr daifset, #0x2
ldr x1, [x0, #CPU_CONTEXT_PC]
ldr x2, [x0, #CPU_CONTEXT_SP]
auth_thread_context_common
msr daif, x9
ldp x29, x30, [sp], #16
ret
SYM_FUNC_END(auth_thread_context)
/*
* Register set_exception_context_register_asm for AArch64.
* int set_exception_context_register_asm(struct pt_regs *regs, int offset, u64 val);
* On entry:
* x0: the regs of task
* x1: the offset of member in pt_regs struct
* x2: the value need to be update
*/
SYM_FUNC_START(set_exception_context_register_asm)
stp x29, x30, [sp, #-16]!
mov x29, sp
mov x9, x1
mov x10, x2
mrs x11, daif
msr daifset, #0x2
ldr_pt_regs
mov x12, x1
mov x13, x2
auth_exception_context_common x0, x12, x13
cmp x9, #S_LR
b.eq .Lupdate_lr
b.ls .Lchoose_lower
cmp x9, #S_PC
b.eq .Lupdate_pc
b.cc .Lupdate_sp
cmp x9, #S_PSTATE
b.eq .Lupdate_pstate
.Lerror_return:
/* invalid value: return -EINVAL */
mov x0, #-22
b .Lreturn
.Lchoose_lower:
cmp x9, #S_X16
b.eq .Lupdate_x16
b.hi .Lupdate_x17
b .Lerror_return
.Lupdate_pstate:
mov x6, x10
.Lupdate_done:
str x10, [x0, x9]
sign_exception_context_common
.Lreturn:
mov x0, #0
msr daif, x11
ldp x29, x30, [sp], #16
ret
.Lupdate_x16:
mov x1, x10
b .Lupdate_done
.Lupdate_x17:
mov x2, x10
b .Lupdate_done
.Lupdate_lr:
mov x3, x10
b .Lupdate_done
.Lupdate_sp:
mov x4, x10
b .Lupdate_done
.Lupdate_pc:
mov x5, x10
b .Lupdate_done
SYM_FUNC_END(set_exception_context_register_asm)
#ifdef CONFIG_COMPAT
/*
* Register set_compat_exception_context_register_asm for AArch64.
* int set_compat_exception_context_register_asm(struct pt_regs *regs, int offset, u64 val);
* On entry:
* x0: the regs of compat task
* x1: the offset of member in pt_regs struct
* x2: the value need to be update
*/
SYM_FUNC_START(set_compat_exception_context_register_asm)
stp x29, x30, [sp, #-16]!
mov x29, sp
mov x9, x1
mov x10, x2
mrs x11, daif
msr daifset, #0x2
ldr_compat_pt_regs
mov x12, x1
mov x13, x2
auth_exception_context_common x0, x12, x13
cmp x9, #S_COMPAT_LR
b.eq .Lupdate_compat_lr
b.ls .Lcompat_choose_lower
cmp x9, #S_PSTATE
b.eq .Lupdate_compat_pstate
b.cc .Lupdate_compat_pc
.Lcompat_error_return:
/* invalid value: return -EINVAL */
mov x0, #-22
b .Lcompat_return
.Lcompat_choose_lower:
cmp x9, #S_COMPAT_SP
b.eq .Lupdate_compat_sp
b .Lcompat_error_return
.Lupdate_compat_pstate:
mov x6, x10
.Lcompat_update_done:
str x10, [x0, x9]
sign_exception_context_common
.Lcompat_return:
mov x0, #0
msr daif, x11
ldp x29, x30, [sp], #16
ret
.Lupdate_compat_lr:
mov x3, x10
b .Lcompat_update_done
.Lupdate_compat_sp:
mov x4, x10
b .Lcompat_update_done
.Lupdate_compat_pc:
mov x5, x10
b .Lcompat_update_done
SYM_FUNC_END(set_compat_exception_context_register_asm)
#endif
/*
* Register sign_exception_context_asm for AArch64.
* void sign_exception_context_asm(struct pt_regs *regs);
* On entry:
* x0: the regs of task
*/
SYM_FUNC_START(sign_exception_context_asm)
ldr_pt_regs
sign_exception_context_common
ret
SYM_FUNC_END(sign_exception_context_asm)
/*
* Register auth_exception_context_asm for AArch64.
* void auth_exception_context_asm(struct pt_regs *regs);
* On entry:
* x0: the regs of task
*/
SYM_FUNC_START(auth_exception_context_asm)
stp x29, x30, [sp, #-16]!
mov x29, sp
ldr_pt_regs
auth_exception_context_common
ldp x29, x30, [sp], #16
ret
SYM_FUNC_END(auth_exception_context_asm)
#ifdef CONFIG_COMPAT
/*
* Register sign_compat_exception_context_asm for AArch64.
* void sign_compat_exception_context_asm(struct pt_regs *regs);
* On entry:
* x0: the regs of compat task
*/
SYM_FUNC_START(sign_compat_exception_context_asm)
ldr_compat_pt_regs
sign_exception_context_common
ret
SYM_FUNC_END(sign_compat_exception_context_asm)
/*
* Register auth_compat_exception_context_asm for AArch64.
* void auth_compat_exception_context_asm(struct pt_regs *regs);
* On entry:
* x0: the regs of compat task
*/
SYM_FUNC_START(auth_compat_exception_context_asm)
stp x29, x30, [sp, #-16]!
mov x29, sp
ldr_compat_pt_regs
auth_exception_context_common
ldp x29, x30, [sp], #16
ret
SYM_FUNC_END(auth_compat_exception_context_asm)
#endif
+56
View File
@@ -0,0 +1,56 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*
* Pointer authentication keys initialisation.
*/
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/assembler.h>
.pushsection ".init.text", "ax"
.macro ptrauth_key_init type, tmp
mrs x25, ap\type\()keylo_el1
str x25, [\tmp]
mrs x25, ap\type\()keyhi_el1
str x25, [\tmp, #8]
.endm
/* init ptrauth key for kernel backward-edge CFI */
.macro ptrauth_back_key_init
mov x6, x5 /* x5: address of init task */
mov x7, #THREAD_KEYS_KERNEL
add x6, x6, x7
add x6, x6, #PTRAUTH_KERNEL_KEY_APIB
ptrauth_key_init ib, x6
.endm
/* init common ptrauth keys for kernel forward-edge CFI, data pointer DFI and data field DFI */
.macro ptrauth_common_keys_init
adr_l x7, kernel_common_keys
mov x6, x7
add x6, x6, #PTRAUTH_KERNEL_KEY_APIA
ptrauth_key_init ia, x6
mov x6, x7
add x6, x6, #PTRAUTH_KERNEL_KEY_APDA
ptrauth_key_init da, x6
mov x6, x7
add x6, x6, #PTRAUTH_KERNEL_KEY_APDB
ptrauth_key_init db, x6
mov x6, x7
add x6, x6, #PTRAUTH_KERNEL_KEY_APGA
ptrauth_key_init ga, x6
.endm
SYM_CODE_START(ptrauth_kernel_keys_init)
ptrauth_back_key_init
ptrauth_common_keys_init
isb
ret
SYM_CODE_END(ptrauth_kernel_keys_init)
+133
View File
@@ -0,0 +1,133 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#include <asm/asm-offsets.h>
#include <asm/ptrace.h>
#include <linux/irqflags.h>
/* The members of arrays below are corresponding to the enum defined in pointer_auth_context.h:
* enum pac_pt_regs {
* REGS_X16 = 0,
* REGS_X17,
* REGS_LR,
* REGS_SP,
* REGS_PC,
* REGS_PSTATE,
* };
*
* compat_regs_offset_array[]:
* S_X14: the offset of compat_lr
* S_X13: the offset of compat_sp
*/
static off_t compat_regs_offset_array[] = {0, 0, S_X14, S_X13, S_PC, S_PSTATE};
static off_t regs_offset_array[] = {S_X16, S_X17, S_LR, S_SP, S_PC, S_PSTATE};
int set_compat_exception_context_register(void *regs, enum pac_pt_regs regs_enum, u64 val)
{
switch (regs_enum) {
case REGS_LR:
case REGS_SP:
case REGS_PC:
case REGS_PSTATE:
return set_compat_exception_context_register_asm(regs, compat_regs_offset_array[regs_enum], val);
default:
return -EINVAL;
}
}
int set_exception_context_register(void *regs, enum pac_pt_regs regs_enum, u64 val)
{
if (compat_user_mode((struct pt_regs *)regs)) {
return set_compat_exception_context_register(regs, regs_enum, val);
} else {
switch (regs_enum) {
case REGS_X16:
case REGS_X17:
case REGS_LR:
case REGS_SP:
case REGS_PC:
case REGS_PSTATE:
return set_exception_context_register_asm(regs, regs_offset_array[regs_enum], val);
default:
return -EINVAL;
}
}
}
void set_compat_exception_context_register_index(struct pt_regs *regs, int index, uint64_t val)
{
/* 14 means the index of compat_lr */
if (index == 14) {
set_compat_exception_context_register_asm(regs, S_X14, val);
/* 13 means the index of compat_sp */
} else if (index == 13) {
set_compat_exception_context_register_asm(regs, S_X13, val);
} else {
regs->regs[index] = val;
}
}
void set_exception_context_register_index(struct pt_regs *regs, int index, uint64_t val)
{
off_t offset;
if (compat_user_mode(regs)) {
set_compat_exception_context_register_index(regs, index, val);
} else {
switch (index) {
/* 16 means the index of regs[16] */
case 16:
/* 17 means the index of regs[17] */
case 17:
/* 30 means the index of regs[30] */
case 30:
offset = offsetof(struct pt_regs, regs[index]);
set_exception_context_register_asm(regs, offset, val);
break;
default:
regs->regs[index] = val;
}
}
}
void sign_compat_exception_context(void *regs)
{
unsigned long irq_flags;
local_irq_save(irq_flags);
sign_compat_exception_context_asm(regs);
local_irq_restore(irq_flags);
}
void auth_compat_exception_context(void *regs)
{
unsigned long irq_flags;
local_irq_save(irq_flags);
auth_compat_exception_context_asm(regs);
local_irq_restore(irq_flags);
}
void sign_exception_context(void *regs)
{
unsigned long irq_flags;
local_irq_save(irq_flags);
if (compat_user_mode((struct pt_regs *)regs)) {
sign_compat_exception_context_asm(regs);
} else {
sign_exception_context_asm(regs);
}
local_irq_restore(irq_flags);
}
void auth_exception_context(void *regs)
{
unsigned long irq_flags;
local_irq_save(irq_flags);
if (compat_user_mode((struct pt_regs *)regs)) {
auth_compat_exception_context_asm(regs);
} else {
auth_exception_context_asm(regs);
}
local_irq_restore(irq_flags);
}
+10
View File
@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*
* Pointer authentication keys initialisation.
*/
#include <asm/pointer_auth.h>
struct ptrauth_keys_kernel_common kernel_common_keys = {{-1, -1}};