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

x/crypto/curve25519: MOVQ global clobbers R15 when dynamically linking #18820

Closed
crawshaw opened this issue Jan 27, 2017 · 19 comments
Closed

x/crypto/curve25519: MOVQ global clobbers R15 when dynamically linking #18820

crawshaw opened this issue Jan 27, 2017 · 19 comments
Milestone

Comments

@crawshaw
Copy link
Member

The functions ladderstep, mul, and square load global values.

When dynamically linking on amd64, a the load uses R15 as a temporary. Unfortunately, these functions try to use R15 across these loads.

For example,

MOVQ ·REDMASK51(SB),DX

turns into MOVQ 0xABCD(IP), DX typically, but under the compiler's dynamic linking mode it becomes

MOVQ 0xABCD(IP), R15
MOVQ 0(R15), DX

The unit tests for this package (and crypto/tls which depends on this) hang under -buildmode=shared and fail under -buildmode=plugin:

curve25519_test.go:27: incorrect result: got 469423c8d7cc27bb36c7096de54d38d285740efa69594c1f98f49b113dcc7a19, want 89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a

cc @mwhudson

@bradfitz Any idea who owns this code? I'd like their opinion before touching it.

@crawshaw crawshaw added this to the Go1.8Maybe milestone Jan 27, 2017
@bradfitz
Copy link
Contributor

@agl is the meta owner of all x/crypto.

@agl agl self-assigned this Jan 27, 2017
@agl
Copy link
Contributor

agl commented Jan 27, 2017

These values should be hidden in "C shared library" terminology, i.e. they should not go via a GOT when loading. Is there some directive that can be used to make them as such?

@crawshaw
Copy link
Member Author

I do not believe we have such a mechanism. (Though I would be happy to be proven wrong.)

How performance sensitive are these functions? We could push the globals into stack slots at the start.

@agl
Copy link
Contributor

agl commented Jan 27, 2017

I can work around it, I'm sure, but if there's no notion of symbol visibility in Go does that mean that every function call goes via the PLT and every global access goes via the GOT? That does seem at odds with traditional shared-library conventions and unlikely to give good performance.

(I would guess that it also means that every function is listed in the dynamic exports table, but that's less crazy in Go since it already has namespaces.)

@crawshaw
Copy link
Member Author

crawshaw commented Jan 27, 2017

I suspect @mwhudson or @ianlancetaylor can give a better answer as they have thought about it more, but my attempt would be:

(EDIT) All exported symbols in -buildmode=shared and cgo exports need to exposed so they can be dynamically linked again. Otherwise all unexported symbols like this are hidden (in the "C shared library" sense), unless the //go:cgo_export_static or //go:cgo_export_dynamic directives are used. The toolchain is missing optimizations.

@agl
Copy link
Contributor

agl commented Jan 27, 2017

(If someone can definitively say that we're currently indirecting all global loads and thus need to avoid holding R15 during them I can start on the needed changes. Just want to make sure that this is needed though because it's unexpected to me.)

@ianlancetaylor
Copy link
Contributor

In the normal case we do not indirect global loads through R15. However, we do when the code is compiled with the -dynlink option, which happens when using the go tool options -buildmode=shared, -buildmode=plugin, or -linkshared. When the compiler is invoked with -dynlink, the assembler will be invoked with -D=GOBUILDMODE_shared=1, so it is possible for you to assemble different instruction sequences if you like.

@agl
Copy link
Contributor

agl commented Jan 28, 2017

@ianlancetaylor and there's no way to avoid the indirection when the symbol cannot be shadowed, like hidden symbols in C?

@ianlancetaylor
Copy link
Contributor

That is correct: it applies to every global symbol. There is no way to mark a symbol as hidden.

@mwhudson
Copy link
Contributor

Oh, good sleuthing @crawshaw

There is one way to make a symbol end up being local to the module being built, which is to use the ·foo<> form. But this is file local, which is not really appropriate here, as far as I can see.

@minux
Copy link
Member

minux commented Jan 30, 2017 via email

@ianlancetaylor ianlancetaylor modified the milestones: Go1.8, Go1.8Maybe Jan 30, 2017
@rsc
Copy link
Contributor

rsc commented Jan 30, 2017

@agl, yes there's no way to avoid the indirection. R15 is clobbered by global references like this, sorry. We should probably fix this for Go 1.8, right?

@mwhudson
Copy link
Contributor

Perhaps the linker should treat ·foo<> as private symbols when generating
shared libraries.

It does already. But that doesn't really help here.

It would be nice to fix this for 1.8, please. I can carry a fix as a distro patch until 1.8.1 if necessary if the timings don't work out.

@minux
Copy link
Member

minux commented Jan 31, 2017 via email

@gopherbot
Copy link

CL https://golang.org/cl/36359 mentions this issue.

@gopherbot
Copy link

CL https://golang.org/cl/36412 mentions this issue.

@rsc
Copy link
Contributor

rsc commented Feb 6, 2017

Fixed in subrepo. CL pending for master. Then have to cherry-pick to release branch.

@rsc rsc reopened this Feb 6, 2017
@rsc
Copy link
Contributor

rsc commented Feb 6, 2017

Final CL out: https://go-review.googlesource.com/36414

@rsc rsc closed this as completed Feb 6, 2017
@gopherbot
Copy link

CL https://golang.org/cl/36414 mentions this issue.

@rsc rsc reopened this Feb 6, 2017
gopherbot pushed a commit that referenced this issue Feb 6, 2017
…oss of R15 in -dynlink mode

Original code fixed in https://go-review.googlesource.com/#/c/36359/.

Fixes #18820.

Change-Id: I060e6c9d0e312b4fd5d0674aff131055bf5cf61d
Reviewed-on: https://go-review.googlesource.com/36412
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
Reviewed-on: https://go-review.googlesource.com/36414
Reviewed-by: Austin Clements <austin@google.com>
@rsc rsc closed this as completed Feb 7, 2017
@golang golang locked and limited conversation to collaborators Feb 7, 2018
c-expert-zigbee pushed a commit to c-expert-zigbee/crypto_go that referenced this issue Mar 28, 2022
Fixes golang/go#18820.

Change-Id: I4b3a49b3bbbecc4e1008989fefd39da9725a28ea
Reviewed-on: https://go-review.googlesource.com/36359
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Adam Langley <agl@golang.org>
c-expert-zigbee pushed a commit to c-expert-zigbee/crypto_go that referenced this issue Mar 29, 2022
Fixes golang/go#18820.

Change-Id: I4b3a49b3bbbecc4e1008989fefd39da9725a28ea
Reviewed-on: https://go-review.googlesource.com/36359
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Adam Langley <agl@golang.org>
@rsc rsc unassigned agl Jun 23, 2022
LewiGoddard pushed a commit to LewiGoddard/crypto that referenced this issue Feb 16, 2023
Fixes golang/go#18820.

Change-Id: I4b3a49b3bbbecc4e1008989fefd39da9725a28ea
Reviewed-on: https://go-review.googlesource.com/36359
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Adam Langley <agl@golang.org>
BiiChris pushed a commit to BiiChris/crypto that referenced this issue Sep 15, 2023
Fixes golang/go#18820.

Change-Id: I4b3a49b3bbbecc4e1008989fefd39da9725a28ea
Reviewed-on: https://go-review.googlesource.com/36359
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Adam Langley <agl@golang.org>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

8 participants