Skip to content

Commit

Permalink
This example demonstrates a simple overflow of a
Browse files Browse the repository at this point in the history
pointer that has had 0x1001 bytes allocated using malloc().
It shows the expected behaviours in three different CHERI environments,
displaying a message to the user immediately before the program is
expected to crash in each respective environment: riscv64-purecap,
morello-purecap and morello-hybrid. The program can also be compiled
and run in a non-CHERI environment, but the behaviour is undefined,
so the point at which the program crashes (or whether it crashes) is
unpredictable.
  • Loading branch information
tel3path authored and probablytom committed Nov 14, 2023
1 parent b5bbc06 commit 4a1fc8a
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 1 deletion.
6 changes: 6 additions & 0 deletions compare_platforms/Makefile.morello-hybrid
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copyright (c) 2023 The CapableVMs "CHERI Examples" Contributors.
# SPDX-License-Identifier: MIT OR Apache-2.0

include ../build/Makefile.vars.morello-hybrid
include ../build/Makefile.vars.common
include build/Makefile.review
6 changes: 6 additions & 0 deletions compare_platforms/Makefile.riscv64-purecap
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copyright (c) 2023 The CapableVMs "CHERI Examples" Contributors.
# SPDX-License-Identifier: MIT OR Apache-2.0

include ../build/Makefile.vars.riscv64-purecap
include ../build/Makefile.vars.common
include build/Makefile.review
2 changes: 1 addition & 1 deletion compare_platforms/build/Makefile.review
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Common Makefile for the compare_platforms example.
# This should not be invoked directly.

RUNDIR := $(RUNDIR)/review
RUNDIR := $(RUNDIR)/compare_platforms
HFILES := $(wildcard include/*.h) $(wildcard ../include/*.h)
export

Expand Down
146 changes: 146 additions & 0 deletions compare_platforms/compare_platforms_overflow.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* This example demonstrates a simple overflow of a pointer that has had
* 0x1001 bytes allocated using malloc(). It shows the expected behaviours
* in three different CHERI environments, displaying a message to the user
* immediately before the program is expected to crash in each respective
* environment:
*
* - riscv64-purecap
* - morello-purecap
* - morello-hybrid
*
* The program can also be compiled and run in a non-CHERI environment,
* but the behaviour is undefined, so the point at which the program crashes
* (or whether it crashes) is unpredictable.
*/

#ifdef __CHERI_PURE_CAPABILITY__
#include "../include/common.h"
#endif

#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct review
{
char *publicreview;
char *permissions;
};

void print_details(struct review *rv)
{
printf("Public Review: %s\n", rv->publicreview);
printf("Permissions: %s\n", rv->permissions);
fflush(stdout);
}

void overflow_publicreview(size_t offset, size_t reps, size_t overflow_amt, struct review *rv)
{
printf("\nOverflowing publicreview by %zx\n", overflow_amt);
memset(rv->publicreview + offset, 'w', reps);
printf("Permissions: %s\n", rv->permissions);
fflush(stdout);
}

char *min(char *a, char *b)
{
return (a > b ? b : a);
}

char *max(char *a, char *b)
{
return (a > b ? a : b);
}

void assert_positions(char *publicreview, char *permissions, size_t smsz, size_t bigsz)
{
if (min(publicreview, permissions) == publicreview)
{
assert((publicreview + bigsz) <= permissions);
}
else
{
assert((permissions + smsz) <= publicreview);
}
}

void free_pointers(struct review *rv)
{
free(rv->publicreview);
free(rv->permissions);
}

int main(int argc, char *argv[])
{
// initialization values for struct member sizes
const size_t smallsz = 0x20;
const size_t biggersz = 0x1001;

struct review review;

char *publicreview = malloc(biggersz);
review.publicreview = strcpy(
publicreview, "I am a little unclear as to the contribution. I think the authors could "
"strengthen their case considerably if they conducted an RCT. Weak reject.");

char *permissions = malloc(smallsz);
review.permissions = strcpy(permissions, "r");

print_details(&review);

// Just to prove that the allocated spaces of the pointers are not
// overlapping before we attempt to overflow them:
assert_positions(publicreview, permissions, smallsz, biggersz);

#if (!defined(__CHERI_CAPABILITY_WIDTH__) && !defined(__CHERI_PURE_CAPABILITY__))
printf("\nIn a non-CHERI environment, you should reach this line, after which "
"one of the attempts to overflow may or may not cause a crash.\n"
"This behaviour is undefined, so the timing of the crash is unpredictable, "
"if it happens at all.\n");
#endif

#if ((defined(__CHERI_PURE_CAPABILITY__)) && (defined(__aarch64__)))
printf("\nOn morello-purecap, you should reach this line, then the attempt to overflow by 1 "
"should "
"cause a SIGPROT.\n");
printf("This is because the representable length of 0x%zx bytes is 0x%zx.\n", biggersz,
__builtin_cheri_round_representable_length(biggersz));
#endif

size_t offset = biggersz + 1;
overflow_publicreview(offset, 1, 1, &review);

offset++;
const size_t oversz = review.permissions - review.publicreview + 2 - biggersz;

#if ((defined(__CHERI_PURE_CAPABILITY__)) && (defined(__riscv)))
size_t riscv64_padding = (__builtin_cheri_round_representable_length(biggersz) - offset) + 1;
size_t overflow_amt = ((offset - biggersz) + riscv64_padding);
printf("\nOn riscv64-purecap, you should reach this line, then the attempt to overflow by %zx "
"should "
"cause a SIGPROT.\n",
overflow_amt);
printf("You got this far because the representable length of 0x%zx bytes is 0x%zx.\n", biggersz,
__builtin_cheri_round_representable_length(biggersz));
overflow_publicreview(offset, riscv64_padding, overflow_amt, &review);
#endif

overflow_publicreview(offset, oversz, oversz, &review);

// If we reached this line, we should have acquired write privileges on the review.
print_details(&review);

free_pointers(&review);

#if (defined(__aarch64__) && defined(__CHERI_CAPABILITY_WIDTH__) && \
!defined(__CHERI_PURE_CAPABILITY__))
printf("\nOn morello-hybrid, you should make it all the way to the end without crashing.\n");
#endif

return 0;
}
2 changes: 2 additions & 0 deletions tests/run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ if [ "$1" = "riscv64" ] || [ "$1" = "morello-purecap" ]; then
run to_fail capability_sharing/cap-to-file cap_to_file
run to_fail capability_sharing/leak-capability leak-capability
run to_fail capability_sharing/mmap-shared-vs-private shared_file_main
run to_fail compare_platforms compare_platforms_overflow
run to_fail compare_platforms compare_platforms_read_only
elif [ "$1" = "morello-hybrid" ]; then
# HYBRID TESTS
Expand All @@ -80,6 +81,7 @@ elif [ "$1" = "morello-hybrid" ]; then
run to_fail hybrid/compartment_examples/inter_comp_call/malicious_compartments inter_comp_call-secure-redirect_clr
run to_fail hybrid/compartment_examples/inter_comp_call/malicious_compartments inter_comp_call-secure-update_ddc
# Tests that should pass
run OK compare_platforms compare_platforms_overflow
run OK hybrid/ddc_compartment_switching ddc_compartment_switching
run OK hybrid basic_ddc
run OK hybrid/compartment_examples/inter_comp_call/base main
Expand Down

0 comments on commit 4a1fc8a

Please sign in to comment.