-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
runtime: possible memory corruption caused by CL 304470 "cmd/compile, runtime: add metadata for argument printing in traceback" #49075
Comments
How often does this happen? Is there any way we could reproduce? |
@catenacyber says it is still happening multiple times a day on OSS-Fuzz. Philippe, do you have any hints about an easy way to get a reproduction case on our own machines? |
Around 50 times a day on oss-fuzz
I did not manage to reproduce it myself, did not try very hard though...
Well, the hard thing is that this bug does not reproduce for a specific input.
Then, I guess you need to wait one hour, and relaunch the fuzzer if it did not trigger the bug, until it does
Is there some environment variable to do so ? |
Maybe oss-fuzz uses |
No, you'd have to edit the code to replace pool allocations with |
so rebuild the standard library ? |
Just edit it, rebuild will be automatic. |
So, I did google/oss-fuzz#6623 with regex.go not using |
google/oss-fuzz#6623 looks worth a shot. Thanks. |
It looks like the bug is still happening but much less often. One last stack trace is
Any more clues ? |
Could you bisect to a particular commit that introduced the corruption? |
oss-fuzz uses latest Golang release, so they switched from 1.16.x to 1.17 on August 16th, but we do not know which commit exactly in this major release induced the buggy behavior... |
I have another possible theory:
Is there any way you can get at the regexp and the contents of the string? In this case, My theory is that |
Put the hex encoded version of one string here : |
If it's an alignment issue, could we try to reproduce by mmap'ing a large block and creating a string with all the different possible alignments / ending pointer bytes? |
What is the regexp that is being used? |
regexp.MustCompile( |
So, there are kinds of a lot of answers to split.... |
Nothing obvious with the string+regexp you posted. Putting it at different alignments doesn't seem to trigger anything. |
This string posted comes with stack trace
|
When running manually, it seems my string is always aligned on 16 bytes.like |
That doesn't seem right. The string posted is only 227927 bytes, but the stack trace shows that is is 9841664 bytes. To unalign a string, do:
|
So, the string must have been corrupted before the call to |
I'm not sure I understand. How did you get the string, if not just dumping the 0x962c00 bytes starting at address 0x10c000ac201f ? |
oss-fuzz provides the stack trace, and the input that triggered it. |
Hm, then I guess the values in the stack traces are incorrect. Which can happen, especially with regabi introduced in 1.17. Another thing to try, run with |
FWIW, I was not able to reproduce either using the oss-fuzz local execution steps on a clean Linux VM (amd64, Ubuntu 20.04) following the directions outlined above in #49075 (comment), with 3 separate runs that totaled about 24 hours. I also ran for about 24 hours using dvyukov/go-fuzz against the same gonids fuzz target, which also did not crash (although I don't think there is an enormous amount of signal from that result, given libFuzzer and go-fuzz have different process restart strategies, different mutations, different propensity for creating large inputs, and so on). @catenacyber some questions for you:
That said, it might be that size of inputs in the corpus is not meaningful if this turns out to be due to some corruption.
In any event, sorry if anything I wrote is off base, but curious for your thoughts. |
Does it not exist already ?
It should then be :
But that looks dubious, like it will break another case. |
It does not.
It's the default. I think if we redesigned unix from scratch we'd always force signal handlers to have their own stack. |
A bit of background: when running with the Go runtime, all signals must be installed with the But if this program is using So while I'm sure I'm missing something, right now the only way I can see that a problem can arise is if we are using As a side note, setting |
Change https://go.dev/cl/494117 mentions this issue: |
I'm somewhat sure my patch fixes the issue, although hard to be 100% sure with the low failure rate. If anyone else wants to run some overnight jobs, that would be great. Especially on 1.19/1.20, as I've been working at tip. Patch for libFuzzer has been mailed: https://reviews.llvm.org/D150231 |
This is indeed the situation, Go initializes first. |
libfuzzer is written in C and so requires by the C abi that SP be aligned correctly mod 16. Normally CALLs need to have SP aligned to 0 mod 16, but because we're simulating a CALL (which pushes a return address) with a JMP (which doesn't), we need to align to 8 mod 16 before JMPing. This is not causing any current problems that I know of. All the functions called from this callsite that I checked don't rely on correct alignment. So this CL is just futureproofing. Update #49075 Change-Id: I13fcbe9aaf2853056a6d44dc3aa64b7db689e144 Reviewed-on: https://go-review.googlesource.com/c/go/+/494117 Reviewed-by: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com>
Thanks for these inputs. As I understand it, the problem lies rather in https://github.com/mdempsky/go114-fuzz-build ,the framework to link libFuzzer and golang: it should set a signaler handler that sets By the way, will the feature "guard page after a stack" be implemented ? It looks like ASAN for golang to me... |
I don't think that is the problem. libfuzzer would still be setting a SA_ONSTACK-less handler even if other handlers are registered correctly.
There is no plan for that at the moment. I'm happy to review the code if someone wants to take it on... Normally the compiler+linker enforces that Go can't overflow the stack. Signals not on an alternate stack are the only way I know of that the Go stack can overflow. |
I think the chaining of signal handlers solves the issue. |
I can see that preventing the crash, if your But won't that prevent delivery of the signals that libFuzzer wants? I presume |
I'm going to close this issue (and the backports). This probably needs a fix somewhere but it isn't in the Go repository. |
I think it does
Oh, is there a way for golang to pass signal to the next handler ? Cf https://github.com/catenacyber/gonids/tree/repro/pocsig
Running Running Running TL;DR @randall77 should go114-fuzz-build be fixed by adding a C signal handler with |
You don't need to install a new signal handler, you just need to reinstall the old signal handler with the |
Indeed Ian, thanks. So, you confirm that I cannot do that in pure Golang, and need to resort to C ? And I cannot build a static library containing both C and go with only one
I cannot compile sigfuzz.c and sigfuzz.go into sigfuzz.a in one command ? |
You can do it in pure Go using Or, just to be clear, you can do it using cgo without any supporting C files, although I don't know if that meets your requirements.
If you put your Go and C files into a single directory, then you can run |
Not sure I see how to do that... Thanks anyways :-) |
To define |
libfuzzer needs to have its signal handler with SA_ONSTACK because golang stacks are small cf golang/go#49075
libfuzzer needs to have its signal handler with SA_ONSTACK because golang stacks are small and not guarded against overflows Waiting for the clang libfuzzer patch cf https://reviews.llvm.org/D150231, we can fix the signal handlers with the help of `LLVMFuzzerInitialize` Long story : golang/go#49075 I hope it will improve the stability of all golang projects
OSS-Fuzz reported an issue a few weeks ago that we suspect is memory corruption caused by the runtime. This started on August 16th, so is likely a Go 1.17 issue.
A slice bounds out of range issue is being reported from calls to
regexp.MustCompile(,\s*).Split
However, this is not reproducible with the inputs provided by OSS-Fuzz, so we expect something else is going on.
Below are some of the panic logs:
From rsc@:
The relevant code is processing the
[][]int
returned fromregexp.(*Regexp).FindAllStringIndex
.That
[][]int
is prepared by repeated append:Each of the
match[0:2]
being appended is prepared inregexp.(*Regexp).doExecute
by:appending to a zero-length, non-nil slice to copy
m.matchcap
.And each of the
m.matchcap
is associated with the*regexp.machine m
, which is kept in async.Pool
for reuse.The specific corruption is that the integers in the
[][]int
are clear non-integers (like pointers),which suggests that either one of the appends is losing the reference accidentally during GC
or something in sync.Pool is wonky.
This could also be something strange that OSS-Fuzz is doing, and doesn't necessarily represent a real-world use case.
/cc @golang/security
The text was updated successfully, but these errors were encountered: