Skip to content

Commit

Permalink
Add linker warning for when it creates an executable stack.
Browse files Browse the repository at this point in the history
   PR 29072
  • Loading branch information
nickclifton committed Apr 20, 2022
1 parent 72b580b commit 65daf5b
Show file tree
Hide file tree
Showing 77 changed files with 264 additions and 46 deletions.
50 changes: 45 additions & 5 deletions bfd/elflink.c
Original file line number Diff line number Diff line change
Expand Up @@ -7124,13 +7124,23 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
/* Determine any GNU_STACK segment requirements, after the backend
has had a chance to set a default segment size. */
if (info->execstack)
elf_stack_flags (output_bfd) = PF_R | PF_W | PF_X;
{
/* If the user has explicitly requested warnings, then generate one even
though the choice is the result of another command line option. */
if (info->warn_execstack == 1)
_bfd_error_handler
(_("\
warning: enabling an executable stack because of -z execstack command line option"));
elf_stack_flags (output_bfd) = PF_R | PF_W | PF_X;
}
else if (info->noexecstack)
elf_stack_flags (output_bfd) = PF_R | PF_W;
else
{
bfd *inputobj;
asection *notesec = NULL;
bfd *noteobj = NULL;
bfd *emptyobj = NULL;
int exec = 0;

for (inputobj = info->input_bfds;
Expand All @@ -7149,15 +7159,45 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
if (s)
{
if (s->flags & SEC_CODE)
exec = PF_X;
notesec = s;
if (s->flags & SEC_CODE)
{
noteobj = inputobj;
exec = PF_X;
/* There is no point in scanning the remaining bfds. */
break;
}
}
else if (bed->default_execstack)
exec = PF_X;
{
exec = PF_X;
emptyobj = inputobj;
}
}

if (notesec || info->stacksize > 0)
elf_stack_flags (output_bfd) = PF_R | PF_W | exec;
{
if (exec)
{
if (info->warn_execstack != 2)
{
/* PR 29072: Because an executable stack is a serious
security risk, make sure that the user knows that it is
being enabled despite the fact that it was not requested
on the command line. */
if (noteobj)
_bfd_error_handler (_("\
warning: %s: requires executable stack (because the .note.GNU-stack section is executable)"),
bfd_get_filename (noteobj));
else if (emptyobj)
_bfd_error_handler (_("\
warning: %s: missing .note.GNU-stack section implies executable stack"),
bfd_get_filename (emptyobj));
}
}
elf_stack_flags (output_bfd) = PF_R | PF_W | exec;
}

if (notesec && exec && bfd_link_relocatable (info)
&& notesec->output_section != bfd_abs_section_ptr)
notesec->output_section->flags |= SEC_CODE;
Expand Down
4 changes: 4 additions & 0 deletions include/bfdlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,10 @@ struct bfd_link_info
flags. */
unsigned int noexecstack: 1;

/* Tri-state variable: 0 => not set by user; 1 => set, warnings
enabled; 2 => warnings disabled; 3 => unused. */
unsigned int warn_execstack: 2;

/* TRUE if we want to produced optimized output files. This might
need much more time and therefore must be explicitly selected. */
unsigned int optimize: 1;
Expand Down
8 changes: 8 additions & 0 deletions ld/NEWS
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
-*- text -*-

* The linker will now generate a warning message if the stack is made
executable. By default this warning is not issued if the user has
specifically requested an executable stack via the "-z execstack"
command line option, but the warning can be forced via the new
"--warn-execstack" option. Alternatively all warnings about creating
an executable stack can be suppressed via the "--no-warn-execstack"
option.

* TYPE=<type> is now supported in an output section description to set the
section type value.

Expand Down
1 change: 1 addition & 0 deletions ld/emultempl/avrelf.em
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ avr_elf_create_output_section_statements (void)
einfo (_("%X%P: can not create stub BFD: %E\n"));
return;
}
stub_file->the_bfd->flags |= BFD_LINKER_CREATED;

/* Now we add the stub section. */

Expand Down
27 changes: 27 additions & 0 deletions ld/ld.texi
Original file line number Diff line number Diff line change
Expand Up @@ -2653,6 +2653,33 @@ Warn if any global constructors are used. This is only useful for a few
object file formats. For formats like COFF or ELF, the linker can not
detect the use of global constructors.

@kindex --warn-execstack
@cindex warnings, on exectuable stack
@cindex executable stack, warnings on
@item --warn-execstack
@itemx --no-warn-execstack
On ELF platforms this option controls how the linker generates warning
messages when it creates an output file with an executable stack. By
default the linker will not warn if the @command{-z execstack} command
line option has been used, but this behaviour can be overridden by the
@option{--warn-execstack} option.

On the other hand the linker will normally warn if the stack is made
executable because one or more of the input files need an execuable
stack and neither of the @command{-z execstack} or @command{-z
noexecstack} comman line options have been specified. This warning
can be disabled via the @command{--no-warn-execstack} option.

Note: ELF format input files specify that they need an executable
stack by having a @var{.note.GNU-stack} section with the executable
bit set in its section flags. They can specify that they do not need
an executable stack by having that section, but without the executable
flag bit set. If an input file does not have a @var{.note.GNU-stack}
section present then the default behaviour is target specific. For
some targets, then absence of such a section implies that an
executable stack @emph{is} required. This is often a problem for hand
crafted assembler files.

@kindex --warn-multiple-gp
@item --warn-multiple-gp
Warn if multiple global pointer values are required in the output file.
Expand Down
2 changes: 2 additions & 0 deletions ld/ldlex.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ enum option_values
OPTION_CTF_VARIABLES,
OPTION_NO_CTF_VARIABLES,
OPTION_CTF_SHARE_TYPES,
OPTION_WARN_EXECSTACK,
OPTION_NO_WARN_EXECSTACK,
};

/* The initial parser states. */
Expand Down
14 changes: 14 additions & 0 deletions ld/lexsup.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,10 @@ static const struct ld_option ld_options[] =
{ {"warn-constructors", no_argument, NULL, OPTION_WARN_CONSTRUCTORS},
'\0', NULL, N_("Warn if global constructors/destructors are seen"),
TWO_DASHES },
{ {"warn-execstack", no_argument, NULL, OPTION_WARN_EXECSTACK},
'\0', NULL, N_("Warn when creating an executable stack"), TWO_DASHES },
{ {"no-warn-execstack", no_argument, NULL, OPTION_NO_WARN_EXECSTACK},
'\0', NULL, N_("Do not warn when creating an executable stack"), TWO_DASHES },
{ {"warn-multiple-gp", no_argument, NULL, OPTION_WARN_MULTIPLE_GP},
'\0', NULL, N_("Warn if the multiple GP values are used"), TWO_DASHES },
{ {"warn-once", no_argument, NULL, OPTION_WARN_ONCE},
Expand Down Expand Up @@ -915,6 +919,12 @@ parse_args (unsigned argc, char **argv)
case OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS:
link_info.non_contiguous_regions_warnings = true;
break;
case OPTION_WARN_EXECSTACK:
link_info.warn_execstack = 1;
break;
case OPTION_NO_WARN_EXECSTACK:
link_info.warn_execstack = 2;
break;
case 'e':
lang_add_entry (optarg, true);
break;
Expand Down Expand Up @@ -2150,6 +2160,10 @@ elf_static_list_options (FILE *file)
fprintf (file, _("\
-z noexecstack Mark executable as not requiring executable stack\n"));
fprintf (file, _("\
--warn-execstack Generate a warning if the stack is executable\n"));
fprintf (file, _("\
--no-warn-execstack Do not generate a warning if the stack is executable\n"));
fprintf (file, _("\
-z unique-symbol Avoid duplicated local symbol names\n"));
fprintf (file, _("\
-z nounique-symbol Keep duplicated local symbol names (default)\n"));
Expand Down
2 changes: 1 addition & 1 deletion ld/testsuite/ld-elf/eh4.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#source: eh4.s
#source: eh4a.s
#as: --64
#ld: -melf_x86_64 -shared -Ttext 0x400 -z max-page-size=0x200000 -z noseparate-code
#ld: -melf_x86_64 -shared -Ttext 0x400 -z max-page-size=0x200000 -z noseparate-code -z noexecstack
#readelf: -wf
#target: x86_64-*-*

Expand Down
69 changes: 63 additions & 6 deletions ld/testsuite/ld-elf/elf.exp
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,24 @@ if { [check_gc_sections_available] && ![istarget "v850-*-*"] } {
}
}

if { [istarget *-*-*linux*]
|| [istarget *-*-nacl*]
|| [istarget *-*-gnu*] } {
proc target_defaults_to_execstack {} {
if { [istarget "aarch64*-*-*"]
|| [istarget "arc*-*-*"]
|| [istarget "ia64*-*-*"]
|| [istarget "loongarch*-*-*"]
|| [istarget "nios2*-*-*"]
|| [istarget "powerpc64*-*-*"]
|| [istarget "riscv*-*-*"]
|| [istarget "tilegx*-*-*"]
|| [istarget "tilepro*-*-*"] } {
return 0
}
return 1
}

if { [istarget *-*-*linux*]
|| [istarget *-*-nacl*]
|| [istarget *-*-gnu*] } {
run_ld_link_tests [list \
[list "stack exec" \
"-z execstack" \
Expand All @@ -199,7 +214,7 @@ if { [istarget *-*-*linux*]
{{readelf {-Wl} stack-noexec.rd}} \
"stack-noexec.exe"] \
[list "stack size" \
"-z stack-size=0x123400" \
"-z stack-size=0x123400 -z noexecstack" \
"" \
"" \
{stack.s} \
Expand All @@ -212,7 +227,49 @@ if { [istarget *-*-*linux*]
{pr23900-1.s} \
[list [list "readelf" {-Wl} $pr23900_1_exp]] \
"pr23900-1.exe"] \
[list "PR ld/29072 (warn about an executable .note-GNU-stack)" \
"-e 0" \
"" \
"" \
{pr29072-a.s} \
{{ld pr29072.a.warn}} \
"pr29072-a.exe"] \
[list "PR 29072 (warn about -z execstack)" \
"-z execstack --warn-execstack" \
"" \
"" \
{stack.s} \
{{ld pr29072.c.warn}} \
"pr29072-c.exe"] \
[list "PR ld/29072 (suppress warnings about executable stack)" \
"-e 0 --no-warn-execstack" \
"" \
"" \
{pr29072-a.s} \
{} \
"pr29072-d.exe"] \
]
if { [target_defaults_to_execstack] } {
run_ld_link_tests [list \
[list "PR ld/29072 (warn about absent .note-GNU-stack)" \
"-e 0 -z stack-size=0x123400" \
"" \
"" \
{pr29072-b.s} \
{{ld pr29072.b.warn}} \
"pr29072-b.exe"] \
]
} else {
run_ld_link_tests [list \
[list "PR ld/29072 (ignore absent .note-GNU-stackk)" \
"-e 0 -z stack-size=0x123400" \
"" \
"" \
{pr29072-b.s} \
{} \
"pr29072-b.exe"] \
]
}
}

if [check_gc_sections_available] {
Expand Down Expand Up @@ -365,7 +422,7 @@ if { [istarget *-*-linux*]
run_ld_link_exec_tests [list \
[list \
"Run mbind2a" \
"$NOPIE_LDFLAGS -Wl,-z,common-page-size=0x4000" \
"$NOPIE_LDFLAGS -Wl,-z,common-page-size=0x4000 -Wl,-z,noexecstack" \
"" \
{ mbind2a.s mbind2b.c } \
"mbind2a" \
Expand All @@ -374,7 +431,7 @@ if { [istarget *-*-linux*]
] \
[list \
"Run mbind2b" \
"-static -Wl,-z,common-page-size=0x4000" \
"-static -Wl,-z,common-page-size=0x4000 -Wl,-z,noexecstack" \
"" \
{ mbind2a.s mbind2b.c } \
"mbind2b" \
Expand Down
Loading

0 comments on commit 65daf5b

Please sign in to comment.