Skip to content

Commit

Permalink
Update GDB examples for CHERI GDB 12.
Browse files Browse the repository at this point in the history
  • Loading branch information
bsdjhb committed Dec 20, 2022
1 parent eb099b2 commit 4540741
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 129 deletions.
102 changes: 53 additions & 49 deletions src/exercises/adapt-c/answers.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

2. Example output:
```
# ./tools/ccc riscv64 -o /build/cat-cheri ./src/exercises/adapt-c/cat/cat.c ./src/exercises/adapt-c/cat/methods.c
# ./tools/ccc riscv64 -o /build/cat-baseline ./src/exercises/adapt-c/cat/cat.c ./src/exercises/adapt-c/cat/methods.c
Running: /output/sdk/bin/clang -target riscv64-unknown-freebsd -march=rv64gc -mabi=lp64d -mno-relax --sysroot=/output/sdk/sysroot-riscv64-purecap -g -O2 -fuse-ld=lld -Wall -Wcheri -o /build/cat-cheri ./src/exercises/adapt-c/cat/cat.c ./src/exercises/adapt-c/cat/methods.c
# ./tools/ccc riscv64-purecap -o /build/cat-cheri ./src/exercises/adapt-c/cat/cat.c ./src/exercises/adapt-c/cat/methods.c
Running: /output/sdk/bin/clang -target riscv64-unknown-freebsd -march=rv64gcxcheri -mabi=l64pc128d -mno-relax --sysroot=/output/sdk/sysroot-riscv64-purecap -g -O2 -fuse-ld=lld -Wall -Wcheri -o /build/cat-cheri ./src/exercises/adapt-c/cat/cat.c ./src/exercises/adapt-c/cat/methods.c
Expand Down Expand Up @@ -54,23 +54,26 @@
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (write) pending.
(gdb) r /etc/hostid
Starting program: /buildroot/cat-cheri /etc/hostid
Breakpoint 1, write (fd=1, buf=0x40810000, nbytes=37) at /source/cheribsd/lib/libc/sys/write.c:49
49 /source/cheribsd/lib/libc/sys/write.c: No such file or directory.
(gdb) info register ca0 ca1 ca2
Starting program: /root/cat-cheri /etc/hostid
Breakpoint 1, write (fd=<optimized out>, buf=<optimized out>, nbytes=<optimized out>) at /usr/home/john/work/cheri/git/cheribsd/lib/libc/sys/write.c:48
48 __libc_interposing[INTERPOS_write])(fd, buf, nbytes));
```
Even though the debugger believes that the function arguments are
optimized out, from the CHERI-RISC-V calling conventions we know that
the arguments are in the ca0, ca1, and ca2 registers:
```
(gdb) info registers ca0 ca1 ca2
ca0 0x1 0x1
ca1 0x40810000 0x40810000
ca1 0x40802000 0x40802000
ca2 0x25 0x25
(gdb)
(gdb) disassemble
Dump of assembler code for function write:
=> 0x0000000040295dc4 <+0>: auipc a3,0xc2
0x0000000040295dc8 <+4>: lc ca3,1532(a3) # 0x403583c0 <_CHERI_CAPABILITY_TABLE_+2464>
0x0000000040295dcc <+8>: lc ca5,496(a3)
0x0000000040295dd0 <+12>: cjr ca5
=> 0x000000004027fa98 <+0>: auipcc ca3,0xb7
0x000000004027fa9c <+4>: clc ca3,-424(ca3)
0x000000004027faa0 <+8>: clc ca5,496(ca3)
0x000000004027faa4 <+12>: cjr ca5
End of assembler dump.
(gdb)
```
We can see that `write()` was called to write to `stdout` (`ca0`) 37 bytes
(`ca2`) from a buffer with an untagged capability (`ca1`). The `write()` libc
Expand All @@ -82,15 +85,14 @@
4 _write.S: No such file or directory.
(gdb) disassemble
Dump of assembler code for function _write:
=> 0x0000000040299130 <+0>: li t0,4
0x0000000040299132 <+2>: ecall
0x0000000040299136 <+6>: bnez t0,0x4029913e <_write+14>
0x000000004029913a <+10>: cret
0x000000004029913e <+14>: auipc t1,0xffffd
0x0000000040299142 <+18>: cincoffset ct1,ct1,-846
0x0000000040299146 <+22>: cjr ct1
=> 0x0000000040282f40 <+0>: li t0,4
0x0000000040282f42 <+2>: ecall
0x0000000040282f46 <+6>: bnez t0,0x40282f4e <_write+14>
0x0000000040282f4a <+10>: cret
0x0000000040282f4e <+14>: auipcc ct1,0xffffd
0x0000000040282f52 <+18>: cincoffset ct1,ct1,-1166
0x0000000040282f56 <+22>: cjr ct1
End of assembler dump.
(gdb)
```
`write()` jumped to `_write()`, a system call wrapper written in assembly,
that uses the `ecall` instruction to make a system call. Let's see what is
Expand Down Expand Up @@ -145,43 +147,45 @@
```
# gdb-run.sh ./cat-cheri -n /etc/hostid
(...)
Starting program: /buildroot/cat-cheri -n /etc/hostid
Program received signal SIGPROT, CHERI protection violation
Capability tag fault caused by register cs2.
verbose_cat (file=<optimized out>) at ./src/exercises/adapt-c/cat/methods.c:87
87 ./src/exercises/adapt-c/cat/methods.c: No such file or directory.
Thread 1 (LWP 100043 of process 808):
#0 verbose_cat (file=<optimized out>) at ./src/exercises/adapt-c/cat/methods.c:87
#1 do_cat (file=<optimized out>, verbose=<optimized out>) at ./src/exercises/adapt-c/cat/methods.c:214
#2 0x0000000000102f1a in scanfiles (argv=<optimized out>, verbose=<optimized out>) at ./src/exercises/adapt-c/cat/cat.c:172
#3 0x0000000000102d8c in main (argc=<optimized out>, argv=<optimized out>) at ./src/exercises/adapt-c/cat/cat.c:128
(gdb)
Starting program: /root/cat-cheri -n /etc/hostid
Program received signal SIGPROT, CHERI protection violation.
Capability tag fault caused by register cs4.
verbose_cat (file=<optimized out>) at cat/methods.c:87
87 for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
Thread 1 (LWP 100061 of process 2694):
#0 verbose_cat (file=<optimized out>) at cat/methods.c:87
#1 do_cat (file=<optimized out>, verbose=<optimized out>) at cat/methods.c:214
#2 0x0000000000102dca in scanfiles (argv=0x3fbfdff7c0 [rwRW,0x3fbfdff7a0-0x3fbfdff7e0], verbose=<optimized out>) at cat/cat.c:172
#3 0x0000000000102c52 in main (argc=3, argv=0x0) at cat/cat.c:128
```
`gdb` says that `cs2` triggered a CHERI exception:
`gdb` says that `cs4` triggered a CHERI exception:
```
(gdb) info register cs2
cs2 0x4037a400 0x4037a400
(gdb)
(gdb) info register cs4
cs4 0x403545d0 0x403545d0
```
`cs2` holds an untagged capability and the program tries to load a word using
`cs2` which violates CHERI restrictions:
`cs4` holds an untagged capability and the program tries to load a word using
`cs4` which violates CHERI restrictions:
```
(gdb) disassemble $pcc,+4
Dump of assembler code from 0x103094 to 0x103098:
=> 0x0000000000103094 <do_cat+228>: lw a0,16(s2)
Dump of assembler code from 0x102f7e to 0x102f82:
=> 0x0000000000102f7e <do_cat+294>: clw a0,16(cs4)
End of assembler dump.
(gdb)
```
Looking at the above backtrace, we can correlate this output with the source
code and see that `cs2` holds a value of
the `fp` variable:
Looking at the values of local variables, we can see that `cs4` holds the
value of the `fp` variable:
```
(gdb) p fp
$1 = (FILE *) 0x4037a400
(gdb) info locals
fp = 0x403545d0
gobble = 0
line = 0
prev = 10
ch = <optimized out>
wch = <optimized out>
```
It means that for some reason `fp` became an invalid capability.
It means that for some reason `fp` holds an invalid (NULL-derived)
capability.


7. When compiling `cat-cheri`, the compiler printed:
Expand Down
23 changes: 8 additions & 15 deletions src/exercises/buffer-overflow-global/answers.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,15 @@
```
Program received signal SIGPROT, CHERI protection violation
Capability bounds fault caused by register ca4.
fill_buf (
buf=0x104060 <buffer> [rwRW,0x104060-0x1040e0] 'b' <repeats 128 times>,
len=128) at src/exercises/buffer-overflow-global/buffer-overflow-global.c:11
11 in src/exercises/buffer-overflow-global/buffer-overflow-global.c
fill_buf (buf=0x104160 <buffer> [rwRW,0x104160-0x1041e0] 'b' <repeats 128 times>, "c", len=128) at buffer-overflow-global.c:15
15 buf[i] = 'b';
(gdb) info reg ca4
ca4 0xf17d00000439806400000000001040e0 0x1040e0 <c> [rwRW,0x104060-0x1040e0]
ca4 0xf17d00000479816400000000001041e0 0x1041e0 <c> [rwRW,0x104160-0x1041e0]
(gdb) x/i $pcc
=> 0x101cc8 <fill_buf+12>: sb a3,0(a4)
=> 0x101d2c <fill_buf+12>: csb a3,0(ca4)
```
The array has been incremented beyond the end of the allocation as out
of bounds store has been attempted (`Capability bounds fault`).
*Note:* due to deficiencies in the current GDB implementation, the
instruction incorrectly decodes as `sb` rather than correctly as:
```
1cc8: 23 00 d7 00 csb a3, 0(ca4)
```

5. Expected output:
```
Expand All @@ -40,13 +33,13 @@
To see why this occurs, examine the bounds of the buffer in `fill_buf`.
```
(gdb) b fill_buf
Breakpoint 1 at 0x1cc2: file src/exercises/buffer-overflow-global/buffer-overflow-global.c, line 11.
Breakpoint 1 at 0x101d26: file buffer-overflow-global.c, line 15.
(gdb) r
Starting program: /root/buffer-overflow-global-cheri
c = c
Breakpoint 1, fill_buf (buf=0x105000 <buffer> [rwRW,0x105000-0x205800] "",
len=1048577) at src/exercises/buffer-overflow-global/buffer-overflow-global.c:11
11 src/exercises/buffer-overflow-global/buffer-overflow-global.c: No such file or directory.
Breakpoint 1, fill_buf (buf=0x105000 <buffer> [rwRW,0x105000-0x205800] "", len=1048577) at buffer-overflow-global.c:15
15 buf[i] = 'b';
```
This indicates that buffer has been allocated (1024 * 1026) bytes. This
is due to the padding required to ensure that the bounds of `buffer`
Expand Down
38 changes: 18 additions & 20 deletions src/exercises/buffer-overflow-stack/answers.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,22 @@
Program received signal SIGPROT, CHERI protection violation
Capability bounds fault caused by register ca0.
0x0000000000101ce8 in write_buf (buf=<optimized out>, ix=<optimized out>) at ./buffer-overflow-stack.c:13
0x0000000000101cf0 in write_buf (buf=<optimized out>, ix=<optimized out>) at buffer-overflow-stack.c:13
13 buf[ix] = 'b';
Thread 1 (LWP 100044 of process 838):
#0 0x0000000000101ce8 in write_buf (buf=<optimized out>, ix=<optimized out>) at ./buffer-overflow-stack.c:13
#1 0x0000000000101d72 in main () at ./buffer-overflow-stack.c:31
Thread 1 (LWP 100055 of process 829):
#0 0x0000000000101cf0 in write_buf (buf=<optimized out>, ix=<optimized out>) at buffer-overflow-stack.c:13
#1 0x0000000000101d7a in main () at buffer-overflow-stack.c:31
(gdb) disass
Dump of assembler code for function write_buf:
0x0000000000101ce0 <+0>: cincoffset ca0,ca0,a1
0x0000000000101ce4 <+4>: li a1,98
=> 0x0000000000101ce8 <+8>: sb a1,0(a0)
0x0000000000101cec <+12>: ret
0x0000000000101ce8 <+0>: cincoffset ca0,ca0,a1
0x0000000000101cec <+4>: li a1,98
=> 0x0000000000101cf0 <+8>: csb a1,0(ca0)
0x0000000000101cf4 <+12>: cret
End of assembler dump.
```

*Note:* due to deficiencies in the current GDB implementation, the faulting
instruction incorrectly decodes as `sb` rather than correctly as `csb a1,
0(ca0)`. Asking `gdb` about the registers with `info registers` and focusing
Asking `gdb` about the registers with `info registers` and focusing
on the ones involved here, we see
```
a0 0x3fffdfff50 274875809616
Expand All @@ -55,20 +53,20 @@
`disass`embling, we see (eliding irrelevant instructions):
```
(gdb) up
#1 0x0000000000101d72 in main () at ./buffer-overflow-stack.c:31
#1 0x0000000000101d7a in main () at buffer-overflow-stack.c:31
31 write_buf(lower, sizeof(lower));
(gdb) disass
Dump of assembler code for function main:
0x0000000000101cf0 <+0>: cincoffset csp,csp,-144
0x0000000000101cf8 <+0>: cincoffset csp,csp,-144
0x0000000000101d0c <+28>: cincoffset ca0,csp,48
0x0000000000101d10 <+32>: csetbounds cs0,ca0,16
0x0000000000101d14 <+28>: cincoffset ca0,csp,48
0x0000000000101d18 <+32>: csetbounds cs0,ca0,16
0x0000000000101d64 <+116>: li a1,16
0x0000000000101d66 <+118>: cmove ca0,cs0
0x0000000000101d6a <+122>: auipc ra,0x0
0x0000000000101d6e <+126>: jalr -138(ra) # 0x101ce0 <write_buf>
=> 0x0000000000101d72 <+130>: lbu a0,0(s1)
0x0000000000101d6c <+116>: li a1,16
0x0000000000101d6e <+118>: cmove ca0,cs0
0x0000000000101d72 <+122>: auipcc cra,0x0
0x0000000000101d76 <+126>: cjalr -138(cra)
=> 0x0000000000101d7a <+130>: clbu a0,0(cs1)
```
The compiler has arranged for `main` to allocate 144 bytes on the stack by
decrementing the *capability stack pointer* register (`csp`) by 144 bytes.
Expand Down
56 changes: 31 additions & 25 deletions src/exercises/cheri-allocator/answers.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,26 @@
a later call to `alloc_allocate()`:

```
Starting program: /opt/cheri-exercises/cheri-allocator-cheri
Starting program: /root/cheri-allocator
Allocator initialised
Allocating memory
Allocation returned 0x104830
Preparing to overflow 0x104830
Overflowed allocation 0x104830
Freeing allocation 0x104830
Allocation 0x104830 freed
Allocation returned 0x104550
Preparing to overflow 0x104550
Overflowed allocation 0x104550
Freeing allocation 0x104550
Allocation 0x104550 freed
Allocating memory
Allocation returned 0x104830
Allocation returned 0x104550
Allocating memory
Allocation returned 0x1048c0
Allocation returned 0x1045e0
Allocating memory
Program received signal SIGPROT, CHERI protection violation
Capability tag fault caused by register ca2.
0x0000000000102374 in alloc_allocate ()
Program received signal SIGPROT, CHERI protection violation.
Capability tag fault caused by register ca0.
alloc_allocate () at cheri-allocator.c:83
83 alloc_nextfree = alloc->a_next;
(gdb) p alloc
$1 = (struct alloc_storage *) 0x4141414141414141 [,0x4141402800000000-0x414142a000000000] (invalid,sealed)
```

3. When compiling for CHERI C, use `cheri_bounds_set()` to set bounds on the
Expand All @@ -42,16 +45,16 @@ Capability tag fault caused by register ca2.
violation exception on overflow:

```
Starting program: /opt/cheri-exercises/cheri-allocator-cheri
Starting program: /root/cheri-allocator
Allocator initialised
Allocating memory
Allocation returned 0x104840
Preparing to overflow 0x104840
Allocation returned 0x104550
Preparing to overflow 0x104550
Program received signal SIGPROT, CHERI protection violation
Program received signal SIGPROT, CHERI protection violation.
Capability bounds fault caused by register ca3.
memset (dst0=0x1048c0 <alloc_array+144> [rwRW,0x104840-0x1048c0], c0=65,
length=15) at /home/rnw24/cheri/cheribsd/lib/libc/string/memset.c:94
memset (dst0=0x1045d0 <alloc_array+144> [rwRW,0x104550-0x1045d0], c0=65, length=15) at /usr/home/john/work/cheri/git/cheribsd/lib/libc/string/memset.c:94
94 *dst++ = VAL;
```

## Reaching allocator metadata
Expand All @@ -60,18 +63,21 @@ memset (dst0=0x1048c0 <alloc_array+144> [rwRW,0x104840-0x1048c0], c0=65,
due to reaching outside the bounds of the passed memory allocation:

```
Starting program: /opt/cheri-exercises/cheri-allocator-cheri
Starting program: /root/cheri-allocator
Allocator initialised
Allocating memory
Allocation returned 0x1046e0
Freeing allocation 0x1046e0
Allocation returned 0x104420
Freeing allocation 0x104420
Program received signal SIGPROT, CHERI protection violation
Capability bounds fault caused by register ca3.
0x00000000001022fe in alloc_free ()
Program received signal SIGPROT, CHERI protection violation.
Capability bounds fault caused by register cfp.
alloc_free (ptr=<optimized out>) at cheri-allocator.c:106
106 alloc->a_next = alloc_nextfree;
(gdb) bt
#0 0x00000000001022fe in alloc_free ()
#1 0x0000000000101f52 in main ()
#0 alloc_free (ptr=<optimized out>) at cheri-allocator.c:106
#1 main () at cheri-allocator.c:137
(gdb) p alloc
$1 = (struct alloc_storage *) 0x104410 <alloc_array> [rwRW,0x104420-0x1044a0]
```

7. We need to create a new capability, derived from `alloc_array` but with the
Expand Down
15 changes: 8 additions & 7 deletions src/exercises/cheri-tags/answers.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,19 @@
We can ask `gdb` to print out the faulting instruction:
```
(gdb) x/i $pcc
=> 0x101d7c <main+244>: lbu a0,0(s1)
=> 0x101d84 <main+244>: clbu a1,0(cs1)
```

*Note:* due to deficiencies in the current GDB implementation, the faulting
instruction incorrectly decodes as `lbu` with integer operands rather than
correctly as `clbu a0, 0(cs1)`.

We can also ask `gdb` for more information about the signal we received:
```
(gdb) p $_siginfo
$1 = {si_signo = 34, si_errno = 0, si_code = 2, si_pid = 0, si_uid = 0, si_status = 0, si_addr = 0x101d7c <main+244>, si_value = {sival_int = 0, sival_ptr = 0x0}, _reason = {_fault = {si_trapno = 28, si_capreg = 9}, _timer = {si_timerid = 28, si_overrun = 9}, _mesgq = {si_mqd = 28}, _poll = {si_band = 38654705692}, __spare__ = {__spare1__ = 38654705692, __spare2__ = {0, 0, 0, 0, 0, 0, 0}}}}
$1 = {si_signo = 34, si_errno = 0, si_code = 2, si_pid = 0, si_uid = 0,
si_status = 0,
si_addr = 0x101d84 <main+244> [rxR,0x100000-0x104120] (invalid), si_value = {
sival_int = 0, sival_ptr = 0x0}, _reason = {_fault = {si_trapno = 28,
si_capreg = 9}, _timer = {si_timerid = 28, si_overrun = 9}, _mesgq = {
si_mqd = 28}, _poll = {si_band = 38654705692}, __spare__ = {
__spare1__ = 38654705692, __spare2__ = {0, 0, 0, 0, 0, 0, 0}}}}
```
As said, `si_signo = 34` is `SIGPROT`, for which `si_code = 2` is
`PROT_CHERI_TAG`, indicating a missing (clear) tag as an input to a
Expand Down
1 change: 0 additions & 1 deletion src/exercises/cheriabi/answers.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@
ca0 0xd17d00000785b9b40000003fbfdff9b0 0x3fbfdff9b0 [rwRW,0x3fbfdff9b0-0x3fbfdffe10]
pcc 0x4010f040 0x4010f040 <rtld_start>
ddc 0x0 0x0
cap_valid 0x80800003 2155872259
```

6. In baseline programs, the stack is bounded only by operating system measures
Expand Down
2 changes: 1 addition & 1 deletion src/exercises/pointer-revocation/answers.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Capability permission fault caused by register ca2.
0x0000000000102140 in main ()
(gdb) x/i 0x0000000000102140
=> 0x102140 <main+524>: lc ca2,32(a2)
=> 0x102140 <main+524>: clc ca2,32(ca2)
(gdb) p $ca2
$1 = (void *) 0x41200040 [,0x41200040-0x41200080]
Expand Down
Loading

0 comments on commit 4540741

Please sign in to comment.