authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2022-06-08 14:33:11+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2022-06-08 14:33:11+02:00
log33817794268b5453794f98ee752403ff44693112
tree5d869719d15d72fb2e14bfdbe5cf32c46ce091ec
parent61844b6bd405b4cca3ab673284609aa6a651d506
signaturelock-open Commit is signed but in an unrecognized format.

linker: Enable full RELRO by default

Full RELRO is a hardening feature that makes it impossible to perform certian attacks involving overwriting parts of the Global Offset Table to invoke arbitrary code. It requires all symbols to be resolved before execution of the program starts which may have an impact on startup time. However most if not all popular Linux distributions enable full RELRO by default for all binaries and this does not seem to make a noticeable difference in practice. "Partial RELRO" is equivalent to `-z relro -z lazy`. "Full RELRO" is equivalent to `-z relro -z now`. LLD defaults to `-z relro -z lazy`, which means Zig's current `-z relro` option has no effect on LLD's behavior. The changes made by this commit are as follows: - Document that `-z relro` is the default and add `-z norelro`. - Pass `-z now` to LLD by default to enable full RELRO by default. - Add `-z lazy` to disable passing `-z now`.

3 files changed, 21 insertions(+), 11 deletions(-)

src/Compilation.zig+2-2
......@@ -763,8 +763,8 @@ pub const InitOptions = struct {
763763 linker_z_defs: bool = false,
764764 linker_z_origin: bool = false,
765765 linker_z_noexecstack: bool = false,
766 linker_z_now: bool = false,
767 linker_z_relro: bool = false,
766 linker_z_now: bool = true,
767 linker_z_relro: bool = true,
768768 linker_z_nocopyreloc: bool = false,
769769 linker_tsaware: bool = false,
770770 linker_nxcompat: bool = false,
src/link/Elf.zig+5-5
......@@ -1517,12 +1517,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
15171517 try argv.append("noexecstack");
15181518 }
15191519 if (self.base.options.z_now) {
1520 try argv.append("-z");
1521 try argv.append("now");
1520 // LLD defaults to -zlazy
1521 try argv.append("-znow");
15221522 }
1523 if (self.base.options.z_relro) {
1524 try argv.append("-z");
1525 try argv.append("relro");
1523 if (!self.base.options.z_relro) {
1524 // LLD defaults to -zrelro
1525 try argv.append("-znorelro");
15261526 }
15271527
15281528 if (getLDMOption(target)) |ldm| {
src/main.zig+14-4
......@@ -434,8 +434,10 @@ const usage_build_generic =
434434 \\ origin Indicate that the object must have its origin processed
435435 \\ nocopyreloc Disable the creation of copy relocations
436436 \\ noexecstack Indicate that the object requires an executable stack
437 \\ now Force all relocations to be processed on load
438 \\ relro Force all relocations to be resolved and be read-only on load
437 \\ now (default) Force all relocations to be processed on load
438 \\ lazy Don't force all relocations to be processed on load
439 \\ relro (default) Force all relocations to be read-only after processing
440 \\ norelro Don't force all relocations to be read-only after processing
439441 \\ -dynamic Force output to be dynamically linked
440442 \\ -static Force output to be statically linked
441443 \\ -Bsymbolic Bind global references locally
......@@ -655,8 +657,8 @@ fn buildOutputType(
655657 var linker_z_defs = false;
656658 var linker_z_origin = false;
657659 var linker_z_noexecstack = false;
658 var linker_z_now = false;
659 var linker_z_relro = false;
660 var linker_z_now = true;
661 var linker_z_relro = true;
660662 var linker_tsaware = false;
661663 var linker_nxcompat = false;
662664 var linker_dynamicbase = false;
......@@ -1209,8 +1211,12 @@ fn buildOutputType(
12091211 linker_z_noexecstack = true;
12101212 } else if (mem.eql(u8, z_arg, "now")) {
12111213 linker_z_now = true;
1214 } else if (mem.eql(u8, z_arg, "lazy")) {
1215 linker_z_now = false;
12121216 } else if (mem.eql(u8, z_arg, "relro")) {
12131217 linker_z_relro = true;
1218 } else if (mem.eql(u8, z_arg, "norelro")) {
1219 linker_z_relro = false;
12141220 } else {
12151221 warn("unsupported linker extension flag: -z {s}", .{z_arg});
12161222 }
......@@ -1691,8 +1697,12 @@ fn buildOutputType(
16911697 linker_z_noexecstack = true;
16921698 } else if (mem.eql(u8, z_arg, "now")) {
16931699 linker_z_now = true;
1700 } else if (mem.eql(u8, z_arg, "lazy")) {
1701 linker_z_now = false;
16941702 } else if (mem.eql(u8, z_arg, "relro")) {
16951703 linker_z_relro = true;
1704 } else if (mem.eql(u8, z_arg, "norelro")) {
1705 linker_z_relro = false;
16961706 } else {
16971707 warn("unsupported linker extension flag: -z {s}", .{z_arg});
16981708 }