Skip to content
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

msan: False positive with libaio? #688

Closed
sitsofe opened this issue Jun 11, 2016 · 8 comments
Closed

msan: False positive with libaio? #688

sitsofe opened this issue Jun 11, 2016 · 8 comments

Comments

@sitsofe
Copy link

sitsofe commented Jun 11, 2016

When trying to use a program that uses libaio MemorySanitzer regularly says uninitialized values are stored just after the io_getevents call:

==20626==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x49842e in finish_io /tmp/aio-stress.c:450:32
    #1 0x4b31d9 in io_oper_wait /tmp/aio-stress.c:548:2
    #2 0x4ac99e in worker /tmp/aio-stress.c:1145:2
    #3 0x4bc18b in main /tmp/aio-stress.c:1499:11
    #4 0x7efc54837f44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)
    #5 0x419f6e in _start (/tmp/a.out+0x419f6e)

  Uninitialized value was stored to memory at
    #0 0x4982bb in finish_io /tmp/aio-stress.c:449
    #1 0x4b31d9 in io_oper_wait /tmp/aio-stress.c:548:2
    #2 0x4ac99e in worker /tmp/aio-stress.c:1145:2
    #3 0x4bc18b in main /tmp/aio-stress.c:1499:11
    #4 0x7efc54837f44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)

  Uninitialized value was stored to memory at
    #0 0x4b30dd in io_oper_wait /tmp/aio-stress.c:545:18
    #1 0x4ac99e in worker /tmp/aio-stress.c:1145:2
    #2 0x4bc18b in main /tmp/aio-stress.c:1499:11
    #3 0x7efc54837f44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)

  Uninitialized value was created by an allocation of 'event' in the stack frame of function 'io_oper_wait'
    #0 0x4b28f0 in io_oper_wait /tmp/aio-stress.c:525

SUMMARY: MemorySanitizer: use-of-uninitialized-value /tmp/aio-stress.c:450:32 in finish_io
Exiting

I see that the sanitizers know about the syscall (https://github.com/llvm-mirror/compiler-rt/blob/release_38/lib/sanitizer_common/sanitizer_common_syscalls.inc#L1295 ) but even if I compile libaio by hand with memory sanitizer and use LD_LIBRARY_PATH to ensure my hand compiled version is used I still get errors.

Steps to reproduce:

  1. Download the xfstests version of aio-stress.c (http://oss.sgi.com/cgi-bin/gitweb.cgi?p=xfs/cmds/xfstests.git;a=blob;f=ltp/aio-stress.c;hb=HEAD ).
  2. Compile aio-stress by doing
    clang-3.8 -g -O0 -fsanitize=memory -fsanitize-memory-track-origins=2 -lpthread -laio -o aio-stress aio-stress.c
  3. Run
    ./aio-stress -m -s 2MB

Expected results:
Test to run without error?

Actual result:

$ ./aio-stress -m -s 2MB
file size 1024MB, record size 64KB, depth 64, ios per iteration 8
max io_submit 8, buffer alignment set to 4KB
threads 1 files 1 contexts 1 context offset 2MB verification off
Running single thread version 
==20656==WARNING: MemorySanitizer: use-of-uninitialized-value
[...]

How reproducible is the problem?
The problem can be reproduced every time.

Version information:
Clang 3.8
Ubuntu 14.04 x86_64

@sitsofe sitsofe changed the title man: False positive with libaio? msan: False positive with libaio? Jun 11, 2016
@eugenis
Copy link
Contributor

eugenis commented Jun 12, 2016

The problem is that libaio uses inline asm for those syscalls, and MSan
does not intercept it.
It can be fixed in libaio code with something like this:

#include <sanitizer/linux_syscall_hooks.h>
#define PRE(name, ...) sanitizer_syscall_pre_##name(__VA_ARGS)
#define POST(name, res, ...) sanitizer_syscall_post_##name(res,
__VA_ARGS
)

and then add PRE and POST to io_syscall1 .. io_syscall5.

On Sat, Jun 11, 2016 at 1:03 AM, Sitsofe Wheeler notifications@github.com
wrote:

When trying to use a program that uses libaio MemorySanitzer regularly
says uninitialized values are stored just after the io_getevents call:

==20626==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x49842e in finish_io /tmp/aio-stress.c:450:32
#1 0x4b31d9 in io_oper_wait /tmp/aio-stress.c:548:2
#2 0x4ac99e in worker /tmp/aio-stress.c:1145:2
#3 0x4bc18b in main /tmp/aio-stress.c:1499:11
#4 0x7efc54837f44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)
#5 0x419f6e in _start (/tmp/a.out+0x419f6e)

Uninitialized value was stored to memory at
#0 0x4982bb in finish_io /tmp/aio-stress.c:449
#1 0x4b31d9 in io_oper_wait /tmp/aio-stress.c:548:2
#2 0x4ac99e in worker /tmp/aio-stress.c:1145:2
#3 0x4bc18b in main /tmp/aio-stress.c:1499:11
#4 0x7efc54837f44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)

Uninitialized value was stored to memory at
#0 0x4b30dd in io_oper_wait /tmp/aio-stress.c:545:18
#1 0x4ac99e in worker /tmp/aio-stress.c:1145:2
#2 0x4bc18b in main /tmp/aio-stress.c:1499:11
#3 0x7efc54837f44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)

Uninitialized value was created by an allocation of 'event' in the stack frame of function 'io_oper_wait'
#0 0x4b28f0 in io_oper_wait /tmp/aio-stress.c:525

SUMMARY: MemorySanitizer: use-of-uninitialized-value /tmp/aio-stress.c:450:32 in finish_io
Exiting

I see that the sanitizers know about the syscall (
https://github.com/llvm-mirror/compiler-rt/blob/release_38/lib/sanitizer_common/sanitizer_common_syscalls.inc#L1295
) but even if I compile libaio by hand with memory sanitizer and use
LD_LIBRARY_PATH to ensure my hand compiled version is used I still get
errors.

Steps to reproduce:

  1. Download the xfstests version of aio-stress.c (
    http://oss.sgi.com/cgi-bin/gitweb.cgi?p=xfs/cmds/xfstests.git;a=blob;f=ltp/aio-stress.c;hb=HEAD
    ).
  2. Compile aio-stress by doing
    clang-3.8 -g -O0 -fsanitize=memory -fsanitize-memory-track-origins=2
    -lpthread -laio -o aio-stress aio-stress.c
  3. Run
    ./aio-stress -m -s 2MB

Expected results:
Test to run without error?

Actual result:

$ ./aio-stress -m -s 2MB
file size 1024MB, record size 64KB, depth 64, ios per iteration 8
max io_submit 8, buffer alignment set to 4KB
threads 1 files 1 contexts 1 context offset 2MB verification off
Running single thread version
==20656==WARNING: MemorySanitizer: use-of-uninitialized-value
[...]

How reproducible is the problem?
The problem can be reproduced every time.

Version information:
Clang 3.8
Ubuntu 14.04 x86_64


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#688, or mute the thread
https://github.com/notifications/unsubscribe/AAZuSkol1F9dFxijdSmnJka5n7VioNgrks5qKmvCgaJpZM4Izf8U
.

@sitsofe
Copy link
Author

sitsofe commented Jun 12, 2016

Thanks for the advice - the attached patch based on your suggestion seems to solve the issue on an x86_64 Linux after building and linking appropriately:
libaio-san.txt

I guess this issue should be closed but before then is there anything that can be done more generically if users are willing to deal with false negatives (e.g. marking all memory from functions in a given given library as unpoisoned)?

@yugr
Copy link

yugr commented Jun 12, 2016

Also, perhaps MSan could warn on unrecognized asm blocks?

@sitsofe
Copy link
Author

sitsofe commented Jun 13, 2016

@yugr:
That could create a lot of spurious warnings because you would never know if a given asm block was one you should care about. In my case I needed to care because asm was being used to run syscalls but perhaps the asm is putting values in allocated memory / making the memory invalid etc behind the scenes. It would be very hard to make something generic that wouldn't just trigger on all asm blocks...

@sitsofe
Copy link
Author

sitsofe commented Jun 13, 2016

(http://thread.gmane.org/gmane.comp.compilers.llvm.cvs/167562/focus=167565 talks about why libaio calls aren't intercepted because doing so would force every *san program to use -laio)

@yugr
Copy link

yugr commented Jun 13, 2016

It would be very hard to make something generic
that wouldn't just trigger on all asm blocks...

But isn't this desired? I mean 99% of asm blocks need special handling in MSan.

@eugenis
Copy link
Contributor

eugenis commented Jun 13, 2016

In my experience it is a lot less than 99%. A lot of assembly blocks don't
have any memory side effects (like rdtsc or cpuid), and a lot have their
memory effects declared in the constraints (MSan can handle those). Warning
indiscriminately on every asm block will break projects that use -Werror.

As for a more generic solution, that's hard. I don't know how to define
"all memory from functions in a given library" - especially when this
library is not instrumented.

On Mon, Jun 13, 2016 at 4:09 AM, Yury Gribov notifications@github.com
wrote:

It would be very hard to make something generic
that wouldn't just trigger on all asm blocks...

But isn't this desired? I mean 99% of asm blocks need special handling in
MSan.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#688 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AAZuSk_Ikzs-oVrRlt4vfy-21GjyLDuPks5qLTpqgaJpZM4Izf8U
.

@sitsofe
Copy link
Author

sitsofe commented Jun 14, 2016

@eugenis: I don't know how to define "all memory from functions in a given library" - especially when this library is not instrumented.

Thank you for answering my remaining question. Marking this issue as closed.

@sitsofe sitsofe closed this as completed Jun 14, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants