[RFC] gdb, configure: Add disable-readers option for configure
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gdb_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 |
success
|
Test passed
|
Commit Message
This is a proof-of-concept of a feature we've discussed internally for a
bit of time, where users would be able to select debug information
formats to not be readable by GDB. This comes from a security concern,
since some readers are pretty old and haven't been touched in a while,
but if they have vulnerabilities, they would make every GDB vulnerable.
This makes it so downstreams don't have to scramble to fix every
security issue, even for things that are extremely unlikely to be used.
I'm not sure I like the way this selection works yet. The ideal way this
features works for me is if we could say --disable-readers=foo,bar, however
autoconf will always treat --disable-option as being an alias for
--enable-option=no, so its impossible to do it that way. The choices then
become either using --enable-readers (the approach of this patch) or adding
a switch for every reader that can be disabled, which could pollute the
help text. If anyone has opinions on which is best - or knows of an even
better way to do this - I'm all ears. This is my first patch dealing
with autotools after all...
I'm also sending this as an RFC to see if people think this is a useful
feature, before I go on to disentangle the many readers and allow for
separate compilation, just in case this turns out to be a doomed project
:-)
---
GDB has support for many debug information formats, some which might be
very unlikely to be found in some situations (such as the COFF format in
linux). This commit introduces the option for a user to choose which
formats GDB will support at build configuration time.
This is especially useful to avoid possible security concerns with
readers that aren't expected to be used at all, as debug info is one of
the simplest vectors for an attacker to try and hit GDB with. This
change also can reduce the size of the final binary, if that is a
concern.
In this patch, most readers are still considered mandatory as there is
interdependence between what should be independent formats, but future
patches should remove this interdependence and allow all the listed
debug format to be independently enabled or disabled.
The only reader that can be safely disabled at this point is xcoff,
which shows no regressions in my fedora 40 machine.
---
gdb/Makefile.in | 76 ++++++++++++++++++++++++--------------------
gdb/README | 3 ++
gdb/configure | 50 +++++++++++++++++++++++++++--
gdb/configure.ac | 37 +++++++++++++++++++++
gdb/configure.reader | 51 +++++++++++++++++++++++++++++
5 files changed, 181 insertions(+), 36 deletions(-)
create mode 100644 gdb/configure.reader
Comments
On 2024-08-26 13:45, Guinevere Larsen wrote:
> This is a proof-of-concept of a feature we've discussed internally for a
> bit of time, where users would be able to select debug information
> formats to not be readable by GDB. This comes from a security concern,
> since some readers are pretty old and haven't been touched in a while,
> but if they have vulnerabilities, they would make every GDB vulnerable.
> This makes it so downstreams don't have to scramble to fix every
> security issue, even for things that are extremely unlikely to be used.
>
> I'm not sure I like the way this selection works yet. The ideal way this
> features works for me is if we could say --disable-readers=foo,bar, however
> autoconf will always treat --disable-option as being an alias for
> --enable-option=no, so its impossible to do it that way. The choices then
> become either using --enable-readers (the approach of this patch) or adding
> a switch for every reader that can be disabled, which could pollute the
> help text. If anyone has opinions on which is best - or knows of an even
> better way to do this - I'm all ears. This is my first patch dealing
> with autotools after all...
>
> I'm also sending this as an RFC to see if people think this is a useful
> feature, before I go on to disentangle the many readers and allow for
> separate compilation, just in case this turns out to be a doomed project
> :-)
>
> ---
I think you should not put your meta-comment (or whathever that's
called, the comment that you want to send to the list but not want to be
part of the commit message) before `---`, because git-am strips what
follows `---`, so we effectively lose your commit message when applying
your patch. I think the idea is that you're supposed to put your
meta-comment after this `---`, so that it does get removed by git-am. I
think it's fine for the "new in v2" kind of messages, but in your case
I'd rather see the context before reading the commit message, so I don't
know what's the best way. We could perhaps find and settle on a
convention for this particular case.
> GDB has support for many debug information formats, some which might be
> very unlikely to be found in some situations (such as the COFF format in
> linux). This commit introduces the option for a user to choose which
> formats GDB will support at build configuration time.
>
> This is especially useful to avoid possible security concerns with
> readers that aren't expected to be used at all, as debug info is one of
> the simplest vectors for an attacker to try and hit GDB with. This
> change also can reduce the size of the final binary, if that is a
> concern.
>
> In this patch, most readers are still considered mandatory as there is
> interdependence between what should be independent formats, but future
> patches should remove this interdependence and allow all the listed
> debug format to be independently enabled or disabled.
>
> The only reader that can be safely disabled at this point is xcoff,
> which shows no regressions in my fedora 40 machine.
I think the idea and the justification are good. If I understand
correctly from the description above, the default is to include all
debug info readers, but as soon as you use the --enable-readers=...
option, then only the specified readers are enabled (an "additive"
option)? This seems fine to me for the "security conscious" folks,
since it makes it so that you only enabled the debug info you asked for.
If a new one gets added, it won't get enable without an action from your
part.
So, I'd be fine without a "subtractive" option (start with all enabled
and remove the specified ones). But if you really wanted to make one,
one way would be to go with a variable (AC_ARG_VAR), although that would
be inconsistent with how we do things today.
Once it is agreed that it is a direction we'd like to take, I would
prefer if we did the work to make all debug info readers optional prior
to merging, so that we won't have this weird state of have some debug
info formats that are mandatory. I know that we use some DWARF stuff in
some core structures, that will probably need to be sorted out, but it's
probably for good. It will help avoid this kind of abstraction leak.
Simon
On 8/26/24 11:58 PM, Simon Marchi wrote:
>
> On 2024-08-26 13:45, Guinevere Larsen wrote:
>> This is a proof-of-concept of a feature we've discussed internally for a
>> bit of time, where users would be able to select debug information
>> formats to not be readable by GDB. This comes from a security concern,
>> since some readers are pretty old and haven't been touched in a while,
>> but if they have vulnerabilities, they would make every GDB vulnerable.
>> This makes it so downstreams don't have to scramble to fix every
>> security issue, even for things that are extremely unlikely to be used.
>>
>> I'm not sure I like the way this selection works yet. The ideal way this
>> features works for me is if we could say --disable-readers=foo,bar, however
>> autoconf will always treat --disable-option as being an alias for
>> --enable-option=no, so its impossible to do it that way. The choices then
>> become either using --enable-readers (the approach of this patch) or adding
>> a switch for every reader that can be disabled, which could pollute the
>> help text. If anyone has opinions on which is best - or knows of an even
>> better way to do this - I'm all ears. This is my first patch dealing
>> with autotools after all...
>>
>> I'm also sending this as an RFC to see if people think this is a useful
>> feature, before I go on to disentangle the many readers and allow for
>> separate compilation, just in case this turns out to be a doomed project
>> :-)
>>
>> ---
> I think you should not put your meta-comment (or whathever that's
> called, the comment that you want to send to the list but not want to be
> part of the commit message) before `---`, because git-am strips what
> follows `---`, so we effectively lose your commit message when applying
> your patch. I think the idea is that you're supposed to put your
> meta-comment after this `---`, so that it does get removed by git-am. I
> think it's fine for the "new in v2" kind of messages, but in your case
> I'd rather see the context before reading the commit message, so I don't
> know what's the best way. We could perhaps find and settle on a
> convention for this particular case.
Ah, sorry. I thought that this time it made sense to have the meta
explanation before the more technical information, and I thought I had
seen in the past git am not stripping meta comments, so I thought this
was fine. I'll keep my meta comments to after the commit messsages from
now on.
>
>> GDB has support for many debug information formats, some which might be
>> very unlikely to be found in some situations (such as the COFF format in
>> linux). This commit introduces the option for a user to choose which
>> formats GDB will support at build configuration time.
>>
>> This is especially useful to avoid possible security concerns with
>> readers that aren't expected to be used at all, as debug info is one of
>> the simplest vectors for an attacker to try and hit GDB with. This
>> change also can reduce the size of the final binary, if that is a
>> concern.
>>
>> In this patch, most readers are still considered mandatory as there is
>> interdependence between what should be independent formats, but future
>> patches should remove this interdependence and allow all the listed
>> debug format to be independently enabled or disabled.
>>
>> The only reader that can be safely disabled at this point is xcoff,
>> which shows no regressions in my fedora 40 machine.
> I think the idea and the justification are good. If I understand
> correctly from the description above, the default is to include all
> debug info readers, but as soon as you use the --enable-readers=...
> option, then only the specified readers are enabled (an "additive"
> option)? This seems fine to me for the "security conscious" folks,
> since it makes it so that you only enabled the debug info you asked for.
> If a new one gets added, it won't get enable without an action from your
> part.
You did understand it correctly. When you put it that way, that nothing
will silently be enabled by GDB updates, using --enable does sound like
a better choice.
>
> So, I'd be fine without a "subtractive" option (start with all enabled
> and remove the specified ones). But if you really wanted to make one,
> one way would be to go with a variable (AC_ARG_VAR), although that would
> be inconsistent with how we do things today.
>
> Once it is agreed that it is a direction we'd like to take, I would
> prefer if we did the work to make all debug info readers optional prior
> to merging, so that we won't have this weird state of have some debug
> info formats that are mandatory. I know that we use some DWARF stuff in
> some core structures, that will probably need to be sorted out, but it's
> probably for good. It will help avoid this kind of abstraction leak.
I planned on sending this as the first patch of a series, and subsequent
patches would introduce code changes required to be able to disable
other readers.
Would you prefer if I instead sent separate patches/series disentangling
the code, and once everything is merged I send a final patch with the
configure changes?
On 2024-08-27 06:25, Guinevere Larsen wrote:
> I planned on sending this as the first patch of a series, and
> subsequent patches would introduce code changes required to be able to
> disable other readers.
>
> Would you prefer if I instead sent separate patches/series
> disentangling the code, and once everything is merged I send a final
> patch with the configure changes?
I would imagine a series that makes any necessary adjustments to the
code first, and the last patch adding the configure machinery to make
all readers optional. But I don't know the amount of work it
represents, so it's not a hard requirement. Just that when we leave
things as "future work", we tend not to do it, so it's preferable to do
it right the first time, when possible.
Simon
On 8/27/24 11:06 AM, Simon Marchi wrote:
>
> On 2024-08-27 06:25, Guinevere Larsen wrote:
>> I planned on sending this as the first patch of a series, and
>> subsequent patches would introduce code changes required to be able to
>> disable other readers.
>>
>> Would you prefer if I instead sent separate patches/series
>> disentangling the code, and once everything is merged I send a final
>> patch with the configure changes?
> I would imagine a series that makes any necessary adjustments to the
> code first, and the last patch adding the configure machinery to make
> all readers optional. But I don't know the amount of work it
> represents, so it's not a hard requirement. Just that when we leave
> things as "future work", we tend not to do it, so it's preferable to do
> it right the first time, when possible.
I've been looking into this some more, and talked to Andrew a bit, and I
think this patch (and gdb in general) muddles 2 different concepts.
There are file format readers, and there are debug information readers.
Both are named <something>reader.c (except for the dwarf2 one), but the
ones that deal with file formats register a symtab_fns struct, while the
ones that deal with only debug information don't - and their functions
get called directly by file format readers.
I'm spitting this project into 2, one that disables file formats, and
the other that disables debug info support even if the file format would
support it. I'll send them in this order, since file formats are much
easier - we should have all the infrastructure in place from symtab_fns,
so it's mostly disentangling debug info from file format reading.
@@ -908,6 +908,46 @@ ALL_TARGET_OBS = \
xtensa-tdep.o \
z80-tdep.o
+# Object files for reading specific types of debug information.
+READER_OBS = @READER_OBS@
+
+# All files that relate to GDB's ability to read debug information.
+# Used with --enable-readers=all.
+ALL_READER_OBS = \
+ coff-pe-read.o \
+ coffread.o \
+ ctfread.o \
+ dbxread.o \
+ dwarf2/abbrev.o \
+ dwarf2/abbrev-cache.o \
+ dwarf2/ada-imported.o \
+ dwarf2/aranges.o \
+ dwarf2/attribute.o \
+ dwarf2/comp-unit-head.o \
+ dwarf2/cooked-index.o \
+ dwarf2/cu.o \
+ dwarf2/die.o \
+ dwarf2/dwz.o \
+ dwarf2/expr.o \
+ dwarf2/frame-tailcall.o \
+ dwarf2/frame.o \
+ dwarf2/index-cache.o \
+ dwarf2/index-common.o \
+ dwarf2/index-write.o \
+ dwarf2/leb.o \
+ dwarf2/line-header.o \
+ dwarf2/loc.o \
+ dwarf2/macro.o \
+ dwarf2/read.o \
+ dwarf2/read-debug-names.o \
+ dwarf2/read-gdb-index.o \
+ dwarf2/section.o \
+ dwarf2/stringify.o \
+ mdebugread.o \
+ mipsread.o \
+ stabsread.o \
+ xcoffread.o
+
# The following native-target dependent variables are defined on
# configure.nat.
NAT_FILE = @NAT_FILE@
@@ -1063,8 +1103,6 @@ COMMON_SFILES = \
c-varobj.c \
charset.c \
cli-out.c \
- coff-pe-read.c \
- coffread.c \
complaints.c \
completer.c \
copying.c \
@@ -1074,11 +1112,9 @@ COMMON_SFILES = \
cp-namespace.c \
cp-support.c \
cp-valprint.c \
- ctfread.c \
d-lang.c \
d-namespace.c \
d-valprint.c \
- dbxread.c \
dcache.c \
debug.c \
debuginfod-support.c \
@@ -1086,31 +1122,6 @@ COMMON_SFILES = \
disasm.c \
displaced-stepping.c \
dummy-frame.c \
- dwarf2/abbrev.c \
- dwarf2/abbrev-cache.c \
- dwarf2/ada-imported.c \
- dwarf2/aranges.c \
- dwarf2/attribute.c \
- dwarf2/comp-unit-head.c \
- dwarf2/cooked-index.c \
- dwarf2/cu.c \
- dwarf2/die.c \
- dwarf2/dwz.c \
- dwarf2/expr.c \
- dwarf2/frame-tailcall.c \
- dwarf2/frame.c \
- dwarf2/index-cache.c \
- dwarf2/index-common.c \
- dwarf2/index-write.c \
- dwarf2/leb.c \
- dwarf2/line-header.c \
- dwarf2/loc.c \
- dwarf2/macro.c \
- dwarf2/read.c \
- dwarf2/read-debug-names.c \
- dwarf2/read-gdb-index.c \
- dwarf2/section.c \
- dwarf2/stringify.c \
extract-store-integer.c \
eval.c \
event-top.c \
@@ -1162,7 +1173,6 @@ COMMON_SFILES = \
maint.c \
maint-test-options.c \
maint-test-settings.c \
- mdebugread.c \
mem-break.c \
memattr.c \
memory-map.c \
@@ -1170,7 +1180,6 @@ COMMON_SFILES = \
memtag.c \
minidebug.c \
minsyms.c \
- mipsread.c \
namespace.c \
objc-lang.c \
objfiles.c \
@@ -1212,7 +1221,6 @@ COMMON_SFILES = \
source.c \
source-cache.c \
split-name.c \
- stabsread.c \
stack.c \
std-regs.c \
symfile.c \
@@ -1884,7 +1892,6 @@ ALLDEPFILES = \
windows-tdep.c \
x86-nat.c \
x86-tdep.c \
- xcoffread.c \
xstormy16-tdep.c \
xtensa-config.c \
xtensa-linux-nat.c \
@@ -1906,7 +1913,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
$(SUBDIR_CLI_OBS) \
$(SUBDIR_MI_OBS) \
$(SUBDIR_TARGET_OBS) \
- $(SUBDIR_GCC_COMPILE_OBS)
+ $(SUBDIR_GCC_COMPILE_OBS) \
+ $(READER_OBS)
SUBDIRS = doc @subdirs@ data-directory
CLEANDIRS = $(SUBDIRS)
@@ -403,6 +403,9 @@ more obscure GDB `configure' options are not listed here.
specified list of targets. The special value `all' configures
GDB for debugging programs running on any target it supports.
+`--disable-readers=READER,READER,...'
+ Configure GDB to be unable to read some formats of debug information.
+
`--with-gdb-datadir=PATH'
Set the GDB-specific data directory. GDB will look here for
certain supporting files or scripts. This defaults to the `gdb'
@@ -760,6 +760,7 @@ HAVE_NATIVE_GCORE_TARGET
TARGET_OBS
AMD_DBGAPI_LIBS
AMD_DBGAPI_CFLAGS
+READER_OBS
ENABLE_BFD_64_BIT_FALSE
ENABLE_BFD_64_BIT_TRUE
subdirs
@@ -933,6 +934,7 @@ with_relocated_sources
with_auto_load_dir
with_auto_load_safe_path
enable_targets
+enable_readers
enable_64_bit_bfd
with_amd_dbgapi
enable_tui
@@ -1644,6 +1646,9 @@ Optional Features:
--disable-nls do not use Native Language Support
--enable-targets=TARGETS
alternative target configurations
+ --enable-readers=DEBUG_READERS
+ enable the chosen debug information readers (default
+ 'all')
--enable-64-bit-bfd 64-bit support (on hosts with narrower word sizes)
--enable-tui enable full-screen terminal user interface (TUI)
--enable-gdbtk enable gdbtk graphical user interface (GUI)
@@ -11499,7 +11504,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11502 "configure"
+#line 11507 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11605,7 +11610,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11608 "configure"
+#line 11613 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -24833,6 +24838,20 @@ esac
fi
+all_readers=
+# Check whether --enable-readers was given.
+if test "${enable_readers+set}" = set; then :
+ enableval=$enable_readers; case "${enableval}" in
+ yes | "") as_fn_error $? "enable-readers option must specify debuginfo readers or 'all'" "$LINENO" 5
+ ;;
+ no) enable_readers= ;;
+ *) enable_readers=$enableval ;;
+esac
+else
+ all_readers=true
+fi
+
+
# Check whether --enable-64-bit-bfd was given.
if test "${enable_64_bit_bfd+set}" = set; then :
enableval=$enable_64_bit_bfd; case $enableval in #(
@@ -24966,6 +24985,33 @@ if test x${all_targets} = xtrue; then
fi
fi
+READER_OBS=
+
+for reader in `echo $enable_readers | sed 's/,/ /g'`
+do
+ if test "$reader" = "all"; then
+ all_readers=true
+ fi
+
+ . ${srcdir}/configure.reader
+done
+
+if test "$all_readers" = "true"; then
+ READER_OBS='$(ALL_READER_OBS)'
+else
+ # These are objfiles for debuginfo readers we hope to be able to disable
+ # at compile time some day, but we can't yet because of assumptions in the
+ # codebase.
+ required_readers="coffread.o coff-pe-read.o ctfread.o dbxread.o dwarf2/read.o mdebugread.o mipsread.o stabsread.o"
+ for req in $required_readers; do
+ if ! echo "$READER_OBS" | grep -wq "$req"; then
+ as_fn_error $? "\"$req is required to build GDB but it was not requested in: $READER_OBS\"" "$LINENO" 5
+ fi
+ done
+fi
+
+
+
# AMD debugger API support.
@@ -187,6 +187,16 @@ AS_HELP_STRING([--enable-targets=TARGETS], [alternative target configurations]),
*) enable_targets=$enableval ;;
esac])
+all_readers=
+AC_ARG_ENABLE(readers,
+AS_HELP_STRING([--enable-readers=DEBUG_READERS], [enable the chosen debug information readers (default 'all')]),
+[case "${enableval}" in
+ yes | "") AC_MSG_ERROR(enable-readers option must specify debuginfo readers or 'all')
+ ;;
+ no) enable_readers= ;;
+ *) enable_readers=$enableval ;;
+esac], [all_readers=true])
+
BFD_64_BIT
# Provide defaults for some variables set by the per-host and per-target
@@ -256,6 +266,33 @@ if test x${all_targets} = xtrue; then
fi
fi
+READER_OBS=
+
+for reader in `echo $enable_readers | sed 's/,/ /g'`
+do
+ if test "$reader" = "all"; then
+ all_readers=true
+ fi
+
+ . ${srcdir}/configure.reader
+done
+
+if test "$all_readers" = "true"; then
+ READER_OBS='$(ALL_READER_OBS)'
+else
+ # These are objfiles for debuginfo readers we hope to be able to disable
+ # at compile time some day, but we can't yet because of assumptions in the
+ # codebase.
+ required_readers="coffread.o coff-pe-read.o ctfread.o dbxread.o dwarf2/read.o mdebugread.o mipsread.o stabsread.o"
+ for req in $required_readers; do
+ if ! echo "$READER_OBS" | grep -wq "$req"; then
+ AC_MSG_ERROR("$req is required to build GDB but it was not requested in: $READER_OBS")
+ fi
+ done
+fi
+
+AC_SUBST(READER_OBS)
+
# AMD debugger API support.
AC_ARG_WITH([amd-dbgapi],
new file mode 100644
@@ -0,0 +1,51 @@
+# Copyright (C) 2024 Free Software Foundation, Inc.
+#
+# This file is part of GDB.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is used to decide which files need to be compiled to support
+# a given reader
+
+case $reader in
+ coff-pe) READER_OBS="$READER_OBS coff-pe-read.o";;
+
+ xcoff) READER_OBS="$READER_OBS xcoffread.o" ;;
+
+ coff) READER_OBS="$READER_OBS coffread.o" ;;
+
+ ctf) READER_OBS="$READER_OBS ctfread.o" ;;
+
+ dbx) READER_OBS="$READER_OBS dbxread.o" ;;
+
+ dwarf) READER_OBS="$READER_OBS dwarf2/abbrev.o dwarf2/abbrev-cache.o \
+ dwarf2/ada-imported.o dwarf2/aranges.o \
+ dwarf2/attribute.o dwarf2/comp-unit-head.o \
+ dwarf2/cooked-index.o dwarf2/cu.o dwarf2/die.o \
+ dwarf2/dwz.o dwarf2/expr.o dwarf2/frame.o \
+ dwarf2/frame-tailcall.o dwarf2/index-cache.o \
+ dwarf2/index-common.o dwarf2/index-write.o \
+ dwarf2/leb.o dwarf2/line-header.o dwarf2/loc.o \
+ dwarf2/macro.o dwarf2/read.o dwarf2/section.o \
+ dwarf2/read-debug-names.o dwarf2/read-gdb-index.o \
+ dwarf2/stringify.o" ;;
+
+ mdebug) READER_OBS="$READER_OBS mdebugread.o" ;;
+
+ mips) READER_OBS="$READER_OBS mipsread.o" ;;
+
+ stabs) READER_OBS="$READER_OBS stabsread.o" ;;
+
+ all) ;;
+esac