sandbox: Add -M option to disable mcheck at runtime
Add a command-line option (-M or --no_mcheck) to disable mcheck heap protection at runtime. When mcheck is disabled, the 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. Changes: - Add disable_mcheck flag to sandbox_state - Add mcheck_set_disabled() function to mcheck API - Modify dlmalloc wrappers to bypass mcheck when disabled - Add stub for when MCHECK_HEAP_PROTECTION is not enabled - Document the new option in sandbox.rst Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com>
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include <event.h>
|
||||
#include <init.h>
|
||||
#include <log.h>
|
||||
#include <mcheck.h>
|
||||
#include <os.h>
|
||||
#include <pager.h>
|
||||
#include <sandbox_host.h>
|
||||
@@ -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];
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 ---------------------------- */
|
||||
|
||||
@@ -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 <filename>
|
||||
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.
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user