-
Notifications
You must be signed in to change notification settings - Fork 61
mrs: add paced free #2377
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
mrs: add paced free #2377
Conversation
If defined at compile time, QUARANTINE_HIGHWATER limited the size of the quarantine to QUARANTINE_HIGHWATER bytes. Given the vast range of working set sizes this isn't particularly useful except perhaps to set it to 0. The environment variable _RUNTIME_REVOCATION_EVERY_FREE_ENABLE and associated sysctl now serves this purpose.
Use of this macro was removed with store-side revocation support. Fixes: 62e9115 mrs: remove store-side support")
This allow more granularity including allowing quarantine to exceed 1/2 the size of the heap. Replace QUARANTINE_RATIO with QUARANTINE_NUMERATOR and QUARANTINE_DENOMINATOR. The quarantine is flushed when: QUARANTINE_NUMERATOR <quarantine_size> >= <heap size> * ---------------------- QUARANTINE_DENOMINATOR The default values are QUARANTINE_NUMERATOR=1 and QUARANTINE_DENOMINATOR=4 respectively giving the same behavior as the previous default QUARANTINE_RATIO=4.
lib/libc/stdlib/malloc/mrs/mrs.c
Outdated
if ((envstr = getenv(MALLOC_QUARANTINE_DENOMINATOR_ENV)) != | ||
NULL) { | ||
quarantine_denominator = strtoul(envstr, &end, 0); | ||
if (*end != '\0') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also need to check errno != ERANGE if quarantine_denominator == ULONG_MAX
lib/libc/stdlib/malloc/mrs/mrs.c
Outdated
for (struct mrs_descriptor_slab *iter = quarantine->list; iter != NULL; | ||
iter = iter->next) { | ||
assert(iter->next_descriptor == 0); | ||
while(iter->next_descriptor < iter->num_descriptors) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space
while(iter->next_descriptor < iter->num_descriptors) { | ||
slab_free_next_descriptor(iter); | ||
while((ptr = slab_pop_descriptor(iter)) != NULL) { | ||
descriptor_free(ptr); | ||
} | ||
assert(iter->next_descriptor == iter->num_descriptors); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this get hit because we increment next_descriptor on the iteration where slab_pop_descriptor returns NULL
The environmental variables _RUNTIME_QUARANTINE_NUMERATOR and _RUNTIME_QUARANTINE_DENOMINATOR can now override compiled defaults for QUARANTINE_NUMERATOR and QUARANTINE_DENOMINATOR.
OFFLOAD_QUARANTINE depends on pthreads support and has been superceeded by in-kernel async revocation support. MRS_PINNED_CPUSET was technically independent, but primairly supported benchmarking OFFLOAD_QUARANTINE.
The rest of the block is also a bit sketchy, but is less obviously wrong.
Yuecheng Wang reports that with jemalloc, the tccache gets flushed if too many frees happen at once leading to poor malloc performance. This feature defers frees to the malloc path and frees one revoked pointer each time. This primative implemenation does not take size into account so likely has adverse cache effects if malloc's and free's aren't well matched. This functionality defaults to off and can be enabled with _RUNTIME_PACED_FREE_ENABLE. A _RUNTIME_PACED_FREE_DISABLE also exists should the default change. Freeing an object adds a lock to malloc path so it may be advisiable to add batching support to amortize this cost.
a95bb9e
to
6d31ff9
Compare
Libarchive 3.7.7 Security fixes: #2158 rpm: calculate huge header sizes correctly #2160 util: fix out of boundary access in mktemp functions #2168 uu: stop processing if lines are too long #2174 lzop: prevent integer overflow #2172 rar4: protect copy_from_lzss_window_to_unp() (CVE-2024-20696) #2175 unzip: unify EOF handling #2179 rar4: fix out of boundary access with large files #2203 rar4: fix OOB access with unicode filenames #2210 rar4: add boundary checks to rgb filter #2248 rar4: fix OOB in delta filter #2249 rar4: fix OOB in audio filter #2256 fix multiple vulnerabilities identified by SAST #2258 cpio: ignore out-of-range gid/uid/size/ino and harden AFIO parsing #2265 rar5: clear 'data ready' cache on window buffer reallocs #2269 rar4: fix CVE-2024-26256 (CVE-2024-26256) #2330 iso: be more cautious about parsing ISO-9660 timestamps #2343 tar: clean up linkpath between entries #2364 tar: don't crash on truncated tar archives #2366 gzip: prevent a hang when processing a malformed gzip inside a gzip #2377 tar: fix two leaks in tar header parsing Important bugfixes: #2096 rar5: report encrypted entries #2150 xar: fix another infinite loop and expat error handling #2173 shar: check strdup return value #2161 lha: fix integer truncation on 32-bit systems #2338 tar: fix memory leaks when processing symlinks or parsing pax headers #2245 7zip: fix issue when skipping first file in 7zip archive that is a multiple of 65536 bytes #2252 7-zip: read/write symlink paths as UTF-8 #2259 rar5: don't try to read rediculously long names #2290 ar: fix archive entries having no type #2360 tar: fix truncation of entry pathnames in specific archives CVE: CVE-2024-20696, CVE-2024-26256 PR: 282047 (exp-run) MFC after: 1 week
@@ -378,15 +383,18 @@ static size_t max_allocated_size; | |||
* Quarantine arenas for application threads. At any given time, one is in | |||
* active use, and the others are being cleaned. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment should probably be extended to explain why we need at least 3 arenas.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's helpful, feel free to steal some prose from the relevant CHERIoT-RTOS allocator source, where it does the same thing (I am pretty sure): https://github.com/CHERIoT-Platform/cheriot-rtos/blob/20b588dca8fcff4f6ccac229dfe342cd09d50f29/sdk/core/allocator/alloc.h#L872-L903
|
||
/* | ||
* If we're defering actual free calls until later, just add the | ||
* quaranting to the pending queue and let them be freed one at |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo, "quaranting"
@@ -45,6 +45,7 @@ | |||
#define UTRACE_MRS_QUARANTINE_FLUSH_DONE 10 | |||
#define UTRACE_MRS_QUARANTINE_REVOKE 11 | |||
#define UTRACE_MRS_QUARANTINE_REVOKE_DONE 12 | |||
#define UTRACE_MRS_REAL_FREE 13 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need a corresponding update to lib/libsysdecode/utrace.c?
static inline void | ||
slab_free_next_descriptor(struct mrs_descriptor_slab *s) | ||
static inline void * | ||
slab_pop_descriptor(struct mrs_descriptor_slab *s) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why "pop"? These entries are FIFO, aren't they?
/* | ||
* Doesn't matter if the underlying size isn't a 16-byte multiple | ||
* because all allocations will be 16-byte aligned. | ||
*/ | ||
size_t len = __builtin_align_up(cheri_getlen(s->slab[i].ptr), | ||
size_t len = __builtin_align_up(cheri_getlen(ptr), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't really related to the diff itself, but the descriptor arenas spend 16 bytes per entry to store the size of the memory region, and that seems redundant is it's available from the capability. Do we do that because cheri_getlen()
is relatively expensive? If so, I'd expect we want to use the saved value here rather than extracting it from the capability again.
Add support for deferring free to the malloc path where we check if we should revoke. I've called the feature paced rather than deferred because I think we'll likely want to batch frees and only do them on some calls to malloc.
OFFLOAD_QUARANTINE was making everything hard to read so I removed it as we're unlikely to want to use it again.
This branch contains the changes in #2376, but does not depend on the functionality included there (it would probably conflict if you tried to rebase without those changes)