-
Notifications
You must be signed in to change notification settings - Fork 1k
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: detect *all* uninitialized reads? #883
Comments
It's not hard to do, and it would be an interesting experiment.
If you want to try, look at MemorySanitizerVisitor::visitLoadInst, and add
a call to insertShadowCheck().
It can be hidden behind an -mllvm flag.
I don't know how practical this mode would be, but if it works we can add a
function attribute / blacklist support so it can be enabled only on
interesting functions.
…On Sun, Nov 19, 2017 at 9:27 AM, Roman Lebedev ***@***.***> wrote:
Hi.
This is related to google/oss-fuzz#863
<google/oss-fuzz#863>
I'm fuzzing a RawSpeed <https://github.com/darktable-org/rawspeed>
library.
Memory sanitizer is being *extremely* useful to find one particular set
of issues in decoders - when they don't actually decode the whole image
(i.e. part of the memory is left uninitialized), but also don't report an
issue.
Right now, MSAN seems to only detect uninitialized reads that are then
used (as conditional variable), so i'm [ab]using MSAN_MEM_IS_INITIALIZED()
.
This works great, and at *this* moment has already found ~18 issues
<https://bugs.chromium.org/p/oss-fuzz/issues/list?can=1&q=label%3AProj-librawspeed+uninitialized&colspec=ID+Type+Component+Status+Proj+Reported+Owner+Summary&cells=ids>
.
However, it's not quite what i would like it to be.
1. I need to manually plant MSAN_MEM_IS_INITIALIZED() calls.
2. Deduplication on oss-fuzz is having problems with that
google/oss-fuzz#863 <google/oss-fuzz#863>.
3. I can't call it everywhere, it is simply unfeasible as it would
significantly affect the code readability e.g.
So i'm wondering whether
- there is already an option to instrument *all* reads? :) I guess not
- if not, whether such functionality is in scope of MSAN, and could be
added?
Roman.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#883>, or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAZuSthbpAbLb5qubpjOI7rqtm-pfJUMks5s4GT-gaJpZM4QjdeB>
.
|
Thank you for the reply, but i'm afraid that with my knowledge of compiler-rt, it is not enough info for me to do it. |
Ok, so i looked at this once more. Given int test(int* k) {
return *k;
} which is roughly
Now, if (ClCheckAccessAddress)
insertShadowCheck(I.getPointerOperand(), &I); Sidenote: why does it look like this check is after the load? https://godbolt.org/g/Mqbm85 So what we basically need to check is the shadow of the {
unsigned Alignment = I.getAlignment();
unsigned OriginAlignment = std::max(kMinOriginAlignment, Alignment);
insertShadowCheck(IRB.CreateAlignedLoad(getOriginPtr(Addr, IRB, Alignment),
OriginAlignment),
&I);
} but that crashes
So i'm guessing that i'm passing something wrong as the first argument of the If there are any more hints, it might be interesting to make this work :) |
Yes, it's not as simple as I thought.
Attached patch seems to work.
I did not run it on anything big. MSan tests fail a lot with it, but all
reports seem reasonable.
…On Sun, Dec 3, 2017 at 3:41 AM, Roman Lebedev ***@***.***> wrote:
Ok, so i looked at this once more.
https://github.com/llvm-mirror/llvm/blob/7f86494ddd7b6a32c98a0e8572c3ea
96ac96f826/lib/Transforms/Instrumentation/MemorySanitizer.cpp#L1349-L1383
Given
int test(int* k) {
return *k;
}
which is roughly
; Function Attrs: norecurse nounwind readonly uwtable
define i32 @test(int*)(i32* nocapture readonly) local_unnamed_addr #0 {
%2 = load i32, i32* %0, align 4, !tbaa !2
ret i32 %2
}
LoadInst &I is %2 = load i32, i32* %0, align 4
Now, int* k is %0, and is I.getPointerOperand();.
The shadow *of the pointer* is already checked in
if (ClCheckAccessAddress)
insertShadowCheck(I.getPointerOperand(), &I);
Sidenote: why does it look like this check is *after* the load?
https://godbolt.org/g/Mqbm85
So what we basically need to check is the shadow of the %2, i.e. the
shadow of the [%0, %0+size) region. And this is where i'm loosing the
idea.
My very naive idea was to do similar thing as in MS.TrackOrigins &&
PropagateShadow case:
{
unsigned Alignment = I.getAlignment();
unsigned OriginAlignment = std::max(kMinOriginAlignment, Alignment);
insertShadowCheck(IRB.CreateAlignedLoad(getOriginPtr(Addr, IRB, Alignment),
OriginAlignment),
&I);
}
but that crashes
clang-6.0: /build/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp:1165: llvm::Value *(anonymous namespace)::MemorySanitizerVisitor::getShadow(llvm::Value *): Assertion `Shadow && "No shadow for a value"' failed.
#0 0x000000000241faf4 PrintStackTraceSignalHandler(void*) (/build/llvm-build-Clang-release/bin/clang-6.0+0x241faf4)
#1 0x000000000241fe56 SignalHandler(int) (/build/llvm-build-Clang-release/bin/clang-6.0+0x241fe56)
...
#8 0x00000000026527c8 (anonymous namespace)::MemorySanitizerVisitor::insertShadowCheck(llvm::Value*, llvm::Instruction*) (/build/llvm-build-Clang-release/bin/clang-6.0+0x26527c8)
#9 0x0000000002650d60 llvm::InstVisitor<(anonymous namespace)::MemorySanitizerVisitor, void>::visit(llvm::Instruction&) (/build/llvm-build-Clang-release/bin/clang-6.0+0x2650d60)
So i'm guessing that i'm passing something wrong as the first argument of
the insertShadowCheck()
If there are any more hints, it might be interesting to make this work :)
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#883 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAZuSrgcJ4xBxcJtxTIWQxAcx00zXhFcks5s8oj7gaJpZM4QjdeB>
.
|
On Tue, Dec 5, 2017 at 3:18 AM, Evgeniy Stepanov <notifications@github.com>
wrote:
Yes, it's not as simple as I thought.
Attached patch seems to work.
No patch was attached.
I suspect github simply dropped it right after receiving the mail.
… I did not run it on anything big. MSan tests fail a lot with it, but all
reports seem reasonable.
On Sun, Dec 3, 2017 at 3:41 AM, Roman Lebedev ***@***.***>
wrote:
> Ok, so i looked at this once more.
> https://github.com/llvm-mirror/llvm/blob/7f86494ddd7b6a32c98a0e8572c3ea
> 96ac96f826/lib/Transforms/Instrumentation/MemorySanitizer.cpp#L1349-
L1383
>
> Given
>
> int test(int* k) {
> return *k;
> }
>
> which is roughly
>
> ; Function Attrs: norecurse nounwind readonly uwtable
> define i32 @test(int*)(i32* nocapture readonly) local_unnamed_addr #0 {
> %2 = load i32, i32* %0, align 4, !tbaa !2
> ret i32 %2
> }
>
> LoadInst &I is %2 = load i32, i32* %0, align 4
>
> Now, int* k is %0, and is I.getPointerOperand();.
> The shadow *of the pointer* is already checked in
>
> if (ClCheckAccessAddress)
> insertShadowCheck(I.getPointerOperand(), &I);
>
> Sidenote: why does it look like this check is *after* the load?
> https://godbolt.org/g/Mqbm85
>
> So what we basically need to check is the shadow of the %2, i.e. the
> shadow of the [%0, %0+size) region. And this is where i'm loosing the
> idea.
> My very naive idea was to do similar thing as in MS.TrackOrigins &&
> PropagateShadow case:
>
> {
> unsigned Alignment = I.getAlignment();
> unsigned OriginAlignment = std::max(kMinOriginAlignment, Alignment);
>
> insertShadowCheck(IRB.CreateAlignedLoad(getOriginPtr(Addr, IRB,
Alignment),
> OriginAlignment),
> &I);
> }
>
> but that crashes
>
> clang-6.0: /build/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp:1165:
llvm::Value *(anonymous namespace)::MemorySanitizerVisitor::getShadow(llvm::Value
*): Assertion `Shadow && "No shadow for a value"' failed.
> #0 0x000000000241faf4 PrintStackTraceSignalHandler(void*)
(/build/llvm-build-Clang-release/bin/clang-6.0+0x241faf4)
> #1 0x000000000241fe56 SignalHandler(int) (/build/llvm-build-Clang-
release/bin/clang-6.0+0x241fe56)
> ...
> #8 0x00000000026527c8 (anonymous namespace)::MemorySanitizerVisitor::
insertShadowCheck(llvm::Value*, llvm::Instruction*)
(/build/llvm-build-Clang-release/bin/clang-6.0+0x26527c8)
> #9 0x0000000002650d60 llvm::InstVisitor<(anonymous namespace)::MemorySanitizerVisitor,
void>::visit(llvm::Instruction&) (/build/llvm-build-Clang-
release/bin/clang-6.0+0x2650d60)
>
> So i'm guessing that i'm passing something wrong as the first argument of
> the insertShadowCheck()
>
> If there are any more hints, it might be interesting to make this work :)
>
> —
> You are receiving this because you commented.
> Reply to this email directly, view it on GitHub
> <#883 (comment)
>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/
AAZuSrgcJ4xBxcJtxTIWQxAcx00zXhFcks5s8oj7gaJpZM4QjdeB>
> .
>
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#883 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAFaGFGIvtLGueST6kviQ1pTDBJsJTcSks5s9IvvgaJpZM4QjdeB>
.
|
Yeah. Good job, github!
Let's try a different way:
https://reviews.llvm.org/D40852
On Mon, Dec 4, 2017 at 11:38 PM, Roman Lebedev <notifications@github.com>
wrote:
… On Tue, Dec 5, 2017 at 3:18 AM, Evgeniy Stepanov ***@***.***
>
wrote:
> Yes, it's not as simple as I thought.
> Attached patch seems to work.
>
No patch was attached.
I suspect github simply dropped it right after receiving the mail.
> I did not run it on anything big. MSan tests fail a lot with it, but all
> reports seem reasonable.
>
> On Sun, Dec 3, 2017 at 3:41 AM, Roman Lebedev ***@***.***>
> wrote:
>
> > Ok, so i looked at this once more.
> > https://github.com/llvm-mirror/llvm/blob/
7f86494ddd7b6a32c98a0e8572c3ea
> > 96ac96f826/lib/Transforms/Instrumentation/MemorySanitizer.cpp#L1349-
> L1383
> >
> > Given
> >
> > int test(int* k) {
> > return *k;
> > }
> >
> > which is roughly
> >
> > ; Function Attrs: norecurse nounwind readonly uwtable
> > define i32 @test(int*)(i32* nocapture readonly) local_unnamed_addr #0 {
> > %2 = load i32, i32* %0, align 4, !tbaa !2
> > ret i32 %2
> > }
> >
> > LoadInst &I is %2 = load i32, i32* %0, align 4
> >
> > Now, int* k is %0, and is I.getPointerOperand();.
> > The shadow *of the pointer* is already checked in
> >
> > if (ClCheckAccessAddress)
> > insertShadowCheck(I.getPointerOperand(), &I);
> >
> > Sidenote: why does it look like this check is *after* the load?
> > https://godbolt.org/g/Mqbm85
> >
> > So what we basically need to check is the shadow of the %2, i.e. the
> > shadow of the [%0, %0+size) region. And this is where i'm loosing the
> > idea.
> > My very naive idea was to do similar thing as in MS.TrackOrigins &&
> > PropagateShadow case:
> >
> > {
> > unsigned Alignment = I.getAlignment();
> > unsigned OriginAlignment = std::max(kMinOriginAlignment, Alignment);
> >
> > insertShadowCheck(IRB.CreateAlignedLoad(getOriginPtr(Addr, IRB,
> Alignment),
> > OriginAlignment),
> > &I);
> > }
> >
> > but that crashes
> >
> > clang-6.0: /build/llvm/lib/Transforms/Instrumentation/
MemorySanitizer.cpp:1165:
> llvm::Value *(anonymous namespace)::MemorySanitizerVisitor::
getShadow(llvm::Value
> *): Assertion `Shadow && "No shadow for a value"' failed.
> > #0 0x000000000241faf4 PrintStackTraceSignalHandler(void*)
> (/build/llvm-build-Clang-release/bin/clang-6.0+0x241faf4)
> > #1 0x000000000241fe56 SignalHandler(int) (/build/llvm-build-Clang-
> release/bin/clang-6.0+0x241fe56)
> > ...
> > #8 0x00000000026527c8 (anonymous namespace)::MemorySanitizerVisitor::
> insertShadowCheck(llvm::Value*, llvm::Instruction*)
> (/build/llvm-build-Clang-release/bin/clang-6.0+0x26527c8)
> > #9 0x0000000002650d60 llvm::InstVisitor<(anonymous namespace)::
MemorySanitizerVisitor,
> void>::visit(llvm::Instruction&) (/build/llvm-build-Clang-
> release/bin/clang-6.0+0x2650d60)
> >
> > So i'm guessing that i'm passing something wrong as the first argument
of
> > the insertShadowCheck()
> >
> > If there are any more hints, it might be interesting to make this work
:)
> >
> > —
> > You are receiving this because you commented.
> > Reply to this email directly, view it on GitHub
> > <#883#
issuecomment-348758182
> >,
> > or mute the thread
> > <https://github.com/notifications/unsubscribe-auth/
> AAZuSrgcJ4xBxcJtxTIWQxAcx00zXhFcks5s8oj7gaJpZM4QjdeB>
>
> > .
> >
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <#883 (comment)
>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/
AAFaGFGIvtLGueST6kviQ1pTDBJsJTcSks5s9IvvgaJpZM4QjdeB>
> .
>
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#883 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAZuStzxuTp_BcuCTgWLj-_HPpR5N5nxks5s9PMTgaJpZM4QjdeB>
.
|
Do we want to add such a feature to MSan, or just leave this as experimental and close? |
Personal opinion: |
The instrumentation itself is simple, but a proper implementation will require quite a bit of work - driver changes, function attributes (we'd want it enabled per-function and per-source file), tests, etc. And I don't expect it to be widely used. I'd prefer not to have it in the codebase. |
Would that add much maintenance burden? |
And yet another issue that is detected by MSAN, but would be so much more meaningful with google/sanitizers#883
Hi.
This is related to google/oss-fuzz#863
I'm fuzzing a RawSpeed library.
Memory sanitizer is being extremely useful to find one particular set
of issues in decoders - when they don't actually decode the whole image
(i.e. part of the memory is left uninitialized), but also don't report an issue.
Right now, MSAN seems to only detect uninitialized reads that are then
used (as conditional variable), so i'm [ab]using
MSAN_MEM_IS_INITIALIZED()
.This works great, and at this moment has already found ~18 issues.
However, it's not quite what i would like it to be.
MSAN_MEM_IS_INITIALIZED()
calls.So i'm wondering whether
Roman.
The text was updated successfully, but these errors were encountered: