aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2024-11-05 13:51:32 -0500
committerGopher Robot <gobot@golang.org>2024-11-13 01:25:15 +0000
commit239dbd7dbac883d6f9b6522774a0dfd519f77fa8 (patch)
tree1275ae3fd7f8fc487636bce39f31a3e9094b579e /src/cmd/compile
parent7eeb0a188eb644486da9f77bae0375d91433d0bf (diff)
downloadgo-239dbd7dbac883d6f9b6522774a0dfd519f77fa8.tar.xz
cmd/compile, cmd/link: add FIPS verification support
For FIPS init-time code+data verification, we need to arrange to put the FIPS symbols into contiguous regions of the executable and then record those sections along with the expected checksum. The cmd/internal/obj changes identify the FIPS symbols and give them distinguished types, which the linker then places in contiguous regions. The linker also writes out information to use at run time to find the FIPS sections, along with the expected hash. See cmd/internal/obj/fips.go and cmd/link/internal/ld/fips.go for more details. The code is disabled in this commit. CL 625998 and 625999 adds tests. CL 626000 enables the code. For #69536. Change-Id: I48da6db94bc0bea7428c43d4abcf999527bccfcd Reviewed-on: https://go-review.googlesource.com/c/go/+/625997 Auto-Submit: Russ Cox <rsc@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/cmd/compile')
-rw-r--r--src/cmd/compile/internal/base/debug.go1
-rw-r--r--src/cmd/compile/internal/base/flag.go1
-rw-r--r--src/cmd/compile/internal/staticinit/sched.go44
-rw-r--r--src/cmd/compile/internal/walk/complit.go5
-rw-r--r--src/cmd/compile/internal/walk/order.go7
5 files changed, 53 insertions, 5 deletions
diff --git a/src/cmd/compile/internal/base/debug.go b/src/cmd/compile/internal/base/debug.go
index 05da3efe48..d42e11b2fa 100644
--- a/src/cmd/compile/internal/base/debug.go
+++ b/src/cmd/compile/internal/base/debug.go
@@ -30,6 +30,7 @@ type DebugFlags struct {
DwarfInl int `help:"print information about DWARF inlined function creation"`
EscapeMutationsCalls int `help:"print extra escape analysis diagnostics about mutations and calls" concurrent:"ok"`
Export int `help:"print export data"`
+ FIPSHash string `help:"hash value for FIPS debugging" concurrent:"ok"`
Fmahash string `help:"hash value for use in debugging platform-dependent multiply-add use" concurrent:"ok"`
GCAdjust int `help:"log adjustments to GOGC" concurrent:"ok"`
GCCheck int `help:"check heap/gc use by compiler" concurrent:"ok"`
diff --git a/src/cmd/compile/internal/base/flag.go b/src/cmd/compile/internal/base/flag.go
index b296f3666c..31ea8622b9 100644
--- a/src/cmd/compile/internal/base/flag.go
+++ b/src/cmd/compile/internal/base/flag.go
@@ -206,6 +206,7 @@ func ParseFlags() {
if Debug.Gossahash != "" {
hashDebug = NewHashDebug("gossahash", Debug.Gossahash, nil)
}
+ obj.SetFIPSDebugHash(Debug.FIPSHash)
// Compute whether we're compiling the runtime from the package path. Test
// code can also use the flag to set this explicitly.
diff --git a/src/cmd/compile/internal/staticinit/sched.go b/src/cmd/compile/internal/staticinit/sched.go
index 0e2f7119c6..e013823ee7 100644
--- a/src/cmd/compile/internal/staticinit/sched.go
+++ b/src/cmd/compile/internal/staticinit/sched.go
@@ -279,6 +279,14 @@ func (s *Schedule) staticcopy(l *ir.Name, loff int64, rn *ir.Name, typ *types.Ty
}
func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Type) bool {
+ // If we're building for FIPS, avoid global data relocations
+ // by treating all address-of operations as non-static.
+ // See ../../../internal/obj/fips.go for more context.
+ // We do this even in non-PIE mode to avoid generating
+ // static temporaries that would go into SRODATAFIPS
+ // but need relocations. We can't handle that in the verification.
+ disableGlobalAddrs := base.Ctxt.IsFIPS()
+
if r == nil {
// No explicit initialization value. Either zero or supplied
// externally.
@@ -304,10 +312,16 @@ func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Ty
switch r.Op() {
case ir.ONAME:
+ if disableGlobalAddrs {
+ return false
+ }
r := r.(*ir.Name)
return s.staticcopy(l, loff, r, typ)
case ir.OMETHEXPR:
+ if disableGlobalAddrs {
+ return false
+ }
r := r.(*ir.SelectorExpr)
return s.staticcopy(l, loff, r.FuncName(), typ)
@@ -322,6 +336,9 @@ func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Ty
return true
case ir.OADDR:
+ if disableGlobalAddrs {
+ return false
+ }
r := r.(*ir.AddrExpr)
if name, offset, ok := StaticLoc(r.X); ok && name.Class == ir.PEXTERN {
staticdata.InitAddrOffset(l, loff, name.Linksym(), offset)
@@ -330,6 +347,9 @@ func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Ty
fallthrough
case ir.OPTRLIT:
+ if disableGlobalAddrs {
+ return false
+ }
r := r.(*ir.AddrExpr)
switch r.X.Op() {
case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT, ir.OSTRUCTLIT:
@@ -346,6 +366,9 @@ func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Ty
//dump("not static ptrlit", r);
case ir.OSTR2BYTES:
+ if disableGlobalAddrs {
+ return false
+ }
r := r.(*ir.ConvExpr)
if l.Class == ir.PEXTERN && r.X.Op() == ir.OLITERAL {
sval := ir.StringVal(r.X)
@@ -354,6 +377,9 @@ func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Ty
}
case ir.OSLICELIT:
+ if disableGlobalAddrs {
+ return false
+ }
r := r.(*ir.CompLitExpr)
s.initplan(r)
// Init slice.
@@ -374,7 +400,7 @@ func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Ty
p := s.Plans[r]
for i := range p.E {
e := &p.E[i]
- if e.Expr.Op() == ir.OLITERAL || e.Expr.Op() == ir.ONIL {
+ if e.Expr.Op() == ir.OLITERAL && !disableGlobalAddrs || e.Expr.Op() == ir.ONIL {
staticdata.InitConst(l, loff+e.Xoffset, e.Expr, int(e.Expr.Type().Size()))
continue
}
@@ -388,6 +414,9 @@ func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Ty
break
case ir.OCLOSURE:
+ if disableGlobalAddrs {
+ return false
+ }
r := r.(*ir.ClosureExpr)
if !r.Func.IsClosure() {
if base.Debug.Closure > 0 {
@@ -405,6 +434,10 @@ func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Ty
// This logic is mirrored in isStaticCompositeLiteral.
// If you change something here, change it there, and vice versa.
+ if disableGlobalAddrs {
+ return false
+ }
+
// Determine the underlying concrete type and value we are converting from.
r := r.(*ir.ConvExpr)
val := ir.Node(r)
@@ -460,6 +493,9 @@ func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Ty
return true
case ir.OINLCALL:
+ if disableGlobalAddrs {
+ return false
+ }
r := r.(*ir.InlinedCallExpr)
return s.staticAssignInlinedCall(l, loff, r, typ)
}
@@ -728,10 +764,12 @@ func (s *Schedule) staticAssignInlinedCall(l *ir.Name, loff int64, call *ir.Inli
var statuniqgen int // name generator for static temps
// StaticName returns a name backed by a (writable) static data symbol.
-// Use readonlystaticname for read-only node.
func StaticName(t *types.Type) *ir.Name {
// Don't use LookupNum; it interns the resulting string, but these are all unique.
- sym := typecheck.Lookup(fmt.Sprintf("%s%d", obj.StaticNamePref, statuniqgen))
+ sym := typecheck.Lookup(fmt.Sprintf("%s%d", obj.StaticNamePrefix, statuniqgen))
+ if sym.Name == ".stmp_0" && sym.Pkg.Path == "crypto/internal/fips/check" {
+ panic("bad")
+ }
statuniqgen++
n := ir.NewNameAt(base.Pos, sym, t)
diff --git a/src/cmd/compile/internal/walk/complit.go b/src/cmd/compile/internal/walk/complit.go
index cfdc8becfe..70750ab037 100644
--- a/src/cmd/compile/internal/walk/complit.go
+++ b/src/cmd/compile/internal/walk/complit.go
@@ -153,7 +153,10 @@ func isStaticCompositeLiteral(n ir.Node) bool {
case ir.OLITERAL, ir.ONIL:
return true
case ir.OCONVIFACE:
- // See staticassign's OCONVIFACE case for comments.
+ // See staticinit.Schedule.StaticAssign's OCONVIFACE case for comments.
+ if base.Ctxt.IsFIPS() && base.Ctxt.Flag_shared {
+ return false
+ }
n := n.(*ir.ConvExpr)
val := ir.Node(n)
for val.Op() == ir.OCONVIFACE {
diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go
index 896088901e..613edf497b 100644
--- a/src/cmd/compile/internal/walk/order.go
+++ b/src/cmd/compile/internal/walk/order.go
@@ -220,7 +220,12 @@ func (o *orderState) safeExpr(n ir.Node) ir.Node {
//
// n.Left = o.addrTemp(n.Left)
func (o *orderState) addrTemp(n ir.Node) ir.Node {
- if n.Op() == ir.OLITERAL || n.Op() == ir.ONIL {
+ // Note: Avoid addrTemp with static assignment for literal strings
+ // when compiling FIPS packages.
+ // The problem is that panic("foo") ends up creating a static RODATA temp
+ // for the implicit conversion of "foo" to any, and we can't handle
+ // the relocations in that temp.
+ if n.Op() == ir.ONIL || (n.Op() == ir.OLITERAL && !base.Ctxt.IsFIPS()) {
// TODO: expand this to all static composite literal nodes?
n = typecheck.DefaultLit(n, nil)
types.CalcSize(n.Type())