[patch] New set auto-load-local-gdbinit + disable it by default

Jan Kratochvil
2012-01-17T09:56:45Z

Hi,

this is a patch I want to post for many years. There was:
[RFA] .gdbinit security (revived) [incl doc]
http://sourceware.org/ml/gdb-patches/2010-11/msg00276.html
which was a follow-up for its referenced:
RFC: Check permissions of .gdbinit files
http://sourceware.org/ml/gdb-patches/2005-05/msg00637.html
which was addressing:
http://cve.mitre.org/cgi-bin/cvename.cgi?name=2005-1705
Current Fedora patch (AFAIK in some way contained in many other distros):
http://pkgs.fedoraproject.org/gitweb/?p=gdb.git;a=blob;f=gdb-6.3-security-errata-20050610.patch;hb=master

There is always discussion whether != UID and/or != GID is secure enough vs.
convenient enough.

But from my experience any UID or GID policies just cannot work:
Save Bugzilla bugreport attachment crash.tar.gz as a regular user.
$ tar xzf crash.tar.gz; cd crash
$ gdb crashprog
- You are 0wn3d!

Besides security problems the automatic execution is even inconvenient:
$ gdb testsuite/gdb.base/return
[...]
Setting up the environment for debugging gdb.
Function "internal_error" not defined.
Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
Function "info_command" not defined.
Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
.gdbinit:8: Error in sourced command file:
Argument required (one or more breakpoint numbers).
- What had happened? Oh, I forgot -nx again!

I even always run my `gdbn' as otherwise some random .gdbinit occasionally
gets executed and I get some unknown debugging environment I have to quit:
function gdbn { gdb -nx --command=~/.gdbinit "$@"; }

I do not see a precedent for executing anything from current directory by
default. . (current directory) is also not contained in $PATH at all.
bash also does not execute .bashrc in any current directory.
And "gdb -x ./.gdbinit" is a pretty simple way to do what one wants to do.

From what I know still there may be a resistance to this change, Eli please
save your work with doc reviewing only after the change has been approved.

Still at least the setting should go in and then one can then have
"set auto-load-local-gdbinit off" at least in ~/.gdbinit. Anyway I would
file a FESCo (Fedora Engineering Steering Committee) ticket for such "off" in
/etc/gdbinit at least in distro and IMHO it needs to get approved (but maybe
not, it would be another fork from upstream).

No regressions on {x86_64,x86_64-m32,i686}-fedorarawhide-linux-gnu.

I do not think a testcase makes sense but I may make one if requested.

Thanks,
Jan

gdb/
2012-01-17 Jan Kratochvil <jan.kratochvil@redhat.com>

New set auto-load-local-gdbinit + disable it by default.
* NEWS: New item.
* main.c (captured_main): Execute LOCAL_GDBINIT only if
AUTO_LOAD_LOCAL_GDBINIT_P.
(print_gdb_help): New note for LOCAL_GDBINIT.
* top.c (auto_load_local_gdbinit_p, show_auto_load_local_gdbinit_p):
New.
(init_main): Call add_setshow_boolean_cmd for "auto-load-local-gdbinit".
* top.h (auto_load_local_gdbinit_p): New declaration.

gdb/doc/
2012-01-17 Jan Kratochvil <jan.kratochvil@redhat.com>

* gdb.texinfo (Startup): Describe set auto-load-local-gdbinit and its
default off now.

--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -30,6 +30,9 @@
now set a breakpoint in build/gcc/expr.c, but not
build/libcpp/expr.c.

+* GDB no longer reads .gdbinit file from current directory by default.
+ Use "gdb -x .gdbinit" to retain the original behavior.
+
*** Changes in GDB 7.4

* GDB now handles ambiguous linespecs more consistently; the existing
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -1250,12 +1250,34 @@ that file.
Processes command line options and operands.

@item
-Reads and executes the commands from init file (if any) in the current
-working directory. This is only done if the current directory is
-different from your home directory. Thus, you can have more than one
-init file, one generic in your home directory, and another, specific
-to the program you are debugging, in the directory where you invoke
-@value{GDBN}.
+If you have explicitly set @samp{set auto-load-local-gdbinit on} then
+@value{GDBN} reads and executes the commands from init file (if any) in
+the current working directory. This is only done if the current
+directory is different from your home directory. Thus, you can have
+more than one init file, one generic in your home directory, and
+another, specific to the program you are debugging, in the directory
+where you invoke @value{GDBN}.
+
+Setting it to @samp{on} has security implications if you run
+@value{GDBN} from a directory with untrusted files, such as home
+directories of other users, shared temporary directories or extracted
+downloaded archives. Appropriate @samp{set auto-load-local-gdbinit}
+command can be also placed into the system-wide init file or into the
+init file in your home directory.
+
+@table @code
+@kindex set auto-load-local-gdbinit
+@item set auto-load-local-gdbinit [yes|no]
+Enable or disable the auto-loading of init file (if any) in the current
+working directory. The default is @samp{set auto-load-local-gdbinit
+off}---no file from current working directory is executed during
+startup.
+
+@kindex show auto-load-local-gdbinit
+@item show auto-load-local-gdbinit
+Show whether auto-loading of init file (if any) in the current working
+directory is enabled or disabled.
+@end table

@item
If the command line specified a program to debug, or a process to
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -898,7 +898,7 @@ captured_main (void *data)

/* Read the .gdbinit file in the current directory, *if* it isn't
the same as the $HOME/.gdbinit file (it should exist, also). */
- if (local_gdbinit && !inhibit_gdbinit)
+ if (local_gdbinit && !inhibit_gdbinit && auto_load_local_gdbinit_p)
catch_command_errors (source_script, local_gdbinit, 0, RETURN_MASK_ALL);

/* Now that all .gdbinit's have been read and all -d options have been
@@ -1042,7 +1042,7 @@ At startup, GDB reads the following init files and executes their commands:\n\
"), home_gdbinit);
if (local_gdbinit)
fprintf_unfiltered (stream, _("\
- * local init file: ./%s\n\
+ * local init file (if set auto-load-local-gdbinit is on): ./%s\n\
"), local_gdbinit);
fputs_unfiltered (_("\n\
For more information, type \"help\" from within GDB, or consult the\n\
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -1174,6 +1174,21 @@ set_prompt (const char *s)
xfree (top_prompt);
top_prompt = p;
}
+
+/* Set to non-zero to automatically load file ./.gdbinit during GDB
+ startup. */
+int auto_load_local_gdbinit_p = 0;
+
+/* Show the current state of AUTO_LOAD_LOCAL_GDBINIT_P. */
+
+static void
+show_auto_load_local_gdbinit_p (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("\
+Automatic loading of ./.gdbinit file during GDB startup is %s.\n"),
+ value);
+}
\f

struct qt_args
@@ -1666,6 +1681,16 @@ When set, GDB uses the specified path to search for data files."),
NULL, NULL,
&setlist,
&showlist);
+
+ add_setshow_boolean_cmd ("auto-load-local-gdbinit", class_support,
+ &auto_load_local_gdbinit_p, _("\
+Set to automatically load file ./.gdbinit during GDB startup."), _("\
+Show automatic load of file ./.gdbinit during GDB startup."), _("\
+Automatic loading may have security implications if you start GDB in\n\
+a directory with untrusted files."),
+ NULL,
+ show_auto_load_local_gdbinit_p,
+ &setlist, &showlist);
}

void
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -82,4 +82,6 @@ extern void set_verbose (char *, int, struct cmd_list_element *);

extern void do_restore_instream_cleanup (void *stream);

+extern int auto_load_local_gdbinit_p;
+
#endif