Summary: | false positive on write after mprotect(,,PROT_WRITE) after mmap(,,PROT_NONE,,,) | ||
---|---|---|---|
Product: | [Developer tools] valgrind | Reporter: | John Reiser <jreiser> |
Component: | memcheck | Assignee: | Julian Seward <jseward> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | astasenko, dank, jakub, njn, vargaz |
Priority: | NOR | ||
Version: | 3.5.0 | ||
Target Milestone: | blocking3.5.1 | ||
Platform: | Unlisted Binaries | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: | |||
Attachments: |
patch mmap to act like mprotect when PROT_NONE
*.diff after "make regtest" alternative patch patch implementing proposal in comment #7 |
Description
John Reiser
2009-08-29 00:03:49 UTC
Created attachment 36564 [details]
patch mmap to act like mprotect when PROT_NONE
Something like this seems plausible.
(In reply to comment #1) > seems plausible. Does this work properly (no effect on regtests) ? The reason mprotect is not handled consistently with mmap is that doing so used to screw up m_debuginfo's fragile logic for figuring out when/where text/data segments got mapped. All that stuff needs revisiting anyway. There are other bugs open on it. Created attachment 36584 [details]
*.diff after "make regtest"
With the patch, running under Fedora 11 on x86_64 [and with "-Wl,-defsym,valt_load_address=0x7c000000"], "make regtest" ends with:
== 534 tests, 9 stderr failures, 0 stdout failures, 0 post failures ==
memcheck/tests/linux/stack_switch (stderr)
memcheck/tests/long_namespace_xml (stderr)
none/tests/procfs-linux (stderr)
helgrind/tests/tc06_two_races_xml (stderr)
helgrind/tests/tc20_verifywrap (stderr)
helgrind/tests/tc23_bogus_condwait (stderr)
drd/tests/annotate_trace_memory (stderr)
drd/tests/tc09_bad_unlock (stderr)
exp-ptrcheck/tests/bad_percentify (stderr)
and this attachment contains the *.diff. These look the same to me as the *.diff due to Fedora 11 anyway.
*** Bug 210268 has been marked as a duplicate of this bug. *** Created attachment 40234 [details]
alternative patch
Here's another way to make memcheck handle mmap and mprotect
in a mutually consistent way. John's patch allows memcheck to
believe that memory mmap'd PROT_NONE is still accessible, which
isn't good. This patch leaves the mmap handling unchanged and
instead makes mprotect behave consistently with mmap -- that is,
if memory is mprotected to be PROT_NONE then it's considered
inaccessible, whereas if it is mprotected to anything else then
it's considered accessible and initialised (oh well :-)
This makes memcheck stop complaining about the test program
provided, and also shuts it up with Wine, which afaics is the
real point here.
Yes, the patch attached to comment #5 makes mmap and mprotect consistent. Yes, it reduces the false positive complaints from wine+memcheck. However, the patch introduces a new class [or perhaps reinforces an old class] of false negative reports, undetected memory usage errors that could/would have been detected. mprotect(addr, len, PROT_NONE) followed by mprotect(addr, len, anything_except_PROT_NONE) of the same region will force all the Valid bits to 1, whereas the operating system actually retains the prior contents and validity [the "oh well" from comment #5.] So choose between easy-to-explain-but-not-always-correct, and correct-but-difficult-to-understand (and the original plain-wrong-but-least-work.) Ah, I see this is more complex than it looked at 3.30am yesterday :-) How about the following proposal? mmap NONE -> make noaccess mmap other -> make defined mprotect NONE -> # no change mprotect other -> change any "noaccess" to "defined" I think this is what Jakub is suggesting in the very last sentence of https://bugs.kde.org/show_bug.cgi?id=210268#c1 This gives the behaviours: mmap NONE; rd/wr -> MC warns, then we get SEGV mmap other; rd -> reads as initialised mmap other; wr -> no error mmap NONE; mprotect other; rd -> reads as initialised mmap NONE; mprotect NONE; rd/wr -> MC warns, then we get SEGV so mmap and mprotect are handled consistently. The case we can't deal with really correctly is (eg) mmap other; mprotect NONE; rd/wr -> MC doesn't warn, but we get SEGV but at least this retains the V bits for the mprotected area, so there is no chance of false negatives. And if there is an access then at least we get a SEGV traceback, which is better than nothing. Created attachment 40251 [details] patch implementing proposal in comment #7 The analysis in comment #7 and patch in comment #8 are OK. The byte-by-byte implementation of make_mem_defined_if_noaccess() is OK for now, but high usage or large intervals of mprotect(,,other) could benefit from optimization to take advantage of intervals larger than 1 byte that are all NOACCESS or all not-NOACCESS. (In reply to comment #9) > or large intervals of mprotect(,,other) could benefit from optimization [...] Sure, can unroll/vectorise/whatever if need be. Fixed (r11031). *** Bug 225188 has been marked as a duplicate of this bug. *** |