the Chromium logo

The Chromium Projects

MemorySanitizer (MSan)

MemorySanitizer (MSan) is a tool that detects use of uninitialized memory.

MSan is supported on x86_64 Linux. Additional info on the tool is available at http://clang.llvm.org/docs/MemorySanitizer.html.

MSan in Chromium is unlikely to be usable on systems other than Ubuntu Precise/Trusty - please see the note on instrumented libraries below.

MSan bots are running on chromium.memory.fyi, client.webrtc and chromium.webkit. There are also two LKGR builders for ClusterFuzz: no origins, chained origins (see below for explanation). V8 deployment is ongoing.

Trybots: linux_chromium_msan_rel_ng, linux_chromium_chromeos_msan_rel_ng.

Pre-built Chrome binaries

You can grab fresh Chrome binaries for Linux built with MSan here.

How to build and run

To set up an MSan build in GN:

gclient runhooks
gn args out/msan

In the resulting editor, set the build variables:

is_msan = true

is_debug = false # Release build.

(Note: if you intend to run the Blink web tests with the MSan-instrumented content_shell binary, you must use out/Release instead of out/msan, because otherwise the test expectations will not apply correctly.)

(In older versions of Chromium you also had to explicitly set "use_prebuilt_instrumented_libraries = true". This is now the default if is_msan is set and can no longer be overridden.)

MSan requires using Instrumented system libraries. Note that instrumented libraries are supported on Ubuntu Precise/Trusty only. More information: instrumented-libraries-for-dynamic-tools.

The following flags are implied by is_msan=true (i.e. you don't have to set them explicitly):

Some common flags may break a MSAN build. For example, don't set "dcheck_always_on = true" when using MSAN.

If you are trying to reproduce a test run from the Linux ChromiumOS MSan Tests build, other GN args may also be needed. You can look for them via your test run page, under the section "lookup builder GN args". Add all of them, except the goma_dir.

Running on gLinux locally

testing/xvfb.py out/msan/unit_tests --gtest_filter="<your test filter>" Running on Ubuntu Trusty

Run the resulting binaries as usual. Pipe both stderr and stdout through tools/valgrind/asan/asan_symbolize.py to get symbolized reports:

./out/msan/browser_testsĀ |& tools/valgrind/asan/asan_symbolize.py

Running on other distros using Docker

If you're a Googler, you can install Docker by following the instructions at go/installdocker.

A Trusty docker image for running MSan instrumented binaries can be built:

docker build -t trusty-chromium third_party/instrumented_libraries/docker
third_party/instrumented_libraries/scripts/run_docker.sh out/msan/browser_testsĀ |& tools/valgrind/asan/asan_symbolize.py

If you need to run a binary against some test input, you need to place the input somewhere in your chromium src directory (as it's mounted into the docker container by run_docker.sh).

e.g. you can place the input in chromium/src/testcases/testcase.html and run:

third_party/instrumented_libraries/scripts/run_docker.sh out/msan/chrome --use-gl=angle --use-angle=swiftshader testcases/testcase.html

The CWD in the docker container is your chromium src directory, so you can pass paths relative to that.

Note that this image may have to be rebuilt from time to time if new dependencies are added to install-build-deps.sh. To do a rebuild, pass --no-cache to the docker build command:

docker build --no-cache -t trusty-chromium third_party/instrumented_libraries/docker

Disable OpenGL

Chrome must not use hardware OpenGL when running under MSan. This is because libgl.so is not instrumented and will crash the GPU process. SwANGLE can be used as a software OpenGL implementation, although it is extremely slow. There are several ways to proceed:

If neither flag is specified, Chrome will fall back to the first option after the GPU process crashes with an MSan report.

Origin tracking

MSan allows the user to trade off execution speed for the amount of information provided in reports. This is controlled by the GN/GYP flag msan_track_origins:

Suppressions

MSan does not support suppressions. This is an intentional design choice.

We have a blocklist file which is applied at compile time, and is used mainly to compensate for tool issues. Blocklist rules do not work the way suppression rules do - rather than suppressing reports with matching stack traces, they change the way MSan instrumentation is applied to the matched function. In addition, blocklist changes require a full clobber to take efffect. Please refrain from making changes to the blocklist file unless you know what you are doing.

Note also that instrumented libraries use separate blocklist files.

Debugging MSan reports

Important caveats:

MSan reserves a separate memory region ("shadow memory") in which it tracks the status of application memory. The correspondence between the two is bit-to-bit: if the shadow bit is set to 1, the corresponding bit in the application memory is considered "poisoned" (i.e. uninitialized). The header file <sanitizer/msan_interface.h> declares interface functions which can be used to examine and manipulate the shadow state without changing the application memory, which comes in handy when debugging MSan reports.

Print the complete shadow state of a range of application memory, including the origins of all uninitialized values, if any. (Note: though initializedness is tracked on bit level, origins have 4-byte granularity.)

void __msan_print_shadow(const volatile void *x, size_t size);

The following prints a more minimalistic report which shows only the shadow memory:

void __msan_dump_shadow(const volatile void *x, size_t size);

To mark a memory range as fully uninitialized/initialized:

void __msan_poison(const volatile void *a, size_t size);
void __msan_unpoison(const volatile void *a, size_t size);
void __msan_unpoison_string(const volatile char *a);

The following forces an MSan check, i.e. if any bits in the memory range are uninitialized the call will crash with an MSan report.

void __msan_check_mem_is_initialized(const volatile void *x, size_t size);

This milder check returns the offset of the first (at least partially) poisoned byte in the range, or -1 if the whole range is good:

intptr_t __msan_test_shadow(const volatile void *x, size_t size);

Hint: sometimes to reduce log spam it makes sense to query __msan_test_shadow() before calling __msan_print_shadow().

The complete interface can be found in src/third_party/llvm-build/Release+Asserts/lib/clang/3.6.0/include/sanitizer/msan_interface.h. Functions such as __msan_unpoison() can also be used to permanently annotate your code for MSan, but please CC eugenis@ if you intend to do so.

Reproducing ClusterFuzz Bugs

Because MSan only supports Ubuntu Precise/Trusty and not Rodete, the ClusterFuzz reproduce tool cannot reproduce bugs found using MSan (on Rodete).

If you are on Rodete, you can try to reproduce them manually using docker to run MSan by following these instructions.