occlum/test/brk/main.c
2023-01-06 22:56:41 +08:00

196 lines
5.6 KiB
C

#include <unistd.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <stdint.h>
#include <sys/mman.h>
#include "test.h"
// ============================================================================
// Helper function
// ============================================================================
#define PAGE_SIZE 4096
const static uint8_t magic_num_01 = 0xFF;
typedef struct syscall_args {
int num;
unsigned long arg0;
} syscall_args_t;
static inline uint64_t native_syscall(syscall_args_t *p) {
uint64_t ret;
register int num asm ("rax") = p->num;
register unsigned long arg0 asm ("rdi") = p->arg0;
asm volatile("syscall"
: "=a" (ret)
: "r" (num), "r" (arg0));
return ret;
}
static uint64_t brk_syscall(uint64_t brk) {
syscall_args_t brk_arg = {
.num = __NR_brk,
.arg0 = brk,
};
return native_syscall(&brk_arg);
}
// ============================================================================
// Test cases for access
// ============================================================================
static int test_brk_shrinks() {
char *zero_buf = malloc(PAGE_SIZE * 2);
if (zero_buf == NULL) {
THROW_ERROR("malloc failed");
}
memset(zero_buf, 0, PAGE_SIZE * 2);
uint64_t original_brk = brk_syscall(0);
if (original_brk == 0) {
THROW_ERROR("sbrk failed");
}
printf("original brk = %lx\n", original_brk);
// increase brk
printf("increase brk\n");
uint64_t ret = brk_syscall(original_brk + PAGE_SIZE * 4);
if (ret == 0) {
THROW_ERROR("extend brk failed");
}
// set some values to the brk memory
uint64_t test_range_start = original_brk + PAGE_SIZE * 2;
for (int i = 0; i < PAGE_SIZE; i++) {
*(int *)test_range_start = magic_num_01;
}
// decrease brk
printf("decrease brk\n");
ret = brk_syscall(original_brk + PAGE_SIZE * 2);
if (ret != test_range_start) {
THROW_ERROR("shrink brk failed");
}
printf("test range start = %lx\n", test_range_start);
// increase brk
uint64_t test_range_end = brk_syscall(original_brk + PAGE_SIZE * 4);
if (test_range_end != original_brk + PAGE_SIZE * 4) {
THROW_ERROR("extend brk failed");
}
if ( memcmp((const void *)test_range_start, zero_buf, PAGE_SIZE * 2) != 0) {
THROW_ERROR("sbrk not reset memory");
}
free(zero_buf);
return 0;
}
#ifdef SGX_MODE_HW
// This test case will fail in simulation mode. Because the raw syscall interface are not handled by Occlum
// in simulation mode.
//
// Use brk to allocate 4 pages and test brk and mprotect
// original brk
// | page 00 page 02
// | page 01 page 03
// ...---|-------|-------|-------|-------|
static int test_brk_shrinks_spans_multiple_chunks() {
const static uint8_t magic_num_02 = 0xFE;
char *zero_buf = malloc(PAGE_SIZE * 4);
if (zero_buf == NULL) {
THROW_ERROR("malloc failed");
}
memset(zero_buf, 0, PAGE_SIZE * 4);
size_t original_brk = brk_syscall(0);
if (original_brk == 0) {
THROW_ERROR("brk failed");
}
printf("original brk = %lx\n", original_brk);
// increase brk to the end of page 03
size_t ret = brk_syscall(original_brk + PAGE_SIZE * 4);
if (ret != original_brk + PAGE_SIZE * 4) {
THROW_ERROR("extend brk failed");
}
// set some values to the brk memory page 02
size_t test_range_start = original_brk + PAGE_SIZE * 2;
for (int i = 0; i < PAGE_SIZE; i++) {
*(int *)test_range_start = magic_num_01;
}
// mprotect page 01 - 03 to PROT_NONE and decrease brk to the end of page 00
int rc = mprotect((void *)(original_brk + PAGE_SIZE * 1), PAGE_SIZE * 3, PROT_NONE);
if (rc < 0) {
THROW_ERROR("mprotect failure");
}
ret = brk_syscall(original_brk + PAGE_SIZE * 1);
if (ret != original_brk + PAGE_SIZE * 1) {
THROW_ERROR("shrink brk failed");
}
// increase brk to the end of page 02
ret = brk_syscall(original_brk + PAGE_SIZE * 3);
if (ret != original_brk + PAGE_SIZE * 3) {
THROW_ERROR("extend brk failed");
}
// set some values to the brk memory page 01
test_range_start = original_brk + PAGE_SIZE * 1;
for (int i = 0; i < PAGE_SIZE; i++) {
*(int *)test_range_start = magic_num_02;
}
// decrease brk again to the end of page 00
rc = mprotect((void *)(original_brk + PAGE_SIZE * 1), PAGE_SIZE * 2, PROT_NONE);
if (rc < 0) {
THROW_ERROR("mprotect failure");
}
ret = brk_syscall(original_brk + PAGE_SIZE * 1);
if (ret != original_brk + PAGE_SIZE * 1) {
THROW_ERROR("shrink brk failed");
}
// increase brk to the end of page 03
ret = brk_syscall(original_brk + PAGE_SIZE * 4);
if (ret != original_brk + PAGE_SIZE * 4) {
THROW_ERROR("extend brk failed");
}
if ( memcmp((const void *)original_brk, zero_buf, PAGE_SIZE * 4) != 0) {
THROW_ERROR("brk not reset memory");
}
// decrease brk to the original brk
ret = brk_syscall(original_brk);
if (ret != original_brk) {
THROW_ERROR("shrink brk failed");
}
free(zero_buf);
return 0;
}
#endif
// ============================================================================
// Test suite main
// ============================================================================
static test_case_t test_cases[] = {
TEST_CASE(test_brk_shrinks),
#ifdef SGX_MODE_HW
TEST_CASE(test_brk_shrinks_spans_multiple_chunks),
#endif
};
int main(int argc, const char *argv[]) {
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
}