Skip to content

Commit

Permalink
c18n: Make RTLD export the compartment array to the kernel
Browse files Browse the repository at this point in the history
  • Loading branch information
dpgao committed Jan 9, 2025
1 parent 92b2fda commit 896ce61
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 12 deletions.
33 changes: 24 additions & 9 deletions libexec/rtld-elf/rtld_c18n.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ const char *ld_compartment_stats;
/* Export count of compartment switches to statistics */
const char *ld_compartment_switch_count;

/* Compartmentalisation information exported to the kernel */
static struct cheri_c18n_info *c18n_info;
struct rtld_c18n_stats *c18n_stats;

#define INC_NUM_COMPART (c18n_stats->rcs_compart++, comparts.size++)
Expand Down Expand Up @@ -242,7 +244,8 @@ string_base_search(const struct string_base *sb, const char *str)

struct compart {
/*
* Name of the compartment
* Name of the compartment. Must be the first field to enable kernel
* access to compartment information.
*/
const char *name;
/*
Expand Down Expand Up @@ -296,9 +299,15 @@ expand_comparts_data(compart_id_t capacity)
{
struct compart *data;

atomic_fetch_add_explicit(&c18n_info->comparts_gen, 1,
memory_order_acq_rel);

data = c18n_realloc(comparts.data, sizeof(*data) * capacity);
comparts.data = r_debug.r_comparts = data;
comparts.data = c18n_info->comparts = r_debug.r_comparts = data;
comparts.capacity = capacity;

atomic_fetch_add_explicit(&c18n_info->comparts_gen, 1,
memory_order_acq_rel);
}

static struct compart *
Expand All @@ -312,12 +321,18 @@ add_comparts_data(const char *name)
if (comparts.size == comparts.capacity)
expand_comparts_data(comparts.capacity * 2);

atomic_fetch_add_explicit(&c18n_info->comparts_gen, 1,
memory_order_acq_rel);
GDB_COMPARTS_STATE(RCT_ADD, NULL);

com = &comparts.data[INC_NUM_COMPART];
*com = (struct compart) {
.name = name
};
r_debug.r_comparts_size = comparts.size;
c18n_info->comparts_size = r_debug.r_comparts_size = comparts.size;

atomic_fetch_add_explicit(&c18n_info->comparts_gen, 1,
memory_order_acq_rel);
GDB_COMPARTS_STATE(RCT_CONSISTENT, com);

return (com);
Expand Down Expand Up @@ -1590,7 +1605,6 @@ c18n_init(Obj_Entry *obj_rtld, Elf_Auxinfo *aux_info[])
int fd;
char *file;
struct stat st;
struct cheri_c18n_info *info;

/*
* Create memory mapping for compartmentalisation statistics.
Expand All @@ -1616,13 +1630,14 @@ c18n_init(Obj_Entry *obj_rtld, Elf_Auxinfo *aux_info[])
memory_order_release);

if (aux_info[AT_CHERI_C18N] != NULL) {
info = aux_info[AT_CHERI_C18N]->a_un.a_ptr;
*info = (struct cheri_c18n_info) {
c18n_info = aux_info[AT_CHERI_C18N]->a_un.a_ptr;
*c18n_info = (struct cheri_c18n_info) {
.stats_size = sizeof(*c18n_stats),
.stats = c18n_stats
.stats = c18n_stats,
.comparts_entry_size = sizeof(*comparts.data)
};
atomic_store_explicit(&info->version, CHERI_C18N_INFO_VERSION,
memory_order_release);
atomic_store_explicit(&c18n_info->version,
CHERI_C18N_INFO_VERSION, memory_order_release);
}

/*
Expand Down
25 changes: 22 additions & 3 deletions sys/cheri/c18n.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2024 Dapeng Gao
* Copyright (c) 2024 Capabilities Limited
*
* This software was developed by SRI International, the University of
* Cambridge Computer Laboratory (Department of Computer Science and
* Technology), and Capabilities Limited under Defense Advanced Research
* Projects Agency (DARPA) Contract No. FA8750-24-C-B047 ("DEC").
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
Expand Down Expand Up @@ -44,7 +50,7 @@
* initialised.
*/
struct rtld_c18n_stats {
_Atomic(uint8_t) version;
_Atomic(size_t) version;
size_t rcs_compart;
_Atomic(size_t) rcs_ustack;
_Atomic(size_t) rcs_tramp;
Expand All @@ -58,12 +64,25 @@ struct rtld_c18n_stats {
* information. The version field doubles as a synchronisation flag where a
* non-zero value indicates that the other fields have been initialised.
*/
#define CHERI_C18N_INFO_VERSION 1
#define CHERI_C18N_INFO_VERSION 2

struct cheri_c18n_info {
_Atomic(uint8_t) version;
_Atomic(size_t) version;

size_t stats_size;
struct rtld_c18n_stats * __kerncap stats;

/*
* Since the `comparts` array may be reallocated or ortherwise change
* whilst the kernel is reading it, the generation counter allows the
* kernel to identify such races. An even value indicates that the
* array and size data are in a consistent state, and an odd value
* indicates that the data may be inconsistent.
*/
_Atomic(size_t) comparts_gen;
size_t comparts_size;
size_t comparts_entry_size;
void * __kerncap comparts;
};

#ifndef IN_RTLD
Expand Down

0 comments on commit 896ce61

Please sign in to comment.