-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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: enable address sanitizer in Go #44853
Comments
I care about size of binary. Can you compare both size including small samples(<5M) and big samples(>10M)? |
@AZ-X If you run the go program without the -asan option, the size of binary will not change. Generally, we only enable the address sanitizer in the test environment to help detect memory access issues, so I think the size of binary is not important. Thank you. |
@AZ-X Regarding your question, my answer above seems too one-sided. I wrote a test case to compare the size of binary, and the size of binary with -asan is almost 10% larger than that without -asan. Please refer to the following results.
// the binay size:
From the above result, the size of binary is bigger. But as I mentioned above, we don't recommend opening the asan option in a production environment. The factors to consider are not only size, but also performance. The good news is that ARM64 has a new feature of MTE, which is designed to detect error memory accesses with lower overhead. If ASan with MTE is enabled in Go in the future, the impact on performance and the size of the binary will be relatively small. Thank you. |
Do we need any support for this at all? Though it can make sense to support MTE in Go runtime: |
In fact, we need to do something. Because Go has its own memory allocator, see https://golang.org/src/runtime/malloc.go, we may follow the implementaion in glic, refactor Go memory allcator (regarding the implementation details, I haven't done in-depth research. 🙂), setup memory tagging support if the hardware support it and if the user has requested it. Thank you. |
Yes, that's what I mean by "support MTE in Go runtime". But we don't need anything related to asan (linking asan, asan hooks, etc) |
Yes, you are right. With MTE, all load and store instructions, except for with SP base register and immediate offset, do check tags. Here https://github.com/google/sanitizers/wiki/Stack-instrumentation-with-ARM-Memory-Tagging-Extension-(MTE) introduces how MTE works for stack. Thank you. |
Change https://golang.org/cl/298610 mentions this issue: |
Change https://golang.org/cl/298611 mentions this issue: |
Change https://golang.org/cl/298612 mentions this issue: |
Change https://golang.org/cl/298613 mentions this issue: |
Change https://golang.org/cl/298614 mentions this issue: |
Change https://golang.org/cl/298615 mentions this issue: |
any updates? |
It has entered the code freeze for Go 1.17. 😟 @ianlancetaylor Any plans for it in 1.18? Thank you. |
I assume all these measurements are done on ARM, right? What about x86? Also, do you plan to implement first-class ASan support on x86-64? (Obviously, without MTE, as it's not available on x86) Yours, |
The size of binary with -asan is almost 11% larger than that without -asan. Please refer to the following results. The binary size on x86-64.
The current implementation also enables the ASan support on x86-64. Thank you. |
Change https://golang.org/cl/321715 mentions this issue: |
Change https://golang.org/cl/321716 mentions this issue: |
Hello! What are your plans on supporting ASan for stack-based objects? The problem is that usage of unsafe.Pointer does not affect escape analysis, and there are lots of cases with potentially insecure dereference of unsafe.Pointer to stack objects. AFAIK go does not generate any stack canary code, so those vulnerabilities should be easily exploitable. Also, if you add MTE support, which runtime are you going to use, and will it be part of Go Asan implementation, or another feature? Best wishes, Alex |
For reference, there was some discussion of some different aspects of this proposal in this golang-dev thread: https://groups.google.com/g/golang-dev/c/ACKO07YeeW8 @ph1048, FYI, there was some discussion there around stack objects, though perhaps @zhangfannie will have more to say here. |
With the implementation of CL 321715 , ASan in Go can detect the error memory access to heap objects and global objects. For stack objects, as we discussed in the golang-dev mailing list https://groups.google.com/g/golang-dev/c/ACKO07YeeW8/m/B93kNorLBgAJ, we currently have no plans to add support for it. In this way, support ASan in Go is complete. Welcome to review these patches. Thank you. |
Hi @zhangfannie With all respect, I find these two statements:
to be mutually contradictory. Without stack objects being supported, ASan for Go is definitely not "complete". "ASan for heap and global objects" can be called as complete, sure -- but I still maintain that users shouldn't care on where their objects are allocated, especially giving that escape analysis can move objects from heap to stack easily. As for plans to add support for stack objects, here is what @dvyukov wrote in the mailing list:
I read this as "let's do heap objects first, then decide on stack objects support". |
Thank you for correct my expression and "ASan for heap and global objects is complete" is more accurate. As for plans to add support for stack objects, here is what I wrote in the mailing list:
One problem is the compatibility of abi. Go passes a value, it is also equal to pass the memory, we can use unsafe.Pointer to access the parameter adress and return adress. So far, I am not very clear about the definition of Go calling convention. I am not sure it is passing by value, or passing a memory region shared by caller and callee. For example, in the following case, if ASan in Go wants to detect this error memory acces to stack objects, we need to insert redzone around the pass variables(a, b) and return variable (ret), which will break the current abi.
At present, we do not have a good idea to support it. There should be 3 kinds of stack memory need to be considered, including local variables, argument variables and return variables. If there is no clear calling conversion definition at the moment, maybe this can be a part of the discussion in regabi. @cherrymui |
Change https://golang.org/cl/368834 mentions this issue: |
For #44853 For #47694 Change-Id: Ia76246218b1361d8bdf510bbfc5178c83cdd3eec Reviewed-on: https://go-review.googlesource.com/c/go/+/368834 Trust: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Jeremy Faller <jeremy@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
Change https://golang.org/cl/375256 mentions this issue: |
…on when -asan is enabled When ASan is enabled, treat conversions to unsafe.Pointer as an escaping operation. In this way, all pointer operations on the stack objects will become operations on the escaped heap objects. As we've already supported ASan detection of error memory accesses to heap objects. With this trick, we can use -asan option to report errors on bad stack operations. Add test cases. Updates #44853. CustomizedGitHooks: yes Change-Id: I4e7fe46a3ce01f0d219e6a67dc50f4aff7d2ad87 Reviewed-on: https://go-review.googlesource.com/c/go/+/325629 Trust: Fannie Zhang <Fannie.Zhang@arm.com> Reviewed-by: Keith Randall <khr@golang.org>
Change https://go.dev/cl/393315 mentions this issue: |
…on when -asan is enabled When ASan is enabled, treat conversions to unsafe.Pointer as an escaping operation. In this way, all pointer operations on the stack objects will become operations on the escaped heap objects. As we've already supported ASan detection of error memory accesses to heap objects. With this trick, we can use -asan option to report errors on bad stack operations. Add test cases. Updates #44853. Change-Id: I6281e77f6ba581d7008d610f0b24316078b6e746 Reviewed-on: https://go-review.googlesource.com/c/go/+/393315 Trust: Fannie Zhang <Fannie.Zhang@arm.com> Run-TryBot: Fannie Zhang <Fannie.Zhang@arm.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Eric Fang <eric.fang@arm.com>
Change https://go.dev/cl/401775 mentions this issue: |
With this patch, -asan option can detect the error memory access to global variables. So this patch makes a few changes: 1. Add the asanregisterglobals runtime support function, which calls asan runtime function _asan_register_globals to register global variables. 2. Create a new initialization function for the package being compiled. This function initializes an array of instrumented global variables and pass it to function runtime.asanregisterglobals. An instrumented global variable has trailing redzone. 3. Writes the new size of instrumented global variables that have trailing redzones into object file. 4. Notice that the current implementation is only compatible with the ASan library from version v7 to v9. Therefore, using the -asan option requires that the gcc version is not less than 7 and the clang version is less than 4, otherwise a segmentation fault will occur. So this patch adds a check on whether the compiler being used is a supported version in cmd/go. Updates #44853. Change-Id: Ib877a817209ab2be68a8e22c418fe4a4a20880fc Reviewed-on: https://go-review.googlesource.com/c/go/+/401775 Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Bryan Mills <bcmills@google.com> Run-TryBot: Bryan Mills <bcmills@google.com> Auto-Submit: Bryan Mills <bcmills@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
Change https://go.dev/cl/403851 mentions this issue: |
With this patch, -asan option can detect the error memory access to global variables. So this patch makes a few changes: 1. Add the asanregisterglobals runtime support function, which calls asan runtime function _asan_register_globals to register global variables. 2. Create a new initialization function for the package being compiled. This function initializes an array of instrumented global variables and pass it to function runtime.asanregisterglobals. An instrumented global variable has trailing redzone. 3. Writes the new size of instrumented global variables that have trailing redzones into object file. 4. Notice that the current implementation is only compatible with the ASan library from version v7 to v9. Therefore, using the -asan option requires that the gcc version is not less than 7 and the clang version is less than 4, otherwise a segmentation fault will occur. So this patch adds a check on whether the compiler being used is a supported version in cmd/go. (This is a redo of CL 401775 with a fix for a build break due to an intervening commit that removed the internal/execabs package.) Updates #44853. Change-Id: I719d4ef2b22cb2d5516e1494cd453c3efb47d6c7 Reviewed-on: https://go-review.googlesource.com/c/go/+/403851 Auto-Submit: Bryan Mills <bcmills@google.com> Run-TryBot: Bryan Mills <bcmills@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com>
Change https://go.dev/cl/404214 mentions this issue: |
Add tests to test that -asan in Go can detect the error memory access to the global objects. Updates #44853. Change-Id: I612a048460b497d18389160b66e6f818342d3941 Reviewed-on: https://go-review.googlesource.com/c/go/+/321716 Run-TryBot: Fannie Zhang <Fannie.Zhang@arm.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Keith Randall <khr@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Benny Siegert <bsiegert@gmail.com>
Updates #44853 Change-Id: I3ba6ec0cfc6c7f311b586deedb1cda0f87a637aa Reviewed-on: https://go-review.googlesource.com/c/go/+/375256 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Joel Sing <joel@sing.id.au> Run-TryBot: Zhuo Meng <mzh@golangcn.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: David Chase <drchase@google.com>
Is there anything else need to be done for this? Thanks. |
@cherrymui The implementation mentioned in the proposal is complete, we can close it. Thanks for the reminder. |
@zhangfannie thanks for the getting this done! |
Change https://go.dev/cl/414516 mentions this issue: |
Package buildcfg was added to this list by CL 403851, but package buildcfg does not exist. This was probably intended to refer to internal/buildcfg, but internal/buildcfg is only used by the compiler so it is not clear why it couldn't be instrumented. For #44853. Change-Id: Iad2517358be79c3eabf240376156bcff0c4bcefc Reviewed-on: https://go-review.googlesource.com/c/go/+/414516 Reviewed-by: Bryan Mills <bcmills@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Michael Pratt <mpratt@google.com>
Package buildcfg was added to this list by CL 403851, but package buildcfg does not exist. This was probably intended to refer to internal/buildcfg, but internal/buildcfg is only used by the compiler so it is not clear why it couldn't be instrumented. For golang#44853. Change-Id: Iad2517358be79c3eabf240376156bcff0c4bcefc Reviewed-on: https://go-review.googlesource.com/c/go/+/414516 Reviewed-by: Bryan Mills <bcmills@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Michael Pratt <mpratt@google.com>
Change https://go.dev/cl/408814 mentions this issue: |
updates #44853 Change-Id: I71905ee1bcb99ce7300bbed2daad3617d2643c53 Reviewed-on: https://go-review.googlesource.com/c/go/+/408814 Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Benny Siegert <bsiegert@gmail.com> Reviewed-by: David Chase <drchase@google.com> Run-TryBot: Archana Ravindar <aravind5@in.ibm.com>
The address sanitizer (Asan) is a memory error detector, it finds a number of memory access errors that can occur in C, such as out-of-bounds accesses to heap, stack and global objects, and use-after-free. In general, these issues do not occur in the pure Go code, unless people intentionally use the unsafe package. However, people can use cgo to pass memory back and forth between C and Go, which will cause memory access problems.
Please refer to the following cases.
In this case (case-1) https://play.golang.org/p/eE_8k4poelj, C passes Go an invalid pointer, causing the Go code to have use-after-free errors. In this case (case-2) https://play.golang.org/p/wtHjV-4xuiL, Go passes C a pointer, the C code has out-of-bounds access to heap objects errors. In this case (case-3) https://play.golang.org/p/rOyEo7I7vTY, Go passes C a pointer, the C code has out-of-bounds access to global objects errors.
Integrating Asan with Go would detect the above memory errors. So it is useful. In addition, Asan can help to detect some memory errors that MSan cannot. For example, use-after-free memory error case https://play.golang.org/p/eE_8k4poelj, MSan cannot detect writes on uninitialized memory, while ASan can.
And we can instrument ASan in exactly the same way as MSan. As with the -msan option, if we do not run with -asan option, it has no effect on code execution, if you use it, it may find some memory errors.
Although the above cases are not real world cases. However, on the other hand, when debugging a memory error access in a Go program that calls C code, it is really good to be able to use Asan to ensure that code is correct. Obviously, this will require more code to be maintained in the toolchain, but since almost all of the code is next to the existing MSan code, this is quite limited.
Besides, Arm has a hardware feature MTE (Memory Tagging Extension), it aims to further mitigate these memory safety bugs by enabling us to detect them with low overhead. If ASan will be proven to be useful, we may consider enabling MTE for ASan. In this way, ASan even be enabled in the production environment to help to detect memory errors with low overhead. I saw a blog that introduces enable MTE in Android to detect the most common classes of memory safety bugs. Please refer to the document https://security.googleblog.com/2019/08/adopting-arm-memory-tagging-extension.html.
Thank you.
The text was updated successfully, but these errors were encountered: