CHERIoT-Platform/cheriot-rtos

Miscompilation of callback reference

Closed this issue · 0 comments

rmn30 commented

The following test file produces invalid assembly with the current compiler:

__attribute__((cheri_compartment("other"))) void cross_compartment_call(
  __attribute__((cheri_ccallback)) void (*fn)());

__attribute__((cheri_ccallback))  void callback() {}

void test()
{
	cross_compartment_call(&callback);
	cross_compartment_call(&callback);
}

Specifically when compiled with the following command:

/cheriot-tools/bin/clang++ -c -std=c++20 -Qunused-arguments -target riscv32-unknown-unknown -mcpu=cheriot -mabi=cheriot -mxcheri-rvc -mrelax -fshort-wchar -nostdinc -Oz -g -fomit-frame-pointer -fno-builtin -fno-exceptions -fno-asynchronous-unwind-tables -fno-rtti -Werror -cheri-compartment=me -o test.o test.cc

We get the following objdump:

...
00000004 <_Z4testv>:
       4: 7d 71        	cincoffset	csp, csp, -16
       6: 06 e4        	csc	cra, 8(csp)
       8: 22 e0        	csc	cs0, 0(csp)

0000000a <.LBB1_1>:
       a: 17 04 00 00  	auipcc	cs0, 0
       e: 5b 14 04 00  	cincoffset	cs0, cs0, 0
      12: 03 33 04 00  	clc	ct1, 0(cs0)

00000016 <.LBB1_2>:
      16: 17 05 00 00  	auipcc	ca0, 0
      1a: 5b 15 05 00  	cincoffset	ca0, ca0, 0

0000001e <.LBB1_3>:
      1e: 97 03 00 00  	auipcc	ct2, 0
      22: 83 b3 03 00  	clc	ct2, 0(ct2)
      26: 82 93        	cjalr	ct2

00000028 <.LBB1_4>:
      28: 17 05 00 00  	auipcc	ca0, 0
      2c: 5b 15 05 00  	cincoffset	ca0, ca0, 0
      30: 08 61        	clc	ca0, 0(ca0)
      32: 03 33 04 00  	clc	ct1, 0(cs0)

00000036 <.LBB1_5>:
      36: 97 03 00 00  	auipcc	ct2, 0
      3a: 83 b3 03 00  	clc	ct2, 0(ct2)
      3e: 82 93        	cjalr	ct2
      40: 02 64        	clc	cs0, 0(csp)
      42: a2 60        	clc	cra, 8(csp)
      44: 41 61        	cincoffset	csp, csp, 16
      46: 82 80        	cret

Note that initialising ca0 for the first cross compartment call (0x16 .. 0x1a) uses a different sequence than for the second call (0x28 .. 0x30).
The first one is broken as it is passing an unsealed capability to the callback instead of an import table entry as the second one does.