1#! /usr/bin/perl
2use strict;
3use warnings;
4use File::Spec qw(rel2abs);
5use File::Basename;
6
7my @args = ();
8my $enabled = 0;
9my $debug = 0;
10my $debug_fd = *STDERR;
11
12# Set up defaults
13my %default;
14$default{'DEB_BUILD_HARDENING'}=0;
15$default{'DEB_BUILD_HARDENING_DEBUG'}=0;
16
17# Architecture settings
18# #OS# #ARCH#
19$default{'DEB_BUILD_HARDENING_RELRO'}=1;
20$default{'DEB_BUILD_HARDENING_BINDNOW'}=1;
21
22# System settings
23my $system_conf = '/etc/hardening-wrapper.conf';
24if (-r $system_conf) {
25    open(CONF,$system_conf) || warn "Cannot read $system_conf\n";
26    while (my $line = <CONF>) {
27        if ($line =~ /^\s*(DEB_BUILD_HARDENING[_A-Z]*)\s*=\s*(\d)$/) {
28            $default{$1}=$2+0;
29        }
30    }
31    close(CONF);
32}
33
34# Environment settings
35$enabled =        defined($ENV{'DEB_BUILD_HARDENING'}) ?
36                          $ENV{'DEB_BUILD_HARDENING'} :
37                          $default{'DEB_BUILD_HARDENING'};
38$debug =          defined($ENV{'DEB_BUILD_HARDENING_DEBUG'}) ?
39                          $ENV{'DEB_BUILD_HARDENING_DEBUG'} :
40                          $default{'DEB_BUILD_HARDENING_DEBUG'};
41my $force_relro = defined($ENV{'DEB_BUILD_HARDENING_RELRO'}) ?
42                          $ENV{'DEB_BUILD_HARDENING_RELRO'} :
43                          $default{'DEB_BUILD_HARDENING_RELRO'};
44my $force_bindnow = defined($ENV{'DEB_BUILD_HARDENING_BINDNOW'}) ?
45                          $ENV{'DEB_BUILD_HARDENING_BINDNOW'} :
46                          $default{'DEB_BUILD_HARDENING_BINDNOW'};
47
48if ($enabled) {
49    # Scan arguments
50    my $index = 0;
51    foreach my $arg (@ARGV) {
52        if ($arg eq "relro" && $index>0 && $ARGV[$index-1] eq "-z") {
53            $force_relro = 0;
54        }
55        if ($arg eq "now" && $index>0 && $ARGV[$index-1] eq "-z") {
56            $force_bindnow = 0;
57        }
58        $index++;
59    }
60
61    if ($force_relro) {
62        push(@args,'-z','relro');
63    }
64    if ($force_bindnow) {
65        push(@args,'-z','now');
66    }
67}
68
69my $self = "hardened-ld";
70my $link = "";
71my $arg0 = File::Spec->rel2abs(basename($0),dirname($0));
72my $tool = $arg0;
73if ($tool =~ /$self$/ || defined($ENV{'HARDENING_USE_USR_BIN'})) {
74    $tool = "/usr/bin/ld";
75}
76
77if (defined($ENV{'DEB_BUILD_HARDENING_DEBUG_OUTPUT'})) {
78    $debug_fd = undef;
79    if (!open($debug_fd, ">>$ENV{'DEB_BUILD_HARDENING_DEBUG_OUTPUT'}")) {
80        die "Cannot open $ENV{'DEB_BUILD_HARDENING_DEBUG_OUTPUT'}: $!\n";
81    }
82}
83
84sub resolve_link($)
85{
86    my $origin = $_[0];
87    my $link = readlink($origin);
88    return File::Spec->rel2abs($link,dirname($origin));
89}
90
91while (-l $tool && ($link = resolve_link($tool)) !~ /$self$/) {
92    $tool = $link;
93}
94if (-x "$tool.real") {
95    $tool = "$tool.real";
96}
97# Abort if we ended up on a circular symlink resolution
98if ($tool eq $arg0) {
99    my $short = $tool;
100    $short =~ s/.*\///g;
101	print STDERR "$tool: not found (maybe $short is not installed?)\n";
102	exit(127);
103}
104my @target = ($tool, @args, @ARGV);
105
106print $debug_fd join(" ",@target),"\n" if ($debug);
107
108exec @target or die "Unable to exec $target[0]: $!\n";
109