diff --git a/libexec/rtld-elf/aarch64/rtld_cheri_machdep.h b/libexec/rtld-elf/aarch64/rtld_cheri_machdep.h new file mode 100644 index 000000000000..dbe6268cb614 --- /dev/null +++ b/libexec/rtld-elf/aarch64/rtld_cheri_machdep.h @@ -0,0 +1,122 @@ +/*- + * Copyright 2018-2020 Alex Richardson + * Copyright 2020 Jessica Clarke + * Copyright 2020 Brett F. Gutstein + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory (Department of Computer Science and + * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the + * DARPA SSITH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef RTLD_CHERI_MACHDEP_H +#define RTLD_CHERI_MACHDEP_H 1 + +#define FUNC_PTR_REMOVE_PERMS \ + (CHERI_PERM_SEAL | CHERI_PERM_STORE | CHERI_PERM_STORE_CAP | \ + CHERI_PERM_STORE_LOCAL_CAP) + +#define DATA_PTR_REMOVE_PERMS \ + (CHERI_PERM_SEAL | CHERI_PERM_EXECUTE) + +#define CAP_RELOC_REMOVE_PERMS \ + (CHERI_PERM_SW_VMEM) + +#ifdef __CHERI_PURE_CAPABILITY__ +/* TODO: ABIs with tight bounds */ +#define can_use_tight_pcc_bounds(obj) ((void)(obj), false) +#endif + +/* + * Create a pointer to a function. + */ +static inline dlfunc_t __capability +make_code_cap(const Elf_Sym *def, const struct Struct_Obj_Entry *defobj, + bool tight_bounds, size_t addend) +{ + const void * __capability ret; + + ret = get_codesegment_cap(defobj) + def->st_value; + /* Remove store and seal permissions */ + ret = cheri_clearperm(ret, FUNC_PTR_REMOVE_PERMS); + if (tight_bounds) { + ret = cheri_setbounds(ret, def->st_size); + } + /* + * Note: The addend is required for C++ exceptions since capabilities + * for catch blocks point to the middle of a function. + */ + ret = cheri_incoffset(ret, addend); + /* All code pointers should be sentries: */ + ret = __builtin_cheri_seal_entry(ret); + return __DECONST_CAP(dlfunc_t __capability, ret); +} + +/* + * Create a function pointer that can be called anywhere + */ +static inline dlfunc_t __capability +make_function_cap_with_addend(const Elf_Sym *def, + const struct Struct_Obj_Entry *defobj, size_t addend) +{ + /* TODO: ABIs with tight bounds */ + return make_code_cap(def, defobj, /*tight_bounds=*/false, addend); +} + +static inline dlfunc_t __capability +make_function_cap(const Elf_Sym *def, const struct Struct_Obj_Entry *defobj) +{ + return make_function_cap_with_addend(def, defobj, /*addend=*/0); +} + +static inline void * __capability +make_data_cap(const Elf_Sym *def, const struct Struct_Obj_Entry *defobj) +{ + void * __capability ret; + ret = get_datasegment_cap(defobj) + def->st_value; + /* Remove execute and seal permissions */ + ret = cheri_clearperm(ret, DATA_PTR_REMOVE_PERMS); + ret = cheri_setbounds(ret, def->st_size); + return ret; +} + +#define set_bounds_if_nonnull(cap, size) \ + do { if (cap) { cap = cheri_setbounds(cap, size); } } while(0) + +#ifdef __CHERI_PURE_CAPABILITY__ +static inline void +fix_obj_mapping_cap_permissions(Obj_Entry *obj, const char *path __unused) +{ + obj->text_rodata_cap = (const char*)cheri_clearperm(obj->text_rodata_cap, FUNC_PTR_REMOVE_PERMS); + obj->relocbase = (char*)cheri_clearperm(obj->relocbase, DATA_PTR_REMOVE_PERMS); + obj->mapbase = (char*)cheri_clearperm(obj->mapbase, DATA_PTR_REMOVE_PERMS); +} +#endif + +#endif diff --git a/libexec/rtld-elf/aarch64/rtld_machdep.h b/libexec/rtld-elf/aarch64/rtld_machdep.h index e6358d84e47a..2d395232397f 100644 --- a/libexec/rtld-elf/aarch64/rtld_machdep.h +++ b/libexec/rtld-elf/aarch64/rtld_machdep.h @@ -67,81 +67,6 @@ uintptr_t reloc_jmpslot(uintptr_t *where, uintptr_t target, const struct Struct_Obj_Entry *defobj, const struct Struct_Obj_Entry *obj, const Elf_Rel *rel); -#if __has_feature(capabilities) - -#define FUNC_PTR_REMOVE_PERMS \ - (CHERI_PERM_SEAL | CHERI_PERM_STORE | CHERI_PERM_STORE_CAP | \ - CHERI_PERM_STORE_LOCAL_CAP) - -#define DATA_PTR_REMOVE_PERMS \ - (CHERI_PERM_SEAL | CHERI_PERM_EXECUTE) - -#define CAP_RELOC_REMOVE_PERMS \ - (CHERI_PERM_SW_VMEM) - -#ifdef __CHERI_PURE_CAPABILITY__ -/* TODO: ABIs with tight bounds */ -#define can_use_tight_pcc_bounds(obj) ((void)(obj), false) -#endif - -/* - * Create a pointer to a function. - */ -static inline dlfunc_t __capability -make_code_cap(const Elf_Sym *def, const struct Struct_Obj_Entry *defobj, - bool tight_bounds, size_t addend) -{ - const void * __capability ret; - - ret = get_codesegment_cap(defobj) + def->st_value; - /* Remove store and seal permissions */ - ret = cheri_clearperm(ret, FUNC_PTR_REMOVE_PERMS); - if (tight_bounds) { - ret = cheri_setbounds(ret, def->st_size); - } - /* - * Note: The addend is required for C++ exceptions since capabilities - * for catch blocks point to the middle of a function. - */ - ret = cheri_incoffset(ret, addend); - /* All code pointers should be sentries: */ - ret = __builtin_cheri_seal_entry(ret); - return __DECONST_CAP(dlfunc_t __capability, ret); -} - -/* - * Create a function pointer that can be called anywhere - */ -static inline dlfunc_t __capability -make_function_cap_with_addend(const Elf_Sym *def, - const struct Struct_Obj_Entry *defobj, size_t addend) -{ - /* TODO: ABIs with tight bounds */ - return make_code_cap(def, defobj, /*tight_bounds=*/false, addend); -} - -static inline dlfunc_t __capability -make_function_cap(const Elf_Sym *def, const struct Struct_Obj_Entry *defobj) -{ - return make_function_cap_with_addend(def, defobj, /*addend=*/0); -} - -static inline void * __capability -make_data_cap(const Elf_Sym *def, const struct Struct_Obj_Entry *defobj) -{ - void * __capability ret; - ret = get_datasegment_cap(defobj) + def->st_value; - /* Remove execute and seal permissions */ - ret = cheri_clearperm(ret, DATA_PTR_REMOVE_PERMS); - ret = cheri_setbounds(ret, def->st_size); - return ret; -} - -#define set_bounds_if_nonnull(cap, size) \ - do { if (cap) { cap = cheri_setbounds(cap, size); } } while(0) - -#endif /* __has_feature(capabilities) */ - #ifdef __CHERI_PURE_CAPABILITY__ #define make_function_pointer(def, defobj) \ @@ -218,14 +143,4 @@ extern void *__tls_get_addr(tls_index *ti); #define md_abi_variant_hook(x) -#ifdef __CHERI_PURE_CAPABILITY__ -static inline void -fix_obj_mapping_cap_permissions(Obj_Entry *obj, const char *path __unused) -{ - obj->text_rodata_cap = (const char*)cheri_clearperm(obj->text_rodata_cap, FUNC_PTR_REMOVE_PERMS); - obj->relocbase = (char*)cheri_clearperm(obj->relocbase, DATA_PTR_REMOVE_PERMS); - obj->mapbase = (char*)cheri_clearperm(obj->mapbase, DATA_PTR_REMOVE_PERMS); -} -#endif - #endif diff --git a/libexec/rtld-elf/riscv/rtld_cheri_machdep.h b/libexec/rtld-elf/riscv/rtld_cheri_machdep.h new file mode 100644 index 000000000000..e6f4f8defe22 --- /dev/null +++ b/libexec/rtld-elf/riscv/rtld_cheri_machdep.h @@ -0,0 +1,123 @@ +/*- + * Copyright 2018-2020 Alex Richardson + * Copyright 2020 Jessica Clarke + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef RTLD_CHERI_MACHDEP_H +#define RTLD_CHERI_MACHDEP_H 1 + +#define FUNC_PTR_REMOVE_PERMS \ + (CHERI_PERM_SEAL | CHERI_PERM_STORE | CHERI_PERM_STORE_CAP | \ + CHERI_PERM_STORE_LOCAL_CAP) + +#define DATA_PTR_REMOVE_PERMS \ + (CHERI_PERM_SEAL | CHERI_PERM_EXECUTE) + +#define CAP_RELOC_REMOVE_PERMS \ + (CHERI_PERM_SW_VMEM) + +#ifdef __CHERI_PURE_CAPABILITY__ +/* TODO: ABIs with tight bounds */ +#define can_use_tight_pcc_bounds(obj) ((void)(obj), false) +#endif + +/* + * Create a pointer to a function. + * Important: this is not necessarily callable! For ABIs with tight bounds we + * need to load CGP first -> use make_function_pointer() instead. + */ +static inline dlfunc_t __capability +make_code_cap(const Elf_Sym *def, const struct Struct_Obj_Entry *defobj, + bool tight_bounds, size_t addend) +{ + const void * __capability ret; + + ret = get_codesegment_cap(defobj) + def->st_value; + /* Remove store and seal permissions */ + ret = cheri_clearperm(ret, FUNC_PTR_REMOVE_PERMS); + if (tight_bounds) { + ret = cheri_setbounds(ret, def->st_size); + } + /* + * Note: The addend is required for C++ exceptions since capabilities + * for catch blocks point to the middle of a function. + */ + ret = cheri_incoffset(ret, addend); + /* All code pointers should be sentries: */ + ret = __builtin_cheri_seal_entry(ret); + return __DECONST_CAP(dlfunc_t __capability, ret); +} + +/* + * Create a function pointer that can be called anywhere + */ +static inline dlfunc_t __capability +make_function_cap_with_addend(const Elf_Sym *def, + const struct Struct_Obj_Entry *defobj, size_t addend) +{ + /* TODO: ABIs with tight bounds */ + return make_code_cap(def, defobj, /*tight_bounds=*/false, addend); +} + +static inline dlfunc_t __capability +make_function_cap(const Elf_Sym *def, const struct Struct_Obj_Entry *defobj) +{ + return make_function_cap_with_addend(def, defobj, /*addend=*/0); +} + +static inline void * __capability +make_data_cap(const Elf_Sym *def, const struct Struct_Obj_Entry *defobj) +{ + void * __capability ret; + ret = get_datasegment_cap(defobj) + def->st_value; + /* Remove execute and seal permissions */ + ret = cheri_clearperm(ret, DATA_PTR_REMOVE_PERMS); + ret = cheri_setbounds(ret, def->st_size); + return ret; +} + +#define set_bounds_if_nonnull(cap, size) \ + do { if (cap) { cap = cheri_setbounds(cap, size); } } while(0) + +#ifdef __CHERI_PURE_CAPABILITY__ +static inline void +fix_obj_mapping_cap_permissions(Obj_Entry *obj, const char *path __unused) +{ + obj->text_rodata_cap = (const char*)cheri_clearperm(obj->text_rodata_cap, FUNC_PTR_REMOVE_PERMS); + obj->relocbase = (char*)cheri_clearperm(obj->relocbase, DATA_PTR_REMOVE_PERMS); + obj->mapbase = (char*)cheri_clearperm(obj->mapbase, DATA_PTR_REMOVE_PERMS); + /* Purecap code also needs the capmode flag */ + obj->text_rodata_cap = cheri_setflags(obj->text_rodata_cap, CHERI_FLAGS_CAP_MODE); +} +#endif + +#endif diff --git a/libexec/rtld-elf/riscv/rtld_machdep.h b/libexec/rtld-elf/riscv/rtld_machdep.h index aefc352efa24..2e7fd694803d 100644 --- a/libexec/rtld-elf/riscv/rtld_machdep.h +++ b/libexec/rtld-elf/riscv/rtld_machdep.h @@ -67,83 +67,6 @@ uintptr_t reloc_jmpslot(uintptr_t *where, uintptr_t target, const struct Struct_Obj_Entry *defobj, const struct Struct_Obj_Entry *obj, const Elf_Rel *rel); -#if __has_feature(capabilities) - -#define FUNC_PTR_REMOVE_PERMS \ - (CHERI_PERM_SEAL | CHERI_PERM_STORE | CHERI_PERM_STORE_CAP | \ - CHERI_PERM_STORE_LOCAL_CAP) - -#define DATA_PTR_REMOVE_PERMS \ - (CHERI_PERM_SEAL | CHERI_PERM_EXECUTE) - -#define CAP_RELOC_REMOVE_PERMS \ - (CHERI_PERM_SW_VMEM) - -#ifdef __CHERI_PURE_CAPABILITY__ -/* TODO: ABIs with tight bounds */ -#define can_use_tight_pcc_bounds(obj) ((void)(obj), false) -#endif - -/* - * Create a pointer to a function. - * Important: this is not necessarily callable! For ABIs with tight bounds we - * need to load CGP first -> use make_function_pointer() instead. - */ -static inline dlfunc_t __capability -make_code_cap(const Elf_Sym *def, const struct Struct_Obj_Entry *defobj, - bool tight_bounds, size_t addend) -{ - const void * __capability ret; - - ret = get_codesegment_cap(defobj) + def->st_value; - /* Remove store and seal permissions */ - ret = cheri_clearperm(ret, FUNC_PTR_REMOVE_PERMS); - if (tight_bounds) { - ret = cheri_setbounds(ret, def->st_size); - } - /* - * Note: The addend is required for C++ exceptions since capabilities - * for catch blocks point to the middle of a function. - */ - ret = cheri_incoffset(ret, addend); - /* All code pointers should be sentries: */ - ret = __builtin_cheri_seal_entry(ret); - return __DECONST_CAP(dlfunc_t __capability, ret); -} - -/* - * Create a function pointer that can be called anywhere - */ -static inline dlfunc_t __capability -make_function_cap_with_addend(const Elf_Sym *def, - const struct Struct_Obj_Entry *defobj, size_t addend) -{ - /* TODO: ABIs with tight bounds */ - return make_code_cap(def, defobj, /*tight_bounds=*/false, addend); -} - -static inline dlfunc_t __capability -make_function_cap(const Elf_Sym *def, const struct Struct_Obj_Entry *defobj) -{ - return make_function_cap_with_addend(def, defobj, /*addend=*/0); -} - -static inline void * __capability -make_data_cap(const Elf_Sym *def, const struct Struct_Obj_Entry *defobj) -{ - void * __capability ret; - ret = get_datasegment_cap(defobj) + def->st_value; - /* Remove execute and seal permissions */ - ret = cheri_clearperm(ret, DATA_PTR_REMOVE_PERMS); - ret = cheri_setbounds(ret, def->st_size); - return ret; -} - -#define set_bounds_if_nonnull(cap, size) \ - do { if (cap) { cap = cheri_setbounds(cap, size); } } while(0) - -#endif /* __has_feature(capabilities) */ - #ifdef __CHERI_PURE_CAPABILITY__ #define make_function_pointer(def, defobj) \ @@ -207,16 +130,4 @@ extern void *__tls_get_addr(tls_index* ti); #define md_abi_variant_hook(x) -#ifdef __CHERI_PURE_CAPABILITY__ -static inline void -fix_obj_mapping_cap_permissions(Obj_Entry *obj, const char *path __unused) -{ - obj->text_rodata_cap = (const char*)cheri_clearperm(obj->text_rodata_cap, FUNC_PTR_REMOVE_PERMS); - obj->relocbase = (char*)cheri_clearperm(obj->relocbase, DATA_PTR_REMOVE_PERMS); - obj->mapbase = (char*)cheri_clearperm(obj->mapbase, DATA_PTR_REMOVE_PERMS); - /* Purecap code also needs the capmode flag */ - obj->text_rodata_cap = cheri_setflags(obj->text_rodata_cap, CHERI_FLAGS_CAP_MODE); -} -#endif - #endif diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index 32790aa00ec2..02f0f5e19e65 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -58,7 +58,17 @@ #include #endif +#ifdef CHERI_LIB_C18N +/* + * This environment variable is exposed here so that tls.h can see it. + */ +extern bool ld_compartment_enable; + +#define C18N_ENABLED ld_compartment_enable +#endif + #include "rtld_lock.h" +#include "rtld_machdep.h" __BEGIN_DECLS @@ -449,15 +459,6 @@ void dump_Elf_Rel(Obj_Entry *, const Elf_Rel *, u_long); void dump_Elf_Rela(Obj_Entry *, const Elf_Rela *, u_long); #ifdef __CHERI_PURE_CAPABILITY__ -#ifdef CHERI_LIB_C18N -/* - * This environment variable is exposed here so that tls.h can see it. - */ -extern bool ld_compartment_enable; - -#define C18N_ENABLED ld_compartment_enable -#endif - /* TODO: we should have a separate member for .text/rodata */ #define get_codesegment_cap(obj) \ (cheri_clearperm((obj)->text_rodata_cap, CAP_RELOC_REMOVE_PERMS)) @@ -478,10 +479,12 @@ extern bool ld_compartment_enable; __END_DECLS -/* rtld_machdep.h depends on struct Obj_Entry and _rtld_error() */ -#include "rtld_machdep.h" +#if __has_feature(capabilities) +/* rtld_cheri_machdep.h depends on struct Obj_Entry and _rtld_error() */ +#include "rtld_cheri_machdep.h" +#endif -/* Archictectures other than CHERI can just call the pointer */ +/* Architectures other than CHERI can just call the pointer */ #ifndef call_init_array_pointer #define call_init_array_pointer(obj, target) call_init_pointer(obj, (target).value) #endif