新闻详情

新闻详情

首页 / 资讯中心 / 详情

AArch64 Linux 带标签虚拟地址(Tagged Pointers)完全解析:TBI 机制、内核接口与 Tagged Address ABI 实战

发布时间:2026/9/12 2:01:43来源:尧图网络
AArch64 Linux 带标签虚拟地址(Tagged Pointers)完全解析:TBI 机制、内核接口与 Tagged Address ABI 实战
AArch64 Linux 带标签虚拟地址Tagged Pointers完全解析TBI 机制、内核接口与 Tagged Address ABI 实战【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux本文基于 Linux 内核源码树中的 Documentation/arch/arm64/tagged-pointers.rst 展开系统讲解 AArch64 地址转换系统中最高字节忽略Top Byte IgnoreTBI特性的工作原理、内核对待带标签用户地址的默认策略以及如何通过 AArch64 Tagged Address ABI 与 Memory Tagging ExtensionMTE在应用层安全地使用带标签指针。读完本文你将理解内核为何默认禁止向系统调用传递非零标签地址、信号传递过程中标签如何保留或丢失并能编写出正确启用 Tagged Address ABI、兼容 MTE 的实战代码。引言什么是 AArch64 的 Tagged Virtual Address在 AArch64 地址转换体系中页表翻译由 TTBR0_EL1 与 TTBR1_EL1 两个基地址寄存器所指向的两组翻译表完成TTBR0 负责用户态EL0映射TTBR1 负责内核态EL1映射。AArch64 Linux 在配置翻译表时做了这样一个关键设计经由 TTBR0 完成的翻译即所有用户态映射其虚拟地址的最高一个字节bits 63:56会被翻译硬件直接忽略从而把这个字节解放出来供应用程序自由使用。这便是在 tagged-pointers.rst 中描述的核心事实只要该字节中的位被置为非零这个地址就是一个带标签地址tagged address / tagged pointer标签可用于存放程序自定义的元数据——例如在内存标记扩展MTE中存放 4 位逻辑标签。从内核源码看TBI 特性由页表配置寄存器中的TCR_EL1.TBI0TTBR0 侧与TCR_EL1.TBI1TTBR1 侧位控制其定义位于 arch/arm64/include/asm/pgtable-hwdef.h#define TCR_TBI0 TCR_EL1_TBI0 #define TCR_TBI1 TCR_EL1_TBI1TBI 是 MTE 的基石——Memory Tagging Extension 正是建立在 ARMv8.0 的 TBI 特性之上从虚拟地址 bits 59:56 派生出逻辑标签详见 Documentation/arch/arm64/memory-tagging-extension.rst。因此理解带标签地址是理解 AArch64 内存安全特性的第一步。内核如何解释用户地址默认假设标签为 0x00虽然翻译硬件忽略最高字节但内核在解释用户态内存地址时并不天然接受带标签的指针。默认情况下即应用程序未显式启用 AArch64 Tagged Address ABI 时内核在解释所有用户态内存地址时一律假设地址标签为0x00。这一默认假设覆盖但不限于以下位置的地址系统调用的指针参数包括传递给系统调用的结构体中的指针栈指针 sp——例如内核在投递信号时需要对 sp 进行解释帧指针 x29 与栈帧记录frame records——例如内核据此生成回溯backtrace或调用图call graph。从实现角度看内核通过untagged_addr()宏在需要时清除标签位得到可用于access_ok()等检查的干净指针。该宏定义于 arch/arm64/include/asm/memory.h/* * When dealing with data aborts, watchpoints, or instruction traps we may end * up with a tagged userland pointer. Clear the tag to get a sane pointer to * pass on to access_ok(), for instance. */ #define __untagged_addr(addr) \ ((__force __typeof__(addr))sign_extend64((__force u64)(addr), 55)) #define untagged_addr(addr) ({ \ u64 __addr (__force u64)(addr); \ __addr __untagged_addr(__addr); \ (__force __typeof__(addr))__addr; \ })注意这里使用了sign_extend64(addr, 55)——即用 bit 55 对高位进行符号扩展这与后文架构禁止带标签 PC一节中异常返回时将最高字节设置为 bit 55 的符号扩展的硬件行为完全一致。同样地arch/arm64/kernel/hw_breakpoint.c 在计算 watchpoint 距离时也会先调用untagged_addr()去掉用户指针的标签。向内核传递带标签地址的规则理解了内核的默认假设后规则就非常清晰了。除非应用程序显式启用 AArch64 Tagged Address ABI见下一节否则禁止通过系统调用向内核传递非零标签的地址强烈不鼓励将非零标签用于 sp 栈指针。如果违背上述规则后果是未定义的可能表现为系统调用返回错误码error code内核向进程投递可能致命的信号或其他形式的失败。而维护非零标签帧指针x29与帧记录的程序其调试与性能剖析可见性backtrace / call graph 的准确性也可能受损。之所以如此严格原因在于内核会对用户传入的地址执行合法性检查如access_ok()、地址解引用、信号上下文解释等一系列操作这些操作普遍假设地址是干净的tag 为 0。带标签的指针一旦混入其中轻则检查失败重则导致内核按错误地址解释用户态结构。AArch64 Tagged Address ABI何时以及如何合法使用标签为了让用户空间能够合法地使用标签指针AArch64 Linux 提供了Tagged Address ABI其完整语义记录在 Documentation/arch/arm64/tagged-address-abi.rst 中。什么是合法带标签指针从系统调用接口的角度一个合法带标签指针valid tagged pointer指指针的最高字节可能非零但其引用的地址必须是用户进程地址空间中通过以下任一方式获得的真实地址mmap()系统调用且满足以下任一条件flags 设置了MAP_ANONYMOUS位或文件描述符指向一个普通文件包括memfd_create()返回的或/dev/zerobrk()系统调用即进程创建时 program break 的初始位置到当前位置之间的堆区进程创建期间由内核映射到其地址空间中的内存如 data、bss、stack且遵循与上述mmap()相同的限制。两阶段的 ABI 放松ABI 的放松分两个阶段取决于内核如何使用这些用户地址阶段 1内核不访问、仅用于地址空间管理的地址如mprotect()、madvise()的参数。允许使用合法带标签指针但有如下例外brk()、mmap()以及mremap()的new_address参数——因为这三个调用可能产生与现有用户地址的别名alias问题。注意这一行为在内核 v5.6 中变更更早的内核可能错误地接受带标签指针userfaultfd()返回的文件描述符上UFFDIO_*系列ioctl()的range.start、start和dst参数——因为随后从该文件描述符读取到的 fault address 是不带标签的可能误导不了解标签的程序。该行为在 v5.14 中变更更早内核可能错误接受。阶段 2内核会实际访问的用户地址如write()的参数。此阶段的放松默认关闭应用程序线程必须通过prctl()显式开启具体接口为prctl(PR_SET_TAGGED_ADDR_CTRL, arg2, 0, 0, 0)为调用线程启用或禁用 AArch64 Tagged Address ABI。arg2是描述控制模式的位掩码其中PR_TAGGED_ADDR_ENABLE1UL 0表示启用默认状态为禁用arg3、arg4、arg5必须为 0prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0)查询调用线程的 ABI 状态arg2~arg5必须为 0。这些常量定义于 include/uapi/linux/prctl.h#define PR_SET_TAGGED_ADDR_CTRL 55 #define PR_GET_TAGGED_ADDR_CTRL 56 # define PR_TAGGED_ADDR_ENABLE (1UL 0)ABI 属性是线程作用域的在clone()与fork()时继承在exec()时清除。如果通过sysctl abi.tagged_addr_disabled1在全局禁用了该 ABI则调用prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0)会返回-EINVALabi.tagged_addr_disabled的默认值为 0即不禁用。从内核实现看set_tagged_addr_ctrl()与get_tagged_addr_ctrl()位于 arch/arm64/kernel/process.c。值得注意的实现细节对 32 位兼容线程compat thread直接返回-EINVAL若硬件支持 MTEsystem_supports_mte()valid_mask会额外并入PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC | PR_MTE_TAG_MASK以及PR_MTE_STORE_ONLY即 Tagged Address ABI 的prctl接口同时是 MTE 的配置入口tagged_addr_disabled由abi子系统的 sysctl 表管理proc_dointvec_minmax取值 0/1该全局开关只阻止通过prctl()新启用ABI不会禁用已经选择加入的线程启用状态以TIF_TAGGED_ADDR线程标志记录在thread_info中exec()时通过flush_tagged_addr_state()arch/arm64/kernel/process.c清除——与文档所述exec() 时清除一致。ABI 启用后的保证当某线程启用了 Tagged Address ABI内核保证以下行为除上文阶段 1 例外与下述始终必须不带标签的参数外所有系统调用都可以接受任意合法带标签指针对合法带标签指针的系统调用行为与对应的不带标签指针完全一致对非法带标签指针不在上述合法来源之列的系统调用行为未定义可能返回错误码、投递致命信号或其他失败模式。无论 ABI 如何都必须不带标签的参数以下系统调用参数不受 ABI 放松影响任何时候都必须使用不带标签的指针prctl()中除由内核直接或间接访问的用户数据指针以外的参数ioctl()中除由内核直接或间接访问的用户数据指针以外的参数shmat()与shmdt()brk()自内核 v5.6 起mmap()自内核 v5.6 起mremap()的new_address参数自内核 v5.6 起。对这些参数使用非零标签同样可能产生错误码、致命信号或其他失败。保留标签信号处理路径上的行为细节即使应用正确使用了带标签指针在内核投递信号时标签信息是否会原样出现在信号相关字段中仍有一整套细致规则——这正是 tagged-pointers.rst 的重点内容。siginfo.si_addr 与 SA_EXPOSE_TAGBITS投递信号时非零标签默认不会保留在siginfo.si_addr中除非安装信号处理器时在sigaction.sa_flags中设置了SA_EXPOSE_TAGBITS标志。这意味着使用标签的应用其信号处理器不能依赖该字段中的用户虚拟地址还携带标签信息除非显式设置了该标志。MTE 同步标签检查错误SEGV_MTESERR的特殊情况对于同步标签检查错误SEGV_MTESERR产生的故障地址标签保留与否取决于硬件特性如果 CPU 支持FEAT_MTE_TAGGED_FARArmv8.9故障地址的 bits 63:60 会被保留否则即使设置了SA_EXPOSE_TAGBITS这些位也不会被保留。应用程序应依据对HWCAP3_MTE_FAR的支持情况来解释这些位的值若该 HWCAP 不存在这些位应视为未定义若存在则为有效值。watchpoint 调试异常与 sigcontext.fault_address有两个无论标志如何的确定性行为watchpoint 调试异常引发的信号其标签信息无论SA_EXPOSE_TAGBITS如何设置都会被保留非零标签永远不会保留在sigcontext.fault_address中同样与SA_EXPOSE_TAGBITS无关。禁止带标签的 PC架构禁止使用带标签的 PC指令指针。在异常返回exception return时PC 的最高一个字节会被设置为 bit 55 的符号扩展值。这一行为在 Tagged Address ABI 启用后依然保持ABI 的放松只涉及数据地址不涉及 PC。这也解释了前文untagged_addr()宏为何使用sign_extend64(..., 55)进行符号扩展——它精确复刻了硬件对地址的解释方式。实战示例在应用中使用 Tagged Address ABI下面这段 C 代码摘自 Documentation/arch/arm64/tagged-address-abi.rst 的正确用法示例演示了从启用 ABI 到使用带标签指针完成一次write()系统调用的完整流程#include stdlib.h #include string.h #include unistd.h #include sys/mman.h #include sys/prctl.h #define PR_SET_TAGGED_ADDR_CTRL 55 #define PR_TAGGED_ADDR_ENABLE (1UL 0) #define TAG_SHIFT 56 int main(void) { int tbi_enabled 0; unsigned long tag 0; char *ptr; /* check/enable the tagged address ABI */ if (!prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0)) tbi_enabled 1; /* memory allocation */ ptr mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (ptr MAP_FAILED) return 1; /* set a non-zero tag if the ABI is available */ if (tbi_enabled) tag rand() 0xff; ptr (char *)((unsigned long)ptr | (tag TAG_SHIFT)); /* memory access to a tagged address */ strcpy(ptr, tagged pointer\n); /* syscall with a tagged pointer */ write(1, ptr, strlen(ptr)); return 0; }要点拆解PR_TAGGED_ADDR_ENABLE对应 prctl 编号 55 的第一个位定义于 include/uapi/linux/prctl.h内存来自mmap(MAP_PRIVATE | MAP_ANONYMOUS)属于前文定义的合法带标签指针来源因此write()能够接受它标签通过tag TAG_SHIFT即tag 56置入最高字节若prctl()失败例如 ABI 被sysctl abi.tagged_addr_disabled1全局禁用返回-EINVAL程序退化为使用标签 0行为仍正确——这是稳健的降级路径。与 Memory Tagging ExtensionMTE的衔接带标签地址机制并不止于高位存数据它与 MTE 深度绑定。当硬件支持 MTECONFIG_ARM64_MTE开启且硬件具备该特性时内核通过HWCAP2_MTE向用户空间通告。用户进程可用mmap()/mprotect()的PROT_MTE标志0x20定义于arch/arm64/include/uapi/asm/mman.h为地址范围启用内存标记属性MTE 将从虚拟地址 bits 59:56 派生 4 位逻辑标签与每个 16 字节粒度的分配标签比对失配时按PR_MTE_TCF_*配置触发同步SEGV_MTESERR或异步SEGV_MTEAERR的SIGSEGV。这些 MTE 的 tag check 模式、标签生成掩码PR_MTE_TAG_MASK、每 CPU 偏好模式/sys/devices/system/cpu/cpuN/mte_tcf_preferred等均通过与 Tagged Address ABI 相同的prctl(PR_SET_TAGGED_ADDR_CTRL, ...)接口配置参见 arch/arm64/kernel/process.c 对valid_mask的扩展完整细节请阅读 Documentation/arch/arm64/memory-tagging-extension.rst。可以说Tagged Address ABI 是可以带标签调用内核的准入证而 MTE 是把标签用于内存安全检测的硬件能力——二者共享同一套 prctl 控制面却解决不同层面的问题。其他注意事项与使用警告tagged-pointers.rst 在结尾给出了一个容易被忽视的工程警告使用带标签指针时需要特别小心因为C 编译器几乎不会对仅最高字节不同的两个虚拟地址做别名规避hazard处理。也就是说若程序持有0x0000...XXXX与0x00FF...XXXX这样一对仅标签不同的指针编译器基于严格别名规则做出的优化如缓存、重排、合并访问可能破坏预期语义。因此标签操作应尽量集中、显式避免同一内存区域被带标签指针与不带标签指针混用标签在指针生命周期内应保持一致跨函数传递时应明确约定在性能敏感或依赖指针相等性/排序的代码路径中务必先清除标签再比较。总结AArch64 Linux 的带标签虚拟地址机制可以浓缩为一张规则表场景规则翻译硬件TTBR0 用户映射忽略最高字节bits 63:56由TCR_EL1.TBI0控制内核默认假设用户地址标签为 0x00未启用 ABI 时禁止向系统调用传非零标签地址地址管理类 syscallmprotect/madvise允许合法带标签指针brk/mmap/mremap-new_address/userfaultfd 除外内核访问类 syscall如 write需prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE)按线程启用始终禁用prctl/ioctl 非数据指针、shmat/shmdt、brk、mmap、mremap new_address信号投递siginfo.si_addr需SA_EXPOSE_TAGBITS才保留标签sigcontext.fault_address永不保留watchpoint 信号始终保留MTE 故障地址需FEAT_MTE_TAGGED_FARArmv8.9HWCAP3_MTE_FAR才能解释 bits 63:60指令指针架构禁止 tagged PC异常返回时最高字节为 bit 55 的符号扩展对应用开发者而言核心结论是能用带标签指针与何时能向内核传带标签指针是两回事。前者由 TBI 硬件特性天然支持后者必须遵循 Tagged Address ABI 的显式准入规则。正确启用 ABI 并遵循本文的标签保留规则才能让标签技术无论是元数据编码还是 MTE 内存安全检测安全地落地到真实程序中。延伸阅读AArch64 Tagged Address ABI 完整规范Memory Tagging ExtensionMTE在 AArch64 Linux 中的实现prctl 常量定义untagged_addr 宏实现set/get_tagged_addr_ctrl 与 sysctl 实现AArch64 架构文档索引【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

终极指南:5分钟快速上手Dango-Translator生肉翻译软件 [特殊字符] 2026/9/12 2:34:48

终极指南:5分钟快速上手Dango-Translator生肉翻译软件 [特殊字符]

终极指南:5分钟快速上手Dango-Translator生肉翻译软件 🚀 想要轻松翻译游戏、漫画、视频中的外文内容吗?Dango-Translator(团子翻译器)是一款基于OCR技术的专业生肉翻译软件,能够实时识别屏幕文字并进行翻…

阅读更多 →
Spark交通大数据实时分析实战:轨迹清洗、OD矩阵与特征工程 2026/9/12 2:34:48

Spark交通大数据实时分析实战:轨迹清洗、OD矩阵与特征工程

简介:本资源是一套基于Apache Spark构建的交通数据分析系统完整实现,面向计算机、电子信息工程及数学等专业的本科生与研究生,适用于课程设计、期末大作业及毕业设计等实践场景,聚焦交通流统计、实时车速监测、异常事件预警等典型…

阅读更多 →
Remix 3 表单数据怎么用 data-schema 校验并返回 400 响应 2026/9/12 2:34:48

Remix 3 表单数据怎么用 data-schema 校验并返回 400 响应

Remix 3 表单数据怎么用 data-schema 校验并返回 400 响应 【免费下载链接】remix The fully-stacked web framework 项目地址: https://gitcode.com/GitHub_Trending/re/remix Remix 里一个常见的服务端表单处理需求:浏览器把未经信任的字段 POST 到 action…

阅读更多 →
如何三步验证系统化交易策略:awesome-systematic-trading 完整指南 2026/9/12 2:34:48

如何三步验证系统化交易策略:awesome-systematic-trading 完整指南

如何三步验证系统化交易策略:awesome-systematic-trading 完整指南 【免费下载链接】awesome-systematic-trading A curated list of awesome libraries, packages, strategies, books, blogs, tutorials for systematic trading. 项目地址: https://gitcode.com/…

阅读更多 →
如何在华为 HarmonyOS 上跑通 GMS 应用:MicroG 签名伪造与位置权限配置完整指南 2026/9/12 2:34:47

如何在华为 HarmonyOS 上跑通 GMS 应用:MicroG 签名伪造与位置权限配置完整指南

如何在华为 HarmonyOS 上跑通 GMS 应用:MicroG 签名伪造与位置权限配置完整指南 【免费下载链接】GmsCore Free implementation of Play Services 项目地址: https://gitcode.com/GitHub_Trending/gm/GmsCore 这篇文章是一份 MicroG 华为配置教程&#xff0c…

阅读更多 →
SpringBoot+Vue3+MyBatis构建美食推荐系统实践 2026/9/12 2:31:47

SpringBoot+Vue3+MyBatis构建美食推荐系统实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞