diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 1a5ca97e15e..b9f48376d22 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -523,6 +524,15 @@ static int sandbox_cmdline_cb_noflat(struct sandbox_state *state, } SANDBOX_CMDLINE_OPT_SHORT(noflat, 'F', 0, "Don't run second set of DM tests"); +static int sandbox_cmdline_cb_no_mcheck(struct sandbox_state *state, + const char *arg) +{ + state->disable_mcheck = true; + + return 0; +} +SANDBOX_CMDLINE_OPT_SHORT(no_mcheck, 'M', 0, "Disable mcheck heap protection"); + static int sandbox_cmdline_cb_soft_fail(struct sandbox_state *state, const char *arg) { @@ -674,6 +684,9 @@ int sandbox_init(int argc, char *argv[], struct global_data *data) if (os_parse_args(state, argc, argv)) return 1; + if (state->disable_mcheck) + mcheck_set_disabled(true); + /* Remove old frame*.bmp files if video_frames_dir is set */ if (state->video_frames_dir) { char pattern[256]; diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h index ff7493ec5d6..1b6eef4a9c3 100644 --- a/arch/sandbox/include/asm/state.h +++ b/arch/sandbox/include/asm/state.h @@ -178,6 +178,7 @@ struct sandbox_state { bool pager_bypass; /* Enable pager-bypass mode */ bool no_term_present; /* Assume no terminal present */ bool quiet_vidconsole; /* Don't use vidconsole for stdout */ + bool disable_mcheck; /* Disable mcheck heap protection */ int video_test; /* ms to wait before next assert */ const char *video_frames_dir; /* Directory to write video frames */ int video_frame_count; /* Number of frames written */ diff --git a/common/dlmalloc.c b/common/dlmalloc.c index 5069a95d9b3..78efdf5fd9a 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -5965,6 +5965,14 @@ static bool in_backtrace __section(".data"); */ static bool mcheck_skip_backtrace __section(".data"); +/* Runtime flag to disable mcheck - allows bypassing heap protection */ +static bool mcheck_disabled __section(".data"); + +void mcheck_set_disabled(bool disabled) +{ + mcheck_disabled = disabled; +} + void malloc_backtrace_skip(bool skip) { mcheck_skip_backtrace = skip; @@ -5993,6 +6001,9 @@ void *dlmalloc(size_t bytes) !(gd->flags & GD_FLG_FULL_MALLOC_INIT)) return malloc_simple(bytes); + if (mcheck_disabled) + return dlmalloc_impl(bytes CALLER_NULL); + mcheck_pedantic_prehook(); size_t fullsz = mcheck_alloc_prehook(bytes); void *p = dlmalloc_impl(fullsz CALLER_NULL); @@ -6009,12 +6020,15 @@ void dlfree(void *mem) dlfree_impl(mem); return; } + if (mcheck_disabled) { + dlfree_impl(mem); + return; + } dlfree_impl(mcheck_free_prehook(mem)); } void *dlrealloc(void *oldmem, size_t bytes) { - mcheck_pedantic_prehook(); #ifdef REALLOC_ZERO_BYTES_FREES if (bytes == 0) { if (oldmem) @@ -6026,6 +6040,10 @@ void *dlrealloc(void *oldmem, size_t bytes) if (oldmem == NULL) return dlmalloc(bytes); + if (mcheck_disabled) + return dlrealloc_impl(oldmem, bytes); + + mcheck_pedantic_prehook(); void *p = mcheck_reallocfree_prehook(oldmem); size_t newsz = mcheck_alloc_prehook(bytes); @@ -6041,6 +6059,9 @@ void *dlmemalign(size_t alignment, size_t bytes) !(gd->flags & GD_FLG_FULL_MALLOC_INIT)) return memalign_simple(alignment, bytes); + if (mcheck_disabled) + return dlmemalign_impl(alignment, bytes); + mcheck_pedantic_prehook(); size_t fullsz = mcheck_memalign_prehook(alignment, bytes); void *p = dlmemalign_impl(alignment, fullsz); @@ -6064,6 +6085,9 @@ void *dlcalloc(size_t n, size_t elem_size) return p; } + if (mcheck_disabled) + return dlcalloc_impl(n, elem_size); + mcheck_pedantic_prehook(); /* NB: no overflow check here */ size_t fullsz = mcheck_alloc_prehook(n * elem_size); @@ -6121,6 +6145,13 @@ void *dlcalloc(size_t n, size_t elem_size) } #endif /* MCHECK_HEAP_PROTECTION */ +#if !CONFIG_IS_ENABLED(MCHECK_HEAP_PROTECTION) +/* Stub when mcheck is not enabled */ +void mcheck_set_disabled(bool disabled) +{ +} +#endif + #endif /* !ONLY_MSPACES */ /* ----------------------------- user mspaces ---------------------------- */ diff --git a/doc/arch/sandbox/sandbox.rst b/doc/arch/sandbox/sandbox.rst index 90c3dfa837e..0962aeeb1a0 100644 --- a/doc/arch/sandbox/sandbox.rst +++ b/doc/arch/sandbox/sandbox.rst @@ -181,6 +181,13 @@ available options. Some of these are described below: all log statements at LOGL_DEBUG and below. The higher the number, the more info is shown. +-M, --no_mcheck + Disable mcheck heap protection at runtime. When enabled, the mcheck wrapper + functions pass through directly to the underlying allocator without adding + headers or checking for corruption. This is useful for debugging when mcheck + interferes with test results, such as when memory-leak detection reports false + positives due to accumulated allocations from other tests. + -m, --memory Sets the location of the file which holds sandbox's emulated RAM. This can be read and written across phases, so that sandbox behaves like a normal board. diff --git a/include/mcheck.h b/include/mcheck.h index b170acf6281..cd72edb6ae8 100644 --- a/include/mcheck.h +++ b/include/mcheck.h @@ -51,4 +51,15 @@ enum mcheck_status mprobe(void *__ptr); /* Called during RAM relocation to reset the heap registry */ void mcheck_on_ramrelocation(size_t offset); +/** + * mcheck_set_disabled() - Disable mcheck at runtime + * + * When disabled, mcheck wrapper functions pass through directly to the + * underlying allocator without adding headers or checking for corruption. + * This is useful for debugging when mcheck interferes with test results. + * + * @disabled: true to disable mcheck, false to enable + */ +void mcheck_set_disabled(bool disabled); + #endif