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

cmd/vet: improve the frame pointer check #69838

Open
nsrip-dd opened this issue Oct 10, 2024 · 7 comments
Open

cmd/vet: improve the frame pointer check #69838

nsrip-dd opened this issue Oct 10, 2024 · 7 comments
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FeatureRequest Issues asking for a new feature that does not need a proposal. help wanted NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@nsrip-dd
Copy link
Contributor

The framepointer check from go vet is currently quite conservative. Since Go 1.21, frame pointers have become more load-bearing in the Go runtime. They're now used on amd64 and arm64 to collect call stacks for the execution tracer and the block & mutex profilers. Now, frame pointer bugs can crash Go programs, whereas before they would merely result in broken call stacks for external profilers like Linux perf.

For example, #69629 was ultimately caused by a bug in programatically-generated amd64 assembly which clobbered the frame pointer register. As of Go 1.23.2, go vet misses that frame pointer bug. This is because the frame pointer is clobbered after a branch instruction, and the check aborts if it reaches a branch.

I think we should try to expand the number of bugs the framepointer check can catch. For example, arm64 support would be good. We also might be able to drop that branch check, or flag assembly that writes to rbp without a push rbp near the beginning and a pop rbp before returning. These kinds of ideas should of course be tested against existing open source Go assembly code, since I assume there is little (if any?) tolerance for false positives in go vet tools.

@cherrymui cherrymui added NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. FeatureRequest Issues asking for a new feature that does not need a proposal. labels Oct 10, 2024
@cherrymui cherrymui added this to the Backlog milestone Oct 10, 2024
@cherrymui cherrymui added the compiler/runtime Issues related to the Go compiler and/or runtime. label Oct 10, 2024
@mknyszek mknyszek modified the milestones: Backlog, Unplanned Oct 30, 2024
@prattmic
Copy link
Member

prattmic commented Dec 10, 2024

I ran an analysis on modules with 10 or more imports on the module proxy (~25k modules).

Normally I'd provide sampled results, but there are few enough results that these are the full results.

As a baseline, here are findings of the framepointer vet check at tip:

github.com/apache/arrow/go/v17@v17.0.0/arrow/compute/internal/kernels/base_arithmetic_avx2_amd64.s#L13322
github.com/apache/arrow/go/v17@v17.0.0/arrow/compute/internal/kernels/base_arithmetic_avx2_amd64.s#L18
github.com/apache/arrow/go/v17@v17.0.0/arrow/compute/internal/kernels/base_arithmetic_avx2_amd64.s#L20569
github.com/apache/arrow/go/v17@v17.0.0/arrow/compute/internal/kernels/base_arithmetic_avx2_amd64.s#L25887
github.com/apache/arrow/go/v17@v17.0.0/arrow/compute/internal/kernels/base_arithmetic_avx2_amd64.s#L5858
github.com/apache/arrow/go/v17@v17.0.0/arrow/compute/internal/kernels/base_arithmetic_sse4_amd64.s#L13800
github.com/apache/arrow/go/v17@v17.0.0/arrow/compute/internal/kernels/base_arithmetic_sse4_amd64.s#L16
github.com/apache/arrow/go/v17@v17.0.0/arrow/compute/internal/kernels/base_arithmetic_sse4_amd64.s#L20509
github.com/apache/arrow/go/v17@v17.0.0/arrow/compute/internal/kernels/base_arithmetic_sse4_amd64.s#L26381
github.com/apache/arrow/go/v17@v17.0.0/arrow/compute/internal/kernels/base_arithmetic_sse4_amd64.s#L7209
github.com/apache/arrow/go/v17@v17.0.0/arrow/compute/internal/kernels/cast_numeric_avx2_amd64.s#L37
github.com/apache/arrow/go/v17@v17.0.0/arrow/compute/internal/kernels/cast_numeric_sse4_amd64.s#L48
github.com/apache/arrow/go/v17@v17.0.0/internal/utils/min_max_avx2_amd64.s#L24
github.com/apache/arrow/go/v17@v17.0.0/internal/utils/min_max_avx2_amd64.s#L272
github.com/apache/arrow/go/v17@v17.0.0/internal/utils/min_max_avx2_amd64.s#L497
github.com/apache/arrow/go/v17@v17.0.0/internal/utils/min_max_avx2_amd64.s#L686
github.com/apache/arrow/go/v17@v17.0.0/internal/utils/min_max_avx2_amd64.s#L795
github.com/apache/arrow/go/v17@v17.0.0/internal/utils/min_max_sse4_amd64.s#L16
github.com/apache/arrow/go/v17@v17.0.0/internal/utils/min_max_sse4_amd64.s#L250
github.com/apache/arrow/go/v17@v17.0.0/internal/utils/min_max_sse4_amd64.s#L468
github.com/apache/arrow/go/v17@v17.0.0/internal/utils/min_max_sse4_amd64.s#L699
github.com/apache/arrow/go/v17@v17.0.0/internal/utils/min_max_sse4_amd64.s#L855
github.com/apache/arrow/go/v17@v17.0.0/parquet/internal/bmi/bitmap_bmi2_amd64.s#L29
<same findings on older versions of github.com/apache/arrow/go>
github.com/bwesterb/go-ristretto@v1.2.3/edwards25519/field_amd64.s#L15
github.com/cloudflare/cfssl@v1.6.5/scan/crypto/md5/md5block_amd64.s#L17
github.com/dgraph-io/ristretto@v0.2.0/z/simd/search_amd64.s#L15
github.com/dgryski/go-sip13@v0.0.0-20211015210918-3d5f40f242a3/sip13_amd64.s#L13
github.com/dgryski/go-sip13@v0.0.0-20211015210918-3d5f40f242a3/sip13_amd64.s#L172
github.com/emmansun/gmsm@v0.29.5/zuc/asm_amd64.s#L502
github.com/emmansun/gmsm@v0.29.5/zuc/asm_amd64.s#L649
github.com/gtank/ristretto255@v0.1.2/internal/radix51/fe_mul_amd64.s#L20
github.com/hellobchain/newcryptosm@v0.0.0-20221019060107-edb949a317e9/sm2/sm2_asm_amd64.s#L1536
github.com/hellobchain/newcryptosm@v0.0.0-20221019060107-edb949a317e9/sm2/sm2_asm_amd64.s#L1690
github.com/Hyperledger-TWGC/ccs-gm@v1.0.0/sm2/sm2p256_amd64.s#L1606
github.com/Hyperledger-TWGC/ccs-gm@v1.0.0/sm2/sm2p256_amd64.s#L1821
github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/ring0/entry_amd64.s#L404
github.com/outcaste-io/ristretto@v0.2.3/z/simd/search_amd64.s#L15
github.com/phoreproject/bls@v0.0.0-20200525203911-a88a5ae26844/primitivefuncs_amd64.s#L102
github.com/phoreproject/bls@v0.0.0-20200525203911-a88a5ae26844/primitivefuncs_amd64.s#L1474
github.com/phoreproject/bls@v0.0.0-20200525203911-a88a5ae26844/primitivefuncs_amd64.s#L1502
github.com/RyuaNerin/go-krypto@v1.3.0/lsh256/asm_amd64_avx2.s#L550
github.com/RyuaNerin/go-krypto@v1.3.0/lsh256/asm_amd64_avx2.s#L63
github.com/RyuaNerin/go-krypto@v1.3.0/lsh256/asm_amd64_ssse3.s#L32
github.com/RyuaNerin/go-krypto@v1.3.0/lsh256/asm_amd64_ssse3.s#L715
github.com/RyuaNerin/go-krypto@v1.3.0/lsh512/asm_amd64_avx2.s#L798
github.com/vmware/vmw-guestinfo@v0.0.0-20220317130741-510905f0efa3/bdoor/bdoor_amd64.s#L15
github.com/vmware/vmw-guestinfo@v0.0.0-20220317130741-510905f0efa3/bdoor/bdoor_amd64.s#L36
github.com/vmware/vmw-guestinfo@v0.0.0-20220317130741-510905f0efa3/bdoor/bdoor_amd64.s#L57
github.com/vmware/vmw-guestinfo@v0.0.0-20220317130741-510905f0efa3/bdoor/bdoor_amd64.s#L78
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/dasum_amd64.s#L3
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/daxpy_amd64.s#L3
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/dcopy_amd64.s#L10
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/ddot_amd64.s#L3
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/dnrm2_amd64.s#L3
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/drot_amd64.s#L3
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/dscal_amd64.s#L3
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/dswap_amd64.s#L6
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/idamax_amd64.s#L3
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/isamax_amd64.s#L3
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/sasum_amd64.s#L3
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/saxpy_amd64.s#L3
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/scopy_amd64.s#L10
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/sdot_amd64.s#L3
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/sdsdot_amd64.s#L3
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/snrm2_amd64.s#L3
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/srot_amd64.s#L3
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/sscal_amd64.s#L3
github.com/ziutek/blas@v0.0.0-20190227122918-da4ca23e90bb/sswap_amd64.s#L3
github.com/ztalab/cfssl@v0.0.6/scan/crypto/md5/md5block_amd64.s#L17
github.com/ztdbp/cfssl@v0.0.5/scan/crypto/md5/md5block_amd64.s#L17

The new findings from eliminating the bail out on control flow:

github.com/bamiaux/rez@v0.0.0-20170731184118-29f4463c688b/vscalers_amd64.s#L1019
github.com/bamiaux/rez@v0.0.0-20170731184118-29f4463c688b/vscalers_amd64.s#L1341
github.com/bamiaux/rez@v0.0.0-20170731184118-29f4463c688b/vscalers_amd64.s#L149
github.com/bamiaux/rez@v0.0.0-20170731184118-29f4463c688b/vscalers_amd64.s#L305
github.com/bamiaux/rez@v0.0.0-20170731184118-29f4463c688b/vscalers_amd64.s#L37
github.com/bamiaux/rez@v0.0.0-20170731184118-29f4463c688b/vscalers_amd64.s#L503
github.com/bamiaux/rez@v0.0.0-20170731184118-29f4463c688b/vscalers_amd64.s#L741
github.com/consensys/gnark-crypto@v0.14.0/ecc/bls12-381/internal/fptower/e2_amd64.s#L449
github.com/consensys/gnark-crypto@v0.14.0/ecc/bls24-315/internal/fptower/e2_amd64.s#L406
github.com/consensys/gnark-crypto@v0.14.0/ecc/bn254/internal/fptower/e2_amd64.s#L714
github.com/dgryski/go-metro@v0.0.0-20211217172704-adc40b04c140/metro_amd64.s#L205
github.com/dgryski/go-metro@v0.0.0-20211217172704-adc40b04c140/metro_amd64.s#L21
github.com/emmansun/gmsm@v0.29.5/sm4/gcm_amd64.s#L826
github.com/enceve/crypto@v0.0.0-20160707101852-34d48bb93815/chacha20/chacha/chacha_amd64.s#L213
github.com/fumiama/go-base16384@v1.7.0/base14_amd64.s#L137
github.com/fumiama/go-base16384@v1.7.0/base14_amd64.s#L16
github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L103710
github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L104213
github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L104533
github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L10918
github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L11247
github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L11535
github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L17922
github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L26231
github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L35773
github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L46607
github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L58798
github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L72411
github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L87270
github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L87838
github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L88196
github.com/minio/md5-simd@v1.1.2/md5block_amd64.s#L18
github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/ring0/entry_amd64.s#L467
github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/ring0/entry_amd64.s#L585
github.com/RyuaNerin/go-krypto@v1.3.0/lsh256/asm_amd64_avx2.s#L23
github.com/RyuaNerin/go-krypto@v1.3.0/lsh256/asm_amd64_sse2.s#L23
github.com/RyuaNerin/go-krypto@v1.3.0/lsh512/asm_amd64_avx2.s#L95
github.com/RyuaNerin/go-krypto@v1.3.0/lsh512/asm_amd64_sse2.s#L88
github.com/skycoin/skycoin@v0.28.0/src/cipher/chacha20poly1305/chacha20poly1305_amd64.s#L271
github.com/Sora233/MiraiGo-Template@v0.0.0-20230524170745-70b74eec19b8/internal/encryption/t544/encryption_amd64.s#L476
gitlab.com/yawning/chacha20.git@v0.0.0-20230427033715-7877545b1b37/internal/hardware/impl_amd64.s#L1032
leb.io/aeshash@v0.1.2/aeshash.s#L67

@randall77
Copy link
Contributor

I don't understand, for example, this one: https://go-mod-viewer.appspot.com/github.com/klauspost/reedsolomon@v1.12.4/galois_gen_amd64.s#L11535

It is in a function with a nonzero frame size, so we already spill/restore BP. The vet check shouldn't be checking such functions.
(The check here: https://cs.opensource.google/go/x/tools/+/master:go/analysis/passes/framepointer/framepointer.go;drc=74c9cfe4d22faa696baabeea02df6493b15e8c79;l=68 . Maybe that check is wrong? Perhaps it doesn't deactivate correctly from the previous function?)

@nsrip-dd
Copy link
Contributor Author

@prattmic and I discussed this on Gopher slack, small mistake in the change to the analyzer. If the branch check (which also checks for RET) is dropped with no other changes, then the analyzer stays "active" once it sees a frameless function for the first time. So in that example, it's looking for BP writes because the preceding function was frameless. We can tweak it to reset the active flag for every TEXT line.

@nsrip-dd
Copy link
Contributor Author

Excluding the false positives for functions with frames, the rest seem to mostly be true positives. One exception is https://go-mod-viewer.appspot.com/github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/ring0/entry_amd64.s#L467, which saves the frame pointer in a macro. Unless the vet check does preprocessing it's going to miss things like that.

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/635338 mentions this issue: go/analysis/passes/framepointer: support arm64

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/640075 mentions this issue: go/analysis/passes/framepointer: only stop on unconditional branches

gopherbot pushed a commit to golang/tools that referenced this issue Feb 7, 2025
Add arm64 support to the framepointer vet check. Essentially use the
same logic as the amd64 check: in instruction order, look at functions
without frames, and fail if the functions write to the frame pointer
register before reading it. Stop looking at a function on the first
branch instruction.

For golang/go#69838

Change-Id: If69be8a6eb5f9275df602c2c2ff644c338deaef2
Reviewed-on: https://go-review.googlesource.com/c/tools/+/635338
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FeatureRequest Issues asking for a new feature that does not need a proposal. help wanted NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

7 participants