Skip to content

Commit

Permalink
Prevent memory coalescing memory if cap-bounds do not span full length
Browse files Browse the repository at this point in the history
During a GC sweep, coalescing contiguous memory that spans two separate
system OS allocations (e.g. using mmap()), causes memory leakage in
CHERI systems. This is because the capability used to represent such
coalesced (expanded) memory regions has memory bounds derived from the
original allocation syscall (smaller than the size of the coalesced memory).
To prevent a client being given a capability with invalid bounds, such
coalescing is prevented.

1. Add hblk pointer within header during re-allocation of GC'd memory.
2. Prevent coalescing in either directions when capability bounds do not
   span the size of the coalesced memory.
3. Derive only valid pointers when coalescing memory
  • Loading branch information
Dejice Jacob committed Nov 11, 2021
1 parent 9009e65 commit d8ecfa3
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 1 deletion.
17 changes: 16 additions & 1 deletion allchblk.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#include "private/gc_priv.h"

#include <stdio.h>
#if defined(__CHERI_PURE_CAPABILITY__)
# include <cheriintrin.h>
#endif

#ifdef GC_USE_ENTIRE_HEAP
int GC_use_entire_heap = TRUE;
Expand Down Expand Up @@ -604,6 +607,7 @@ STATIC struct hblk * GC_get_first_part(struct hblk *h, hdr *hhdr,
WARN("Header allocation failed: dropping block\n", 0);
return(0);
}
rest_hdr -> hb_block = rest;
rest_hdr -> hb_sz = total_size - bytes;
rest_hdr -> hb_flags = 0;
# ifdef GC_ASSERTIONS
Expand Down Expand Up @@ -964,6 +968,13 @@ GC_INNER void GC_freehblk(struct hblk *hbp)
/* Coalesce with successor, if possible */
if(0 != nexthdr && HBLK_IS_FREE(nexthdr) && IS_MAPPED(nexthdr)
&& (signed_word)(hhdr -> hb_sz + nexthdr -> hb_sz) > 0
# if defined(__CHERI_PURE_CAPABILITY__)
/* Bounds of capability should span entire coalesced memory */
/* Bounds being larger than blk-size is OK; bounded by the imprecision */
/* of original capability obtained from system memory */
&& (cheri_base_get(hbp) <= cheri_address_get(next))
&& (cheri_base_get(hbp) + cheri_length_get(hbp)) >= (cheri_address_get(next) + nexthdr->hb_sz)
# endif
/* no overflow */) {
GC_remove_from_fl(nexthdr);
hhdr -> hb_sz += nexthdr -> hb_sz;
Expand All @@ -973,7 +984,11 @@ GC_INNER void GC_freehblk(struct hblk *hbp)
if (prev /* != NULL */) { /* CPPCHECK */
prevhdr = HDR(prev);
if (IS_MAPPED(prevhdr)
&& (signed_word)(hhdr -> hb_sz + prevhdr -> hb_sz) > 0) {
&& (signed_word)(hhdr -> hb_sz + prevhdr -> hb_sz) > 0
# if defined(__CHERI_PURE_CAPABILITY__)
&& (cheri_base_get(hbp) <= cheri_address_get(prev))
# endif
/* no overflow */ ) {
GC_remove_from_fl(prevhdr);
prevhdr -> hb_sz += hhdr -> hb_sz;
# ifdef USE_MUNMAP
Expand Down
4 changes: 4 additions & 0 deletions headers.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,13 @@ GC_INNER struct hblk * GC_prev_block(struct hblk *h)
} else if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
j -= (signed_word)hhdr;
} else {
#if !defined(__CHERI_PURE_CAPABILITY__)
return((struct hblk *)
(((bi -> key << LOG_BOTTOM_SZ) + j)
<< LOG_HBLKSIZE));
#else
return((struct hblk *)hhdr->hb_block);
#endif
}
}
j = BOTTOM_SZ - 1;
Expand Down

0 comments on commit d8ecfa3

Please sign in to comment.