qemu-arm
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Differing PAC behavior between Qemu and Arm FVP


From: Derrick McKee
Subject: Re: Differing PAC behavior between Qemu and Arm FVP
Date: Tue, 28 Jul 2020 14:15:09 -0400

Here's a minimal test that shows the different behavior, as of master head commit 0a58e39fe90c50b313a5148c095f8dbb6111a6d6.

The output on FVP:

signed_ptr_1 = 0x72ffff94022000 signed_ptr_2 = 0x59ffff94022000 auth_ptr = 0x20ffff94022000
Unmasked pointers DO NOT match
signed_ptr_1 = 0x72ffff94022000 signed_ptr_2 = 0x19ffff94022000 auth_ptr = 0xffff94022000
Unmasked pointers match

The output on Qemu:

signed_ptr_1 = 0x50ffffbe314000 signed_ptr_2 = 0x4affffbe314000 auth_ptr = 0xffffbe314000
Unmasked pointers match
signed_ptr_1 = 0x50ffffbe314000 signed_ptr_2 = 0x4affffbe314000 auth_ptr = 0xffffbe314000
Unmasked pointers match

To compile: clang -g -O0 --target=aarch64-linux-gnu -march=armv8.5-a+memtag --sysroot=/usr/aarch64-linux-gnu/ -L/usr/lib/gcc/aarch64-linux-gnu/10.1.0/

#include <stdio.h>
#include <sys/mman.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <assert.h>

#define ADDRESS_BITS 48
#define ADDRESS_MASK ((uint64_t)(1ul << ADDRESS_BITS) - 1)

typedef enum {
RED = 1,
GREEN = 2
} MTE_Color;

uintptr_t sign_pointer(void* address, uint64_t modifier, bool use_mask) {
uintptr_t addr_to_use;
if(use_mask) {
addr_to_use = ((uintptr_t) address & ADDRESS_MASK);
} else {
addr_to_use = (uintptr_t)address;
}

uintptr_t result;
asm("pacda %[loc], %[mod]"
: "=r"(result)
: [loc] "r"(addr_to_use), [mod] "r"(modifier)
:
  );
return result;
}

uintptr_t auth_pointer(void* address, uint64_t modifier) {
uintptr_t result;
asm("autda %[addr], %[mod]"
: "=r"(result)
: [addr] "r"(address), [mod] "r"(modifier)
:
  );
return result;
}

int main(int argc, char** argv) {
uint8_t *region = (uint8_t*) mmap(NULL, 16, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);

assert(region);

uint64_t modifier_1 = (1ul << 10) | RED;
uintptr_t signed_ptr_1 = sign_pointer(region, modifier_1, false);


uint64_t modifier_2 = (1ul << 10) | GREEN;
uintptr_t signed_ptr_2 = sign_pointer((void*)signed_ptr_1, modifier_2, false);


uintptr_t auth_ptr = auth_pointer((void*)signed_ptr_2, modifier_2);

printf("signed_ptr_1 = 0x%lx\tsigned_ptr_2 = 0x%lx\tauth_ptr = 0x%lx\n",
signed_ptr_1, signed_ptr_2, auth_ptr);

if(auth_ptr == (uintptr_t)region) {
printf("Unmasked pointers match\n");
} else {
printf("Unmasked pointers DO NOT match\n");
}


signed_ptr_1 = sign_pointer(region, modifier_1, true);
signed_ptr_2 = sign_pointer((void*)signed_ptr_1, modifier_2, true);

auth_ptr = auth_pointer((void*)signed_ptr_2, modifier_2);
printf("signed_ptr_1 = 0x%lx\tsigned_ptr_2 = 0x%lx\tauth_ptr = 0x%lx\n",
signed_ptr_1, signed_ptr_2, auth_ptr);


if(auth_ptr == (uintptr_t)region) {
printf("Unmasked pointers match\n");
} else {
printf("Unmasked pointers DO NOT match\n");
}


return 0;
}

On Tue, Jul 28, 2020 at 1:10 PM Derrick McKee <derrick.mckee@gmail.com> wrote:
I'm not quite sure if it matters, but I am also using MTE as well.  My understanding is that the only affect to PAC is that the available signature bits are reduced  But I am definitely getting a valid pointer from the second pacda instruction because the autda instruction succeeds.  My application is kinda convoluted because I was testing out a research idea.  I'll try to come up with a minimal test case, and test it out on the Qemu master head.

On Tue, Jul 28, 2020 at 11:50 AM Richard Henderson <richard.henderson@linaro.org> wrote:
> The scenario: Application signs pointer 0xdeadbeef using the pacda
> instruction to obtain a new pointer 0xXYdeadbeef.  Later, the application
> wants to generate a new PAC signature for 0xdeadbeef, but uses 0xXYdeadbeef
> as the address for the pacda instruction to generate pointer 0xABdeadbeef.
> Finally, the application wants to authenticate using the autda instruction
> using 0xABdeadbeef and the modifier used to generate that pointer.>
> Qemu behavior: The autda instruction succeeds and 0xdeadbeef is returned.
>
> FVP behavior: The autda instruction fails, and an invalid pointer is
> returned.  In order for the autda instruction to succeed, the pointer
> provided to the pacda instruction must have the upper bits set to zero.
>
> Is this a bug, or are we not very concerned about corner cases like these?

Well, actually, if you haven't already gotten an invalid pointer out of step
two (the second pacda) then *that* is a bug.  And an invalid pointer should not
succeed the autda.

So, yes, this does sound like a bug.

I will see if I can create a test case for this, but if you already have one,
that would also be helpful.


r~


--
Derrick McKee
Phone: (703) 957-9362
Email: derrick.mckee@gmail.com


--
Derrick McKee
Phone: (703) 957-9362
Email: derrick.mckee@gmail.com

reply via email to

[Prev in Thread] Current Thread [Next in Thread]