diff --git a/LICENSE b/LICENSE
index fc48fd28904f6680c1da24e70d27c7ffb7a31c16..2016ff8ae22b64b0270e62eb3521af0f08631083 100644
--- a/LICENSE
+++ b/LICENSE
@@ -2,5 +2,6 @@
./newip/
./xpm/
./qos_auth/
+ ./pac/
As for the specific use of the licenses, please refer to the relevant description in the documents.
diff --git a/OAT.xml b/OAT.xml
index 9de7aacb31ad265d296ee9139b08fe3783166732..a9a37b963fd3db09b7097551cb97f54310fdc088 100644
--- a/OAT.xml
+++ b/OAT.xml
@@ -60,9 +60,11 @@ Note:If the text contains special characters, please escape them according to th
+
+
@@ -81,6 +83,7 @@ Note:If the text contains special characters, please escape them according to th
+
diff --git a/pac/Makefile b/pac/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..6fbb431c930b7267f3401b60298342896597fde9
--- /dev/null
+++ b/pac/Makefile
@@ -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
diff --git a/pac/README_zh.md b/pac/README_zh.md
new file mode 100644
index 0000000000000000000000000000000000000000..0ccf2fe6bc74b564068f50f1f9ef15a7279647fe
--- /dev/null
+++ b/pac/README_zh.md
@@ -0,0 +1,67 @@
+## 背景
+
+现阶段,内存安全漏洞是对计算机系统安全最严重的威胁。从漏洞利用的角度分析,借助常见的攻击手段,包括利用缓冲区溢出等实现JOP/ROP攻击,攻击者可以实现控制流劫持,最终导致任意代码执行,这严重摧毁了一个系统的安全性。另一方面,在攻击者利用内存漏洞做提权的过程中,通常会修改指向关键数据(如Cred)的数据指针,这类攻击被归纳为DOP攻击,同样会对系统安全产生严重威胁。
+因此,系统需要高效的漏洞防利用机制,以保护系统的控制流完整性和数据流完整性,这对于提升系统的安全竞争力具有重要意义。当前,从安全性角度,对于系统安全主流的JOP/ROP/DOP攻击,PAC机制均能实现有效防护。
+
+## PAC(Pointer Authentication Code)模块
+
+PAC模块利用ARMv8.3-a架构提供的PAC特性,基于linux内核提供PAC相关的特性支持,包括密钥管理、数据和指针签名验签,以及任务切换上下文、异常中断上下文的PAC保护机制。PAC主要功能实现如下:
+
+### 1.密钥管理
+
+ARMv8.3-a指令集引入了硬件安全特性PAC,用于保护内存中指针和其他数据的完整性。原理是:ARM硬件基于QARMA密码算法,将被保护的指针或数据、用于签名的密钥和盐值作为输入,计算输出一个MAC值,对于指针来说,将有效的MAC值存放在指针的未使用高位,对于数据来说,需要另开辟内存用于保存MAC值。
+
+
+
+Linux内核的密钥管理分为用户态密钥和内核态密钥,示意图如下:
+
+
+
+### 2.关键数据和指针保护
+
+Linux内核可以利用PAC模块对任务切换上下文、异常中断上下文中的关键字段进行保护,防止在上下文切换的过程中,攻击者利用内存漏洞提权修改关键字段,最终导致任意代码执行。
+
+
+
+## 目录
+
+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_USER=y`
+
+ `CONFIG_ARM64_PTR_AUTH_KERNEL=y`
+
+ `CONFIG_ARM64_PTR_AUTH_EXT=y`
+
+3. 关键数据和指针保护使能
+
+ `CONFIG_ARM64_PTR_AUTH_PTR=y`
+
+ `CONFIG_ARM64_PTR_AUTH_FIELD=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)
diff --git a/pac/apply_pac.sh b/pac/apply_pac.sh
new file mode 100755
index 0000000000000000000000000000000000000000..7192d87ed63e2210a44591eb053308c5db5731b5
--- /dev/null
+++ b/pac/apply_pac.sh
@@ -0,0 +1,28 @@
+#!/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" ]; then
+ mkdir $KERNEL_BUILD_ROOT/arch/arm64/pac
+ fi
+
+ cd $KERNEL_BUILD_ROOT/arch/arm64/pac
+ ln -s -f $(realpath --relative-to=$KERNEL_BUILD_ROOT/arch/arm64/pac/ $PAC_SOURCE_ROOT)/* ./
+
+ popd
+}
+
+main
diff --git a/pac/config/config.txt b/pac/config/config.txt
new file mode 100755
index 0000000000000000000000000000000000000000..3793f5e7f3d9d651cf3cfeb9baf43d0690d21ba5
--- /dev/null
+++ b/pac/config/config.txt
@@ -0,0 +1,51 @@
+struct.task_struct mm
+struct.task_struct stack
+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_user_ns
+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.mount mnt_ns
+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.ipc_namespace user_ns
+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
diff --git a/pac/figures/key.png b/pac/figures/key.png
new file mode 100755
index 0000000000000000000000000000000000000000..10701d465fd63e0dad8393d259c1fb2f1751737d
Binary files /dev/null and b/pac/figures/key.png differ
diff --git a/pac/figures/pac.png b/pac/figures/pac.png
new file mode 100755
index 0000000000000000000000000000000000000000..81556202ea13d6bd3a19a282865a12d1604ca55e
Binary files /dev/null and b/pac/figures/pac.png differ
diff --git a/pac/figures/pac_context.png b/pac/figures/pac_context.png
new file mode 100755
index 0000000000000000000000000000000000000000..5c92414143526cfdf72cd34de25fb2d65d16118f
Binary files /dev/null and b/pac/figures/pac_context.png differ
diff --git a/pac/include/asm_pointer_auth_context.h b/pac/include/asm_pointer_auth_context.h
new file mode 100644
index 0000000000000000000000000000000000000000..bc8acc70f0f4b5997ecf29a74a4a9c931d423bd6
--- /dev/null
+++ b/pac/include/asm_pointer_auth_context.h
@@ -0,0 +1,168 @@
+// 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
+#include
+
+ /* 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
+ /* 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 x28, elr_el1
+ mov x29, x22
+ .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 x28, elr_el1
+ .if \sign_or_auth == 0
+ mrs x29, spsr_el1
+ .else
+ mov x29, 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
+ 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, x28, x29
+ .else
+ auth_exception_context_common x23, x24, x25, x26, x27, x28, x29
+ .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 */
diff --git a/pac/include/asm_pointer_auth_key.h b/pac/include/asm_pointer_auth_key.h
new file mode 100644
index 0000000000000000000000000000000000000000..d49e1490950167fc391cfdad1251ea9880946159
--- /dev/null
+++ b/pac/include/asm_pointer_auth_key.h
@@ -0,0 +1,63 @@
+/* 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
+#include
+#include
+#include
+
+ .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
+ .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
diff --git a/pac/include/pointer_auth_common.h b/pac/include/pointer_auth_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..1eb97e16cb7a59158358c3755bcb09e73fa4e828
--- /dev/null
+++ b/pac/include/pointer_auth_common.h
@@ -0,0 +1,87 @@
+// 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 PTR_AUTH_PROTECT_PTR __attribute__((pac_protected_ptr))
+#define PTR_AUTH_PROTECT_DATA __attribute__((pac_protected_data))
+
+#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); \
+ pauth_common(pac, i, key, __fun, 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__ */
diff --git a/pac/include/pointer_auth_context.h b/pac/include/pointer_auth_context.h
new file mode 100644
index 0000000000000000000000000000000000000000..5ef68130cc753ccfa4b40787cd74396332ceda79
--- /dev/null
+++ b/pac/include/pointer_auth_context.h
@@ -0,0 +1,117 @@
+// 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
+
+#include
+#include
+#include
+
+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(void *regs)
+{
+ return sign_compat_exception_context_asm(regs);
+}
+
+static inline void auth_compat_exception_context(void *regs)
+{
+ return auth_compat_exception_context_asm(regs);
+}
+
+static inline void sign_exception_context(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(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(regs);
+
+#define resign_exception_context_end(regs) \
+ sign_exception_context(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(regs); \
+ local_irq_restore(irq_flags); \
+} while(0)
+
+int set_compat_exception_context_register(void *regs, enum pac_pt_regs regs_enum, u64 val);
+int set_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);
+void set_exception_context_register_index(struct pt_regs *regs, int index, u64 val);
+
+#endif /* __POINTER_AUTH_CONTEXT_H */
+
diff --git a/pac/src/asm_pointer_auth_constructors.S b/pac/src/asm_pointer_auth_constructors.S
new file mode 100644
index 0000000000000000000000000000000000000000..4f1405bb1a353d35c70e4cd1188bf9d011761e50
--- /dev/null
+++ b/pac/src/asm_pointer_auth_constructors.S
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ */
+
+#include
+#include
+#include
+
+.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)
diff --git a/pac/src/asm_pointer_auth_context.S b/pac/src/asm_pointer_auth_context.S
new file mode 100644
index 0000000000000000000000000000000000000000..3a4370391c99e6df5aad77352c41c5f91f35df08
--- /dev/null
+++ b/pac/src/asm_pointer_auth_context.S
@@ -0,0 +1,240 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ */
+
+#include "asm_pointer_auth_context.h"
+
+#include
+#include
+#include
+
+#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)
+ ldr x1, [x0, #CPU_CONTEXT_PC]
+ ldr x2, [x0, #CPU_CONTEXT_SP]
+ sign_thread_context_common
+ 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
+ ldr x1, [x0, #CPU_CONTEXT_PC]
+ ldr x2, [x0, #CPU_CONTEXT_SP]
+ auth_thread_context_common
+ 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
+
diff --git a/pac/src/asm_pointer_auth_key.S b/pac/src/asm_pointer_auth_key.S
new file mode 100644
index 0000000000000000000000000000000000000000..ab2360de63d62146e640b47fe7ebe86003cb9b6d
--- /dev/null
+++ b/pac/src/asm_pointer_auth_key.S
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ *
+ * Pointer authentication keys initialisation.
+ */
+
+#include
+#include
+#include
+
+.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)
diff --git a/pac/src/pointer_auth_context.c b/pac/src/pointer_auth_context.c
new file mode 100644
index 0000000000000000000000000000000000000000..95fa3f6bc8ba015b420e481905cf8249d559a583
--- /dev/null
+++ b/pac/src/pointer_auth_context.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ */
+
+#include
+#include
+#include
+#include
+
+/* 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;
+ }
+ }
+}
+
diff --git a/pac/src/pointer_auth_key.c b/pac/src/pointer_auth_key.c
new file mode 100644
index 0000000000000000000000000000000000000000..929341380733d931ec6cb1c10653a0ab12f66bc6
--- /dev/null
+++ b/pac/src/pointer_auth_key.c
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ *
+ * Pointer authentication keys initialisation.
+ */
+
+#include
+
+struct ptrauth_keys_kernel_common kernel_common_keys = {{-1, -1}};