On 2023/12/15 17:49, qiwu.chen(a)transsion.com wrote:
Kernel commit 11167161e553d("kasan, arm64: implement HW_TAGS
runtime") introduce a Hardware Tag-Based KASAN(MTE) mode for ARMv8.5 later CPUs,
which uses the Top Byte Ignore (TBI) feature of arm64 CPUs to store a pointer tag in the
top byte of kernel pointers.
This is correct?
2e903b914797 ("kasan, arm64: implement HW_TAGS runtime")
Currently, crash utility cannot load MTE ramdump due to access the invalid HW Tag-Based
kvaddr. Here's the example error message:
please wait... (gathering kmem slab cache data)
crash: invalid kernel virtual address: f1ffff80c000201c type: "kmem_cache
objsize/object_size"
please wait... (gathering task table data)
crash: invalid kernel virtual address: f9ffff8239c2cde0 type: "xa_node
shift"
This patch replace the orignal generic_is_kvaddr() with arm64_is_kvaddr(), which check
the validity for a HW Tag-Based kvaddr. mte_tag_reset() is used to convert a Tag-Based
kvaddr to untaggged kvaddr in arm64_VTOP() and arm64_IS_VMALLOC_ADDR().
Signed-off-by: chenqiwu <qiwu.chen(a)transsion.com>
---
arm64.c | 48 +++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 45 insertions(+), 3 deletions(-)
diff --git a/arm64.c b/arm64.c
index 2b6b0e5..18d1627 100644
--- a/arm64.c
+++ b/arm64.c
@@ -101,6 +101,42 @@ struct kernel_range { static struct kernel_range
*arm64_get_va_range(struct machine_specific *ms); static void
arm64_get_struct_page_size(struct machine_specific *ms);
+typedef unsigned char u8;
+/* mte tag shift bit */
+#define MTE_TAG_SHIFT 56
+/* native kernel pointers tag */
+#define KASAN_TAG_KERNEL 0xFF
+/* minimum value for random tags */
+#define KASAN_TAG_MIN 0xF0
+/* right shift the tag to MTE_TAG_SHIFT bit */
+#define mte_tag_shifted(tag) ((ulong)(tag) << MTE_TAG_SHIFT)
+/* get the top byte value of the original kvaddr */
+#define mte_tag_get(addr) (u8)((ulong)(addr) >> MTE_TAG_SHIFT)
+/* reset the top byte to get an untaggged kvaddr */
+#define mte_tag_reset(addr) ((ulong)addr & ~mte_tag_shifted(KASAN_TAG_KERNEL)
| mte_tag_shifted(KASAN_TAG_KERNEL))
+
+static inline bool is_mte_kvaddr(ulong addr) {
+ /* check for mte enabled */
+ if (!symbol_exists("cpu_enable_mte"))
+ return false;
It would be better to introduce a flag and initialize it like
if (symbol_exists("cpu_enable_mte"))
machdep->flags |= ARM64_MTE;
or something in arm64_init().
+
+ /* check for HW Tag-Based kvaddr */
+ if (mte_tag_get(addr) >= KASAN_TAG_MIN && mte_tag_get(addr) <
KASAN_TAG_KERNEL)
+ return true;
+
+ return false;
+}
+
+static int arm64_is_kvaddr(ulong addr)
+{
+ /* Check for the untaggged kvaddr for HW tag-based KASAN mode */
+ if (is_mte_kvaddr(addr))
+ return (mte_tag_reset(addr) >= (ulong)(machdep->kvbase));
+
+ return (addr >= (ulong)(machdep->kvbase)); }
+
static void arm64_calc_kernel_start(void) {
struct machine_specific *ms = machdep->machspec; @@ -268,7 +304,7 @@ arm64_init(int
when)
There are some broken lines like the above in this patch, I cannot apply
this patch. Could you check please?
Its archive is also broken:
https://lists.crash-utility.osci.io/archives/list/devel@lists.crash-utili...
Thanks,
Kazu
> machdep->kvbase = ARM64_VA_START;
> ms->userspace_top = ARM64_USERSPACE_TOP;
> }
> - machdep->is_kvaddr = generic_is_kvaddr;
> + machdep->is_kvaddr = arm64_is_kvaddr;
> machdep->kvtop = arm64_kvtop;
>
> /* The defaults */
> @@ -1023,7 +1059,7 @@ arm64_dump_machdep_table(ulong arg)
> fprintf(fp, " dis_filter: arm64_dis_filter()\n");
> fprintf(fp, " cmd_mach: arm64_cmd_mach()\n");
> fprintf(fp, " get_smp_cpus: arm64_get_smp_cpus()\n");
> - fprintf(fp, " is_kvaddr: generic_is_kvaddr()\n");
> + fprintf(fp, " is_kvaddr: arm64_is_kvaddr()\n");
> fprintf(fp, " is_uvaddr: arm64_is_uvaddr()\n");
> fprintf(fp, " value_to_symbol:
generic_machdep_value_to_symbol()\n");
> fprintf(fp, " init_kernel_pgd: arm64_init_kernel_pgd\n");
> @@ -1642,6 +1678,9 @@ ulong arm64_PTOV(ulong paddr) ulong arm64_VTOP(ulong addr)
{
> + if (is_mte_kvaddr(addr))
> + addr = mte_tag_reset(addr);
> +
> if (machdep->flags & NEW_VMEMMAP) {
> if (machdep->machspec->VA_START &&
> (addr >= machdep->machspec->kimage_text) && @@ -4571,7
+4610,10 @@ int arm64_IS_VMALLOC_ADDR(ulong vaddr) {
> struct machine_specific *ms = machdep->machspec;
> -
> +
> + if (is_mte_kvaddr(vaddr))
> + vaddr = mte_tag_reset(vaddr);
> +
> if ((machdep->flags & NEW_VMEMMAP) &&
> (vaddr >= machdep->machspec->kimage_text) &&
> (vaddr <= machdep->machspec->kimage_end))
> --
> 2.25.1
> --
> Crash-utility mailing list -- devel(a)lists.crash-utility.osci.io
> To unsubscribe send an email to devel-leave(a)lists.crash-utility.osci.io
> https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/
> Contribution Guidelines:
https://github.com/crash-utility/crash/wiki