/* * Copyright (c) 2023 Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include #include // for dlsym #include #include #include #include "cmpt.h" #include "morello.h" static void* __capability get_csp(){ void* __capability ret; __asm__( "mov %[reg], csp\n" : [reg] "=r" (ret) : : ); return ret; } static void* __capability get_cid_el0(){ void* __capability ret; __asm__( "MRS %[reg], CID_EL0\n" : [reg] "=r" (ret) : : ); return ret; } // static void set_cid_el0(void* __capability set){ // __asm__( // "MSR CID_EL0, %[reg]\n" // : [reg] "=r" (set) // : // : // ); // } static int callback(struct dl_phdr_info *info, size_t size, void *data) { printf("callback():\n"); printf(" Name: \"%s\" (%d segments)\n", info->dlpi_name, info->dlpi_phnum); printf(" - stack (CSP): %#p\n", cheri_csp_get()); printf(" - program counter (PCC): %#p\n", cheri_pcc_get()); printf(" - base address: %#p\n", (void*) info->dlpi_addr); return 0; } void scanCap(void** __capability cap, int depth){ if(depth > 1){ return; } printf("%*sScanning cap: %#p\n", depth * 4, "", cap); size_t len = cheri_length_get(cap); ptraddr_t start = cheri_base_get(cap); void** new_cap = cheri_address_set(cap, start); printf("%*s%#p, valid: (%d)\n\n", depth*4, "", new_cap, cheri_tag_get(new_cap)); if(cheri_tag_get(new_cap) == 0){ return; } for(int i = 0; i < len/sizeof(void*); i+=sizeof(void*)){ access((char*)(new_cap+i), 0); // printf("%*s(access returns: %d, %d: %s)\n", depth * 4, "", access_ret, errno, strerror(errno)); if(errno == 14){ printf("%*s%#p Segfault, avoiding address\n",depth * 4, "", new_cap+i); continue; } void* __capability new = *((void** __capability)new_cap+i); printf("%*s%#p: cap found: %#p\n", depth * 4, "", new_cap+i, new); if(cheri_address_get(new) != 0 && cheri_tag_get(new) == 1 && cheri_base_get(new) != start && cheri_length_get(new) >= sizeof(void*)){ scanCap(new, depth+1); } } printf("\tdone..\n\n"); } int scanStack(){ void* __capability csp = get_csp(); printf("\n\ncomaprt. csp cap: %#p\n", csp); printf("starting scan...\n\n"); size_t len = cheri_length_get(csp); for(int i = 0; i < len/sizeof(void*); i+=sizeof(void*)){ access((char*)(csp-i), 0); //printf("(%#p)(access returns: %d: %s)\n", (csp-i), errno, strerror(errno)); if(errno == 14){ printf("%#p Segfault, avoiding address\n", csp-i); continue; } void* __capability new = *((void** __capability)csp-i); if(cheri_tag_get(new)){ printf("Valid cap found: %#p\n", new); //scanCap(new, 1); } } return 0; } /** * Functions with vulnerability. */ static void *get_password(void *buffer) { // doesn't work if statically compiled // doesn't have access to the stack either. void* dlopen_ret = dlopen(NULL, RTLD_NOW); printf(" - dlopen: %#p\n", dlopen_ret); void* __capability map = *((void** __capability)dlopen_ret); printf(" - map: %#p\n", map); // testing stack walking // void* __capability csp = get_csp(); // printf("csp : %#p\n", csp); printf("\n\n**inside get_password**\n\n"); dl_iterate_phdr(callback, NULL); void* __capability cid = get_cid_el0(); printf("\n\ncompart cid: %#p\n", cid); // don't need to set this to malloc scavenge..? // printf("setting cid...\n"); // __asm__( // "mov x0, 0x0\n" // "MSR CID_EL0, c0\n" // : // : // ); // printf("scanning stack:\n"); // scanStack(); // testing malloc scavenging printf("\nold array addr: %#p\n\n", buffer); for(int i = 0; i < 15; i++){ void** array2 = malloc(sizeof(int*) * 4); //printf("array in compart: %#p\n", array2); if(array2 == buffer){ printf("found copy at iteration %d\n", i); printf("array in compart: %#p\n", array2); printf("deref: %#p\n", array2[0]); int* myInt = array2[0]; *myInt = 0x4141; break; } free(array2); } return buffer; } static int run_with_cmpt(void* oldArray) { init_cmpt_manager(2000); //char authenticated = 0; //char buffer[8]; cmpt_fun_t *get_password_in_cmpt = create_cmpt(get_password, 3 /* pages */, NULL /* use default settings */); if (!get_password_in_cmpt) { perror("create_cmpt"); return 1; } //while(!authenticated) { get_password_in_cmpt(oldArray); //if (check_password(get_password_in_cmpt(oldArray), sizeof(buffer))) { // authenticated = 1; //} //} printf("password check passed: have some biscuits\n"); return 0; } static int run_without_cmpt(void* oldArray) { //char authenticated = 0; //char buffer[8]; get_password(oldArray); /*while(!authenticated) { if (check_password(get_password(oldArray), sizeof(buffer))) { authenticated = 1; } }*/ printf("password check passed: have some biscuits\n"); return 0; } int main(int argc, char *argv[]) { void* dlopen_ret = dlopen(NULL, RTLD_LAZY); printf(" - dlopen: %#p\n", dlopen_ret); if(dlopen_ret == 0){ printf("Error: %s\n", strerror(errno)); } dl_iterate_phdr(callback, NULL); void* __capability csp = get_csp(); printf("maincsp : %#p\n", csp); void* __capability cid = get_cid_el0(); printf("main cid: %#p\n", cid); int myInt = 10; printf("&myInt : %#p\n", &myInt); printf("&myInt: %#p = %d\n", &myInt, myInt); void** array = malloc(sizeof(int*) * 4); void** array2 = malloc(sizeof(int*) * 4); array2[0] = &myInt; printf("a1: %#p\n", array); printf("a2: %#p\n", array2); void* oldArray = array2; free(array2); array2 = malloc(sizeof(int*) * 4); printf("alloc again: %#p\n", array2); // malloc scavenging doesn't work here printf("reading from re-allocated a2: %#p\n", array2[0]); free(array2); run_with_cmpt(oldArray); printf("myInt: %d\n", myInt); if (argc > 1) { switch (argv[1][0]) { case '1': printf("running with compartment...\n"); return run_with_cmpt(oldArray); case '0': default: printf("running without compartment...\n"); return run_without_cmpt(oldArray); } } else { fprintf(stderr, "usage: %s where is either 1 or 0\n", argv[0]); return 1; } }