mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile, cmd/link: disallow linkname of some newly added internal functions
Go API is defined through exported symbols. When a package is imported, the compiler ensures that only exported symbols can be accessed, and the go command ensures that internal packages cannot be imported. This ensures API integrity. But there is a hole: using linkname, one can access internal or non-exported symbols. Linkname is a mechanism to give access of a symbol to a package without adding it to the public API. It is intended for coupled packages to share some implementation details, or to break circular dependencies, and both "push" (definition) and "pull" (reference) sides are controlled, so they can be updated in sync. Nevertheless, it is abused as a mechanism to reach into internal details of other packages uncontrolled by the user, notably the runtime. As the other package evolves, the code often breaks, because the linknamed symbol may no longer exist, or change its signature or semantics. This CL adds a mechanism to enforce the integrity of linknames. Generally, "push" linkname is allowed, as the package defining the symbol explicitly opt in for access outside of the package. "Pull" linkname is checked and only allowed in some circumstances. Given that there are existing code that use "pull"-only linkname to access other package's internals, disallowing it completely is too much a change at this point in the release cycle. For a start, implement a hard-coded blocklist, which contains some newly added internal functions that, if used inappropriately, may break memory safety or runtime integrity. All blocked symbols are newly added in Go 1.23. So existing code that builds with Go 1.22 will continue to build. For the implementation, when compiling a package, we mark linknamed symbols in the current package with an attribute. At link time, marked linknamed symbols are checked against the blocklist. Care is taken so it distinguishes a linkname reference in the current package vs. a reference of a linkname from another package and propagated to the current package (e.g. through inlining or instantiation). Symbol references in assembly code are similar to linknames, and are treated similarly. Change-Id: I8067efe29c122740cd4f1effd2dec2d839147d5d Reviewed-on: https://go-review.googlesource.com/c/go/+/584598 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Than McIntosh <thanm@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
parent
df4f40b9e0
commit
4721f95058
14 changed files with 284 additions and 2 deletions
|
|
@ -836,6 +836,9 @@ const (
|
|||
// PkgInit indicates this is a compiler-generated package init func.
|
||||
AttrPkgInit
|
||||
|
||||
// Linkname indicates this is a go:linkname'd symbol.
|
||||
AttrLinkname
|
||||
|
||||
// attrABIBase is the value at which the ABI is encoded in
|
||||
// Attribute. This must be last; all bits after this are
|
||||
// assumed to be an ABI value.
|
||||
|
|
@ -865,6 +868,7 @@ func (a *Attribute) ContentAddressable() bool { return a.load()&AttrContentAddre
|
|||
func (a *Attribute) ABIWrapper() bool { return a.load()&AttrABIWrapper != 0 }
|
||||
func (a *Attribute) IsPcdata() bool { return a.load()&AttrPcdata != 0 }
|
||||
func (a *Attribute) IsPkgInit() bool { return a.load()&AttrPkgInit != 0 }
|
||||
func (a *Attribute) IsLinkname() bool { return a.load()&AttrLinkname != 0 }
|
||||
|
||||
func (a *Attribute) Set(flag Attribute, value bool) {
|
||||
for {
|
||||
|
|
@ -914,6 +918,7 @@ var textAttrStrings = [...]struct {
|
|||
{bit: AttrContentAddressable, s: ""},
|
||||
{bit: AttrABIWrapper, s: "ABIWRAPPER"},
|
||||
{bit: AttrPkgInit, s: "PKGINIT"},
|
||||
{bit: AttrLinkname, s: "LINKNAME"},
|
||||
}
|
||||
|
||||
// String formats a for printing in as part of a TEXT prog.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue