Skip to content

Commit 65daf5b

Browse files
committed
Add linker warning for when it creates an executable stack.
PR 29072
1 parent 72b580b commit 65daf5b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+264
-46
lines changed

bfd/elflink.c

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7124,13 +7124,23 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
71247124
/* Determine any GNU_STACK segment requirements, after the backend
71257125
has had a chance to set a default segment size. */
71267126
if (info->execstack)
7127-
elf_stack_flags (output_bfd) = PF_R | PF_W | PF_X;
7127+
{
7128+
/* If the user has explicitly requested warnings, then generate one even
7129+
though the choice is the result of another command line option. */
7130+
if (info->warn_execstack == 1)
7131+
_bfd_error_handler
7132+
(_("\
7133+
warning: enabling an executable stack because of -z execstack command line option"));
7134+
elf_stack_flags (output_bfd) = PF_R | PF_W | PF_X;
7135+
}
71287136
else if (info->noexecstack)
71297137
elf_stack_flags (output_bfd) = PF_R | PF_W;
71307138
else
71317139
{
71327140
bfd *inputobj;
71337141
asection *notesec = NULL;
7142+
bfd *noteobj = NULL;
7143+
bfd *emptyobj = NULL;
71347144
int exec = 0;
71357145

71367146
for (inputobj = info->input_bfds;
@@ -7149,15 +7159,45 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
71497159
s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
71507160
if (s)
71517161
{
7152-
if (s->flags & SEC_CODE)
7153-
exec = PF_X;
71547162
notesec = s;
7163+
if (s->flags & SEC_CODE)
7164+
{
7165+
noteobj = inputobj;
7166+
exec = PF_X;
7167+
/* There is no point in scanning the remaining bfds. */
7168+
break;
7169+
}
71557170
}
71567171
else if (bed->default_execstack)
7157-
exec = PF_X;
7172+
{
7173+
exec = PF_X;
7174+
emptyobj = inputobj;
7175+
}
71587176
}
7177+
71597178
if (notesec || info->stacksize > 0)
7160-
elf_stack_flags (output_bfd) = PF_R | PF_W | exec;
7179+
{
7180+
if (exec)
7181+
{
7182+
if (info->warn_execstack != 2)
7183+
{
7184+
/* PR 29072: Because an executable stack is a serious
7185+
security risk, make sure that the user knows that it is
7186+
being enabled despite the fact that it was not requested
7187+
on the command line. */
7188+
if (noteobj)
7189+
_bfd_error_handler (_("\
7190+
warning: %s: requires executable stack (because the .note.GNU-stack section is executable)"),
7191+
bfd_get_filename (noteobj));
7192+
else if (emptyobj)
7193+
_bfd_error_handler (_("\
7194+
warning: %s: missing .note.GNU-stack section implies executable stack"),
7195+
bfd_get_filename (emptyobj));
7196+
}
7197+
}
7198+
elf_stack_flags (output_bfd) = PF_R | PF_W | exec;
7199+
}
7200+
71617201
if (notesec && exec && bfd_link_relocatable (info)
71627202
&& notesec->output_section != bfd_abs_section_ptr)
71637203
notesec->output_section->flags |= SEC_CODE;

include/bfdlink.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,10 @@ struct bfd_link_info
489489
flags. */
490490
unsigned int noexecstack: 1;
491491

492+
/* Tri-state variable: 0 => not set by user; 1 => set, warnings
493+
enabled; 2 => warnings disabled; 3 => unused. */
494+
unsigned int warn_execstack: 2;
495+
492496
/* TRUE if we want to produced optimized output files. This might
493497
need much more time and therefore must be explicitly selected. */
494498
unsigned int optimize: 1;

ld/NEWS

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
-*- text -*-
22

3+
* The linker will now generate a warning message if the stack is made
4+
executable. By default this warning is not issued if the user has
5+
specifically requested an executable stack via the "-z execstack"
6+
command line option, but the warning can be forced via the new
7+
"--warn-execstack" option. Alternatively all warnings about creating
8+
an executable stack can be suppressed via the "--no-warn-execstack"
9+
option.
10+
311
* TYPE=<type> is now supported in an output section description to set the
412
section type value.
513

ld/emultempl/avrelf.em

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ avr_elf_create_output_section_statements (void)
134134
einfo (_("%X%P: can not create stub BFD: %E\n"));
135135
return;
136136
}
137+
stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
137138

138139
/* Now we add the stub section. */
139140

ld/ld.texi

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2653,6 +2653,33 @@ Warn if any global constructors are used. This is only useful for a few
26532653
object file formats. For formats like COFF or ELF, the linker can not
26542654
detect the use of global constructors.
26552655

2656+
@kindex --warn-execstack
2657+
@cindex warnings, on exectuable stack
2658+
@cindex executable stack, warnings on
2659+
@item --warn-execstack
2660+
@itemx --no-warn-execstack
2661+
On ELF platforms this option controls how the linker generates warning
2662+
messages when it creates an output file with an executable stack. By
2663+
default the linker will not warn if the @command{-z execstack} command
2664+
line option has been used, but this behaviour can be overridden by the
2665+
@option{--warn-execstack} option.
2666+
2667+
On the other hand the linker will normally warn if the stack is made
2668+
executable because one or more of the input files need an execuable
2669+
stack and neither of the @command{-z execstack} or @command{-z
2670+
noexecstack} comman line options have been specified. This warning
2671+
can be disabled via the @command{--no-warn-execstack} option.
2672+
2673+
Note: ELF format input files specify that they need an executable
2674+
stack by having a @var{.note.GNU-stack} section with the executable
2675+
bit set in its section flags. They can specify that they do not need
2676+
an executable stack by having that section, but without the executable
2677+
flag bit set. If an input file does not have a @var{.note.GNU-stack}
2678+
section present then the default behaviour is target specific. For
2679+
some targets, then absence of such a section implies that an
2680+
executable stack @emph{is} required. This is often a problem for hand
2681+
crafted assembler files.
2682+
26562683
@kindex --warn-multiple-gp
26572684
@item --warn-multiple-gp
26582685
Warn if multiple global pointer values are required in the output file.

ld/ldlex.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ enum option_values
164164
OPTION_CTF_VARIABLES,
165165
OPTION_NO_CTF_VARIABLES,
166166
OPTION_CTF_SHARE_TYPES,
167+
OPTION_WARN_EXECSTACK,
168+
OPTION_NO_WARN_EXECSTACK,
167169
};
168170

169171
/* The initial parser states. */

ld/lexsup.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,10 @@ static const struct ld_option ld_options[] =
536536
{ {"warn-constructors", no_argument, NULL, OPTION_WARN_CONSTRUCTORS},
537537
'\0', NULL, N_("Warn if global constructors/destructors are seen"),
538538
TWO_DASHES },
539+
{ {"warn-execstack", no_argument, NULL, OPTION_WARN_EXECSTACK},
540+
'\0', NULL, N_("Warn when creating an executable stack"), TWO_DASHES },
541+
{ {"no-warn-execstack", no_argument, NULL, OPTION_NO_WARN_EXECSTACK},
542+
'\0', NULL, N_("Do not warn when creating an executable stack"), TWO_DASHES },
539543
{ {"warn-multiple-gp", no_argument, NULL, OPTION_WARN_MULTIPLE_GP},
540544
'\0', NULL, N_("Warn if the multiple GP values are used"), TWO_DASHES },
541545
{ {"warn-once", no_argument, NULL, OPTION_WARN_ONCE},
@@ -915,6 +919,12 @@ parse_args (unsigned argc, char **argv)
915919
case OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS:
916920
link_info.non_contiguous_regions_warnings = true;
917921
break;
922+
case OPTION_WARN_EXECSTACK:
923+
link_info.warn_execstack = 1;
924+
break;
925+
case OPTION_NO_WARN_EXECSTACK:
926+
link_info.warn_execstack = 2;
927+
break;
918928
case 'e':
919929
lang_add_entry (optarg, true);
920930
break;
@@ -2150,6 +2160,10 @@ elf_static_list_options (FILE *file)
21502160
fprintf (file, _("\
21512161
-z noexecstack Mark executable as not requiring executable stack\n"));
21522162
fprintf (file, _("\
2163+
--warn-execstack Generate a warning if the stack is executable\n"));
2164+
fprintf (file, _("\
2165+
--no-warn-execstack Do not generate a warning if the stack is executable\n"));
2166+
fprintf (file, _("\
21532167
-z unique-symbol Avoid duplicated local symbol names\n"));
21542168
fprintf (file, _("\
21552169
-z nounique-symbol Keep duplicated local symbol names (default)\n"));

ld/testsuite/ld-elf/eh4.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#source: eh4.s
22
#source: eh4a.s
33
#as: --64
4-
#ld: -melf_x86_64 -shared -Ttext 0x400 -z max-page-size=0x200000 -z noseparate-code
4+
#ld: -melf_x86_64 -shared -Ttext 0x400 -z max-page-size=0x200000 -z noseparate-code -z noexecstack
55
#readelf: -wf
66
#target: x86_64-*-*
77

ld/testsuite/ld-elf/elf.exp

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,24 @@ if { [check_gc_sections_available] && ![istarget "v850-*-*"] } {
180180
}
181181
}
182182

183-
if { [istarget *-*-*linux*]
184-
|| [istarget *-*-nacl*]
185-
|| [istarget *-*-gnu*] } {
183+
proc target_defaults_to_execstack {} {
184+
if { [istarget "aarch64*-*-*"]
185+
|| [istarget "arc*-*-*"]
186+
|| [istarget "ia64*-*-*"]
187+
|| [istarget "loongarch*-*-*"]
188+
|| [istarget "nios2*-*-*"]
189+
|| [istarget "powerpc64*-*-*"]
190+
|| [istarget "riscv*-*-*"]
191+
|| [istarget "tilegx*-*-*"]
192+
|| [istarget "tilepro*-*-*"] } {
193+
return 0
194+
}
195+
return 1
196+
}
197+
198+
if { [istarget *-*-*linux*]
199+
|| [istarget *-*-nacl*]
200+
|| [istarget *-*-gnu*] } {
186201
run_ld_link_tests [list \
187202
[list "stack exec" \
188203
"-z execstack" \
@@ -199,7 +214,7 @@ if { [istarget *-*-*linux*]
199214
{{readelf {-Wl} stack-noexec.rd}} \
200215
"stack-noexec.exe"] \
201216
[list "stack size" \
202-
"-z stack-size=0x123400" \
217+
"-z stack-size=0x123400 -z noexecstack" \
203218
"" \
204219
"" \
205220
{stack.s} \
@@ -212,7 +227,49 @@ if { [istarget *-*-*linux*]
212227
{pr23900-1.s} \
213228
[list [list "readelf" {-Wl} $pr23900_1_exp]] \
214229
"pr23900-1.exe"] \
230+
[list "PR ld/29072 (warn about an executable .note-GNU-stack)" \
231+
"-e 0" \
232+
"" \
233+
"" \
234+
{pr29072-a.s} \
235+
{{ld pr29072.a.warn}} \
236+
"pr29072-a.exe"] \
237+
[list "PR 29072 (warn about -z execstack)" \
238+
"-z execstack --warn-execstack" \
239+
"" \
240+
"" \
241+
{stack.s} \
242+
{{ld pr29072.c.warn}} \
243+
"pr29072-c.exe"] \
244+
[list "PR ld/29072 (suppress warnings about executable stack)" \
245+
"-e 0 --no-warn-execstack" \
246+
"" \
247+
"" \
248+
{pr29072-a.s} \
249+
{} \
250+
"pr29072-d.exe"] \
251+
]
252+
if { [target_defaults_to_execstack] } {
253+
run_ld_link_tests [list \
254+
[list "PR ld/29072 (warn about absent .note-GNU-stack)" \
255+
"-e 0 -z stack-size=0x123400" \
256+
"" \
257+
"" \
258+
{pr29072-b.s} \
259+
{{ld pr29072.b.warn}} \
260+
"pr29072-b.exe"] \
215261
]
262+
} else {
263+
run_ld_link_tests [list \
264+
[list "PR ld/29072 (ignore absent .note-GNU-stackk)" \
265+
"-e 0 -z stack-size=0x123400" \
266+
"" \
267+
"" \
268+
{pr29072-b.s} \
269+
{} \
270+
"pr29072-b.exe"] \
271+
]
272+
}
216273
}
217274

218275
if [check_gc_sections_available] {
@@ -365,7 +422,7 @@ if { [istarget *-*-linux*]
365422
run_ld_link_exec_tests [list \
366423
[list \
367424
"Run mbind2a" \
368-
"$NOPIE_LDFLAGS -Wl,-z,common-page-size=0x4000" \
425+
"$NOPIE_LDFLAGS -Wl,-z,common-page-size=0x4000 -Wl,-z,noexecstack" \
369426
"" \
370427
{ mbind2a.s mbind2b.c } \
371428
"mbind2a" \
@@ -374,7 +431,7 @@ if { [istarget *-*-linux*]
374431
] \
375432
[list \
376433
"Run mbind2b" \
377-
"-static -Wl,-z,common-page-size=0x4000" \
434+
"-static -Wl,-z,common-page-size=0x4000 -Wl,-z,noexecstack" \
378435
"" \
379436
{ mbind2a.s mbind2b.c } \
380437
"mbind2b" \

0 commit comments

Comments
 (0)