]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: move .dynamic and .got sections to relro if applicable
authorThan McIntosh <thanm@google.com>
Wed, 13 Mar 2024 19:03:43 +0000 (19:03 +0000)
committerThan McIntosh <thanm@google.com>
Mon, 22 Apr 2024 13:29:54 +0000 (13:29 +0000)
This is the second of two CLs to roll forward the changes in CL
473495, which was subsequently reverted.

In this patch we move the .dynamic and .got sections from the writable
data segment to the relro segment if the platform supports relro and
we're producing a PIE binary, and also moves .got.plt into relro if
eager binding is in effect (e.g. -bindnow or -Wl,-z,now).

Updates #45681.

Change-Id: I9f4fba6e825b96d1b5e27fb75844450dd0a650b3
Reviewed-on: https://go-review.googlesource.com/c/go/+/571417
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/elf.go
src/cmd/link/internal/ld/elf_test.go
src/cmd/link/internal/sym/symkind.go
src/cmd/link/internal/sym/symkind_string.go

index 11dc48b18b524978335394c262d75654e90cdded..feaa3c34d8d1c4de09cc23762cbce003aab824a4 100644 (file)
@@ -1850,7 +1850,7 @@ func (state *dodataState) allocateDataSections(ctxt *Link) {
        }
        ldr := ctxt.loader
 
-       // .got
+       // writable .got (note that for PIE binaries .got goes in relro)
        if len(state.data[sym.SELFGOT]) > 0 {
                state.allocateNamedSectionAndAssignSyms(&Segdata, ".got", sym.SELFGOT, sym.SDATA, 06)
        }
@@ -2106,6 +2106,7 @@ func (state *dodataState) allocateDataSections(ctxt *Link) {
                                xcoffUpdateOuterSize(ctxt, state.datsize-symnStartValue, symn)
                        }
                }
+               state.assignToSection(sect, sym.SELFRELROSECT, sym.SRODATA)
 
                sect.Length = uint64(state.datsize) - sect.Vaddr
        }
index 97b24b0cae40682278bbc5f89f9bf2a18e87f804..0d8455d92e336bb342d4078ae865cd216826e8db 100644 (file)
@@ -1113,6 +1113,7 @@ func elfphload(seg *sym.Segment) *ElfPhdr {
 func elfphrelro(seg *sym.Segment) {
        ph := newElfPhdr()
        ph.Type = elf.PT_GNU_RELRO
+       ph.Flags = elf.PF_R
        ph.Vaddr = seg.Vaddr
        ph.Paddr = seg.Vaddr
        ph.Memsz = seg.Length
@@ -1562,7 +1563,11 @@ func (ctxt *Link) doelf() {
 
                /* global offset table */
                got := ldr.CreateSymForUpdate(".got", 0)
-               got.SetType(sym.SELFGOT) // writable
+               if ctxt.UseRelro() {
+                       got.SetType(sym.SELFRELROSECT)
+               } else {
+                       got.SetType(sym.SELFGOT) // writable
+               }
 
                /* ppc64 glink resolver */
                if ctxt.IsPPC64() {
@@ -1575,7 +1580,11 @@ func (ctxt *Link) doelf() {
                hash.SetType(sym.SELFROSECT)
 
                gotplt := ldr.CreateSymForUpdate(".got.plt", 0)
-               gotplt.SetType(sym.SELFSECT) // writable
+               if ctxt.UseRelro() && *flagBindNow {
+                       gotplt.SetType(sym.SELFRELROSECT)
+               } else {
+                       gotplt.SetType(sym.SELFSECT) // writable
+               }
 
                plt := ldr.CreateSymForUpdate(".plt", 0)
                if ctxt.IsPPC64() {
@@ -1597,9 +1606,12 @@ func (ctxt *Link) doelf() {
 
                /* define dynamic elf table */
                dynamic := ldr.CreateSymForUpdate(".dynamic", 0)
-               if thearch.ELF.DynamicReadOnly {
+               switch {
+               case thearch.ELF.DynamicReadOnly:
                        dynamic.SetType(sym.SELFROSECT)
-               } else {
+               case ctxt.UseRelro():
+                       dynamic.SetType(sym.SELFRELROSECT)
+               default:
                        dynamic.SetType(sym.SELFSECT)
                }
 
index 16bf4039b1f3548f767ea3eefbbf863dfaba3f0c..b48cf66038752ec2e52b4979bf26b7e157bc8863 100644 (file)
@@ -198,6 +198,7 @@ func TestElfBindNow(t *testing.T) {
                name                 string
                args                 []string
                prog                 string
+               wantSecsRO           []string
                mustHaveBuildModePIE bool
                mustHaveCGO          bool
                mustInternalLink     bool
@@ -213,6 +214,7 @@ func TestElfBindNow(t *testing.T) {
                        mustHaveBuildModePIE: true,
                        mustInternalLink:     true,
                        wantDf1Pie:           true,
+                       wantSecsRO:           []string{".dynamic", ".got"},
                },
                {
                        name:             "bindnow-linkmode-internal",
@@ -232,6 +234,7 @@ func TestElfBindNow(t *testing.T) {
                        wantDfBindNow:        true,
                        wantDf1Now:           true,
                        wantDf1Pie:           true,
+                       wantSecsRO:           []string{".dynamic", ".got", ".got.plt"},
                },
                {
                        name:                 "bindnow-pie-linkmode-external",
@@ -242,6 +245,8 @@ func TestElfBindNow(t *testing.T) {
                        wantDfBindNow:        true,
                        wantDf1Now:           true,
                        wantDf1Pie:           true,
+                       // NB: external linker produces .plt.got, not .got.plt
+                       wantSecsRO: []string{".dynamic", ".got"},
                },
        }
 
@@ -251,10 +256,14 @@ func TestElfBindNow(t *testing.T) {
                                return true
                        }
                }
-
                return false
        }
 
+       segContainsSec := func(p *elf.Prog, s *elf.Section) bool {
+               return s.Addr >= p.Vaddr &&
+                       s.Addr+s.FileSize <= p.Vaddr+p.Filesz
+       }
+
        for _, test := range tests {
                t.Run(test.name, func(t *testing.T) {
                        if test.mustInternalLink {
@@ -329,6 +338,53 @@ func TestElfBindNow(t *testing.T) {
                        if gotDf1Pie := gotDynFlag(flags1, uint64(elf.DF_1_PIE)); gotDf1Pie != test.wantDf1Pie {
                                t.Fatalf("DT_FLAGS_1 DF_1_PIE got: %v, want: %v", gotDf1Pie, test.wantDf1Pie)
                        }
+
+                       for _, wsroname := range test.wantSecsRO {
+                               // Locate section of interest.
+                               var wsro *elf.Section
+                               for _, s := range elfFile.Sections {
+                                       if s.Name == wsroname {
+                                               wsro = s
+                                               break
+                                       }
+                               }
+                               if wsro == nil {
+                                       t.Fatalf("test %s: can't locate %q section",
+                                               test.name, wsroname)
+                               }
+
+                               // Now walk the program headers. Section should be part of
+                               // some segment that is readonly.
+                               foundRO := false
+                               foundSegs := []*elf.Prog{}
+                               for _, p := range elfFile.Progs {
+                                       if segContainsSec(p, wsro) {
+                                               foundSegs = append(foundSegs, p)
+                                               if p.Flags == elf.PF_R {
+                                                       foundRO = true
+                                               }
+                                       }
+                               }
+                               if !foundRO {
+                                       // Things went off the rails. Write out some
+                                       // useful information for a human looking at the
+                                       // test failure.
+                                       t.Logf("test %s: %q section not in readonly segment",
+                                               wsro.Name, test.name)
+                                       t.Logf("section %s location: st=0x%x en=0x%x\n",
+                                               wsro.Name, wsro.Addr, wsro.Addr+wsro.FileSize)
+                                       t.Logf("sec %s found in these segments: ", wsro.Name)
+                                       for _, p := range foundSegs {
+                                               t.Logf(" %q", p.Type)
+                                       }
+                                       t.Logf("\nall segments: \n")
+                                       for k, p := range elfFile.Progs {
+                                               t.Logf("%d t=%s fl=%s st=0x%x en=0x%x\n",
+                                                       k, p.Type, p.Flags, p.Vaddr, p.Vaddr+p.Filesz)
+                                       }
+                                       t.Fatalf("test %s failed", test.name)
+                               }
+                       }
                })
        }
 }
index 08cafb206b93097dfa6b174423d9f989ef546aa7..9a1f33c582815442e145b86a6afddd50b17e387e 100644 (file)
@@ -76,6 +76,7 @@ const (
        SGCBITSRELRO
        SRODATARELRO
        SFUNCTABRELRO
+       SELFRELROSECT
 
        // Part of .data.rel.ro if it exists, otherwise part of .rodata.
        STYPELINK
index 62b4fd92e505816c82e9e72297ca2a399e920b3a..b29c00334f0958348a4983dc4a68bb6709dfb95f 100644 (file)
@@ -27,53 +27,54 @@ func _() {
        _ = x[SGCBITSRELRO-16]
        _ = x[SRODATARELRO-17]
        _ = x[SFUNCTABRELRO-18]
-       _ = x[STYPELINK-19]
-       _ = x[SITABLINK-20]
-       _ = x[SSYMTAB-21]
-       _ = x[SPCLNTAB-22]
-       _ = x[SFirstWritable-23]
-       _ = x[SBUILDINFO-24]
-       _ = x[SELFSECT-25]
-       _ = x[SMACHO-26]
-       _ = x[SMACHOGOT-27]
-       _ = x[SWINDOWS-28]
-       _ = x[SELFGOT-29]
-       _ = x[SNOPTRDATA-30]
-       _ = x[SINITARR-31]
-       _ = x[SDATA-32]
-       _ = x[SXCOFFTOC-33]
-       _ = x[SBSS-34]
-       _ = x[SNOPTRBSS-35]
-       _ = x[SLIBFUZZER_8BIT_COUNTER-36]
-       _ = x[SCOVERAGE_COUNTER-37]
-       _ = x[SCOVERAGE_AUXVAR-38]
-       _ = x[STLSBSS-39]
-       _ = x[SXREF-40]
-       _ = x[SMACHOSYMSTR-41]
-       _ = x[SMACHOSYMTAB-42]
-       _ = x[SMACHOINDIRECTPLT-43]
-       _ = x[SMACHOINDIRECTGOT-44]
-       _ = x[SFILEPATH-45]
-       _ = x[SDYNIMPORT-46]
-       _ = x[SHOSTOBJ-47]
-       _ = x[SUNDEFEXT-48]
-       _ = x[SDWARFSECT-49]
-       _ = x[SDWARFCUINFO-50]
-       _ = x[SDWARFCONST-51]
-       _ = x[SDWARFFCN-52]
-       _ = x[SDWARFABSFCN-53]
-       _ = x[SDWARFTYPE-54]
-       _ = x[SDWARFVAR-55]
-       _ = x[SDWARFRANGE-56]
-       _ = x[SDWARFLOC-57]
-       _ = x[SDWARFLINES-58]
-       _ = x[SSEHUNWINDINFO-59]
-       _ = x[SSEHSECT-60]
+       _ = x[SELFRELROSECT-19]
+       _ = x[STYPELINK-20]
+       _ = x[SITABLINK-21]
+       _ = x[SSYMTAB-22]
+       _ = x[SPCLNTAB-23]
+       _ = x[SFirstWritable-24]
+       _ = x[SBUILDINFO-25]
+       _ = x[SELFSECT-26]
+       _ = x[SMACHO-27]
+       _ = x[SMACHOGOT-28]
+       _ = x[SWINDOWS-29]
+       _ = x[SELFGOT-30]
+       _ = x[SNOPTRDATA-31]
+       _ = x[SINITARR-32]
+       _ = x[SDATA-33]
+       _ = x[SXCOFFTOC-34]
+       _ = x[SBSS-35]
+       _ = x[SNOPTRBSS-36]
+       _ = x[SLIBFUZZER_8BIT_COUNTER-37]
+       _ = x[SCOVERAGE_COUNTER-38]
+       _ = x[SCOVERAGE_AUXVAR-39]
+       _ = x[STLSBSS-40]
+       _ = x[SXREF-41]
+       _ = x[SMACHOSYMSTR-42]
+       _ = x[SMACHOSYMTAB-43]
+       _ = x[SMACHOINDIRECTPLT-44]
+       _ = x[SMACHOINDIRECTGOT-45]
+       _ = x[SFILEPATH-46]
+       _ = x[SDYNIMPORT-47]
+       _ = x[SHOSTOBJ-48]
+       _ = x[SUNDEFEXT-49]
+       _ = x[SDWARFSECT-50]
+       _ = x[SDWARFCUINFO-51]
+       _ = x[SDWARFCONST-52]
+       _ = x[SDWARFFCN-53]
+       _ = x[SDWARFABSFCN-54]
+       _ = x[SDWARFTYPE-55]
+       _ = x[SDWARFVAR-56]
+       _ = x[SDWARFRANGE-57]
+       _ = x[SDWARFLOC-58]
+       _ = x[SDWARFLINES-59]
+       _ = x[SSEHUNWINDINFO-60]
+       _ = x[SSEHSECT-61]
 }
 
-const _SymKind_name = "SxxxSTEXTSELFRXSECTSMACHOPLTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSFirstWritableSBUILDINFOSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASXCOFFTOCSBSSSNOPTRBSSSLIBFUZZER_8BIT_COUNTERSCOVERAGE_COUNTERSCOVERAGE_AUXVARSTLSBSSSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILEPATHSDYNIMPORTSHOSTOBJSUNDEFEXTSDWARFSECTSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSSEHUNWINDINFOSSEHSECT"
+const _SymKind_name = "SxxxSTEXTSELFRXSECTSMACHOPLTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSELFRELROSECTSTYPELINKSITABLINKSSYMTABSPCLNTABSFirstWritableSBUILDINFOSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASXCOFFTOCSBSSSNOPTRBSSSLIBFUZZER_8BIT_COUNTERSCOVERAGE_COUNTERSCOVERAGE_AUXVARSTLSBSSSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILEPATHSDYNIMPORTSHOSTOBJSUNDEFEXTSDWARFSECTSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSSEHUNWINDINFOSSEHSECT"
 
-var _SymKind_index = [...]uint16{0, 4, 9, 19, 28, 33, 40, 49, 56, 63, 70, 78, 88, 98, 110, 124, 136, 148, 160, 173, 182, 191, 198, 206, 220, 230, 238, 244, 253, 261, 268, 278, 286, 291, 300, 304, 313, 336, 353, 369, 376, 381, 393, 405, 422, 439, 448, 458, 466, 475, 485, 497, 508, 517, 529, 539, 548, 559, 568, 579, 593, 601}
+var _SymKind_index = [...]uint16{0, 4, 9, 19, 28, 33, 40, 49, 56, 63, 70, 78, 88, 98, 110, 124, 136, 148, 160, 173, 186, 195, 204, 211, 219, 233, 243, 251, 257, 266, 274, 281, 291, 299, 304, 313, 317, 326, 349, 366, 382, 389, 394, 406, 418, 435, 452, 461, 471, 479, 488, 498, 510, 521, 530, 542, 552, 561, 572, 581, 592, 606, 614}
 
 func (i SymKind) String() string {
        if i >= SymKind(len(_SymKind_index)-1) {