New option "set auto-load safe-path".
	* NEWS: New commands "set auto-load safe-path"
	and "show auto-load safe-path".
	* auto-load.c: Include gdb_vecs.h, readline/tilde.h and completer.h.
	(auto_load_safe_path, auto_load_safe_path_vec)
	(auto_load_safe_path_vec_update, set_auto_load_safe_path)
	(show_auto_load_safe_path, add_auto_load_safe_path, filename_is_in_dir)
	(filename_is_in_auto_load_safe_path_vec, file_is_auto_load_safe): New.
	(source_gdb_script_for_objfile): New variable is_safe.  Call
	file_is_auto_load_safe.  Return if it is not.
	(struct loaded_script): New field loaded.
	(maybe_add_script): Add parameter loaded.  Initialize SLOT with it.
	(print_script): Use LOADED indicator instead of FULL_PATH.  Change
	output "Missing" to "No".
	(_initialize_auto_load): New variable cmd.  Initialize
	auto_load_safe_path.  Register "set auto-load safe-path",
	"show auto-load safe-path" and "add-auto-load-safe-path".
	* auto-load.h (maybe_add_script): Add parameter loaded.
	(file_is_auto_load_safe): New declaration.
	* config.in: Regenerate.
	* configure: Regenerate.
	* configure.ac: New parameters --with-auto-load-safe-path
	and --without-auto-load-safe-path.
	* linux-thread-db.c (try_thread_db_load_from_pdir_1)
	(try_thread_db_load_from_dir): Check file_is_auto_load_safe first.
	* main.c (captured_main): Check file_is_auto_load_safe for
	LOCAL_GDBINIT.
	* python/py-auto-load.c (gdbpy_load_auto_script_for_objfile): New
	variable is_safe.  Call file_is_auto_load_safe.  Return if it is not.
	(source_section_scripts): Call file_is_auto_load_safe.  Return if it is
	not.

gdb/doc/
	New option "set auto-load safe-path".
	* gdb.texinfo (Auto-loading): Extend the "show auto-load"
	and "info auto-load" examples for safe-path.  Put there also references
	for "set auto-load safe-path" and "show auto-load safe-path".
	New menu item for Auto-loading safe path.
	(Auto-loading safe path): New node.
	(Python Auto-loading): Update the expected output from "Missing"
	to "No".

gdb/testsuite/
	New option "set auto-load safe-path".
	* gdb.python/py-objfile-script.exp (set auto-load safe-path): New.
	* gdb.python/py-section-script.exp (set auto-load safe-path): New.
This commit is contained in:
Jan Kratochvil
2012-04-17 15:54:35 +00:00
parent bf88dd6849
commit bccbefd2aa
15 changed files with 465 additions and 16 deletions

View File

@@ -32,6 +32,9 @@
#include "gdbcmd.h"
#include "cli/cli-decode.h"
#include "cli/cli-setshow.h"
#include "gdb_vecs.h"
#include "readline/tilde.h"
#include "completer.h"
/* The suffix of per-objfile scripts to auto-load as non-Python command files.
E.g. When the program loads libfoo.so, look for libfoo-gdb.gdb. */
@@ -90,6 +93,181 @@ show_auto_load_local_gdbinit (struct ui_file *file, int from_tty,
value);
}
/* Directory list safe to hold auto-loaded files. It is not checked for
absolute paths but they are strongly recommended. It is initialized by
_initialize_auto_load. */
static char *auto_load_safe_path;
/* Vector of directory elements of AUTO_LOAD_SAFE_PATH with each one normalized
by tilde_expand and possibly each entries has added its gdb_realpath
counterpart. */
static VEC (char_ptr) *auto_load_safe_path_vec;
/* Update auto_load_safe_path_vec from current AUTO_LOAD_SAFE_PATH. */
static void
auto_load_safe_path_vec_update (void)
{
VEC (char_ptr) *dir_vec = NULL;
unsigned len;
int ix;
free_char_ptr_vec (auto_load_safe_path_vec);
auto_load_safe_path_vec = dirnames_to_char_ptr_vec (auto_load_safe_path);
len = VEC_length (char_ptr, auto_load_safe_path_vec);
/* Apply tilde_expand and gdb_realpath to each AUTO_LOAD_SAFE_PATH_VEC
element. */
for (ix = 0; ix < len; ix++)
{
char *dir = VEC_index (char_ptr, auto_load_safe_path_vec, ix);
char *expanded = tilde_expand (dir);
char *real_path = gdb_realpath (expanded);
/* Ensure the current entry is at least tilde_expand-ed. */
xfree (dir);
VEC_replace (char_ptr, auto_load_safe_path_vec, ix, expanded);
/* If gdb_realpath returns a different content, append it. */
if (strcmp (real_path, expanded) == 0)
xfree (real_path);
else
VEC_safe_push (char_ptr, auto_load_safe_path_vec, real_path);
}
}
/* "set" command for the auto_load_safe_path configuration variable. */
static void
set_auto_load_safe_path (char *args, int from_tty, struct cmd_list_element *c)
{
auto_load_safe_path_vec_update ();
}
/* "show" command for the auto_load_safe_path configuration variable. */
static void
show_auto_load_safe_path (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
if (*value == 0)
fprintf_filtered (file, _("Auto-load files are safe to load from any "
"directory.\n"));
else
fprintf_filtered (file, _("List of directories from which it is safe to "
"auto-load files is %s.\n"),
value);
}
/* "add-auto-load-safe-path" command for the auto_load_safe_path configuration
variable. */
static void
add_auto_load_safe_path (char *args, int from_tty)
{
char *s;
if (args == NULL || *args == 0)
error (_("\
Adding empty directory element disables the auto-load safe-path security. \
Use 'set auto-load safe-path' instead if you mean that."));
s = xstrprintf ("%s%c%s", auto_load_safe_path, DIRNAME_SEPARATOR, args);
xfree (auto_load_safe_path);
auto_load_safe_path = s;
auto_load_safe_path_vec_update ();
}
/* Return 1 if FILENAME is equal to DIR or if FILENAME belongs to the
subdirectory DIR. Return 0 otherwise. gdb_realpath normalization is never
done here. */
static ATTRIBUTE_PURE int
filename_is_in_dir (const char *filename, const char *dir)
{
size_t dir_len = strlen (dir);
while (dir_len && IS_DIR_SEPARATOR (dir[dir_len - 1]))
dir_len--;
return (filename_ncmp (dir, filename, dir_len) == 0
&& (IS_DIR_SEPARATOR (filename[dir_len])
|| filename[dir_len] == '\0'));
}
/* Return 1 if FILENAME belongs to one of directory components of
AUTO_LOAD_SAFE_PATH_VEC. Return 0 otherwise.
auto_load_safe_path_vec_update is never called.
*FILENAME_REALP may be updated by gdb_realpath of FILENAME - it has to be
freed by the caller. */
static int
filename_is_in_auto_load_safe_path_vec (const char *filename,
char **filename_realp)
{
char *dir;
int ix;
for (ix = 0; VEC_iterate (char_ptr, auto_load_safe_path_vec, ix, dir); ++ix)
if (*filename_realp == NULL && filename_is_in_dir (filename, dir))
break;
if (dir == NULL)
{
if (*filename_realp == NULL)
*filename_realp = gdb_realpath (filename);
for (ix = 0; VEC_iterate (char_ptr, auto_load_safe_path_vec, ix, dir);
++ix)
if (filename_is_in_dir (*filename_realp, dir))
break;
}
if (dir != NULL)
return 1;
return 0;
}
/* Return 1 if FILENAME is located in one of the directories of
AUTO_LOAD_SAFE_PATH. Otherwise call warning and return 0. FILENAME does
not have to be an absolute path.
Existence of FILENAME is not checked. Function will still give a warning
even if the caller would quietly skip non-existing file in unsafe
directory. */
int
file_is_auto_load_safe (const char *filename)
{
char *filename_real = NULL;
struct cleanup *back_to;
back_to = make_cleanup (free_current_contents, &filename_real);
if (filename_is_in_auto_load_safe_path_vec (filename, &filename_real))
{
do_cleanups (back_to);
return 1;
}
auto_load_safe_path_vec_update ();
if (filename_is_in_auto_load_safe_path_vec (filename, &filename_real))
{
do_cleanups (back_to);
return 1;
}
warning (_("File \"%s\" auto-loading has been declined by your "
"`auto-load safe-path' set to \"%s\"."),
filename_real, auto_load_safe_path);
do_cleanups (back_to);
return 0;
}
/* Definition of script language for GDB canned sequences of commands. */
static const struct script_language script_language_gdb
@@ -99,13 +277,20 @@ static void
source_gdb_script_for_objfile (struct objfile *objfile, FILE *file,
const char *filename)
{
int is_safe;
struct auto_load_pspace_info *pspace_info;
volatile struct gdb_exception e;
is_safe = file_is_auto_load_safe (filename);
/* Add this script to the hash table too so "info auto-load gdb-scripts"
can print it. */
pspace_info = get_auto_load_pspace_data_for_loading (current_program_space);
maybe_add_script (pspace_info, filename, filename, &script_language_gdb);
maybe_add_script (pspace_info, is_safe, filename, filename,
&script_language_gdb);
if (!is_safe)
return;
TRY_CATCH (e, RETURN_MASK_ALL)
{
@@ -140,6 +325,9 @@ struct loaded_script
inaccessible). */
const char *full_path;
/* Non-zero if this script has been loaded. */
int loaded;
const struct script_language *language;
};
@@ -232,12 +420,13 @@ get_auto_load_pspace_data_for_loading (struct program_space *pspace)
return info;
}
/* Add script NAME in LANGUAGE to hash table of PSPACE_INFO.
FULL_PATH is NULL if the script wasn't found. The result is
/* Add script NAME in LANGUAGE to hash table of PSPACE_INFO. LOADED 1 if the
script has been (is going to) be loaded, 0 otherwise (such as if it has not
been found). FULL_PATH is NULL if the script wasn't found. The result is
true if the script was already in the hash table. */
int
maybe_add_script (struct auto_load_pspace_info *pspace_info,
maybe_add_script (struct auto_load_pspace_info *pspace_info, int loaded,
const char *name, const char *full_path,
const struct script_language *language)
{
@@ -271,6 +460,7 @@ maybe_add_script (struct auto_load_pspace_info *pspace_info,
}
else
(*slot)->full_path = NULL;
(*slot)->loaded = loaded;
(*slot)->language = language;
}
@@ -432,7 +622,7 @@ print_script (struct loaded_script *script)
chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
ui_out_field_string (uiout, "loaded", script->full_path ? "Yes" : "Missing");
ui_out_field_string (uiout, "loaded", script->loaded ? "Yes" : "No");
ui_out_field_string (uiout, "script", script->name);
ui_out_text (uiout, "\n");
@@ -718,6 +908,8 @@ void _initialize_auto_load (void);
void
_initialize_auto_load (void)
{
struct cmd_list_element *cmd;
auto_load_pspace_data
= register_program_space_data_with_cleanup (auto_load_pspace_data_cleanup);
@@ -757,4 +949,30 @@ This options has security implications for untrusted inferiors."),
_("Print whether current directory .gdbinit file has been loaded.\n\
Usage: info auto-load local-gdbinit"),
auto_load_info_cmdlist_get ());
auto_load_safe_path = xstrdup (DEFAULT_AUTO_LOAD_SAFE_PATH);
auto_load_safe_path_vec_update ();
add_setshow_optional_filename_cmd ("safe-path", class_support,
&auto_load_safe_path, _("\
Set the list of directories from which it is safe to auto-load files."), _("\
Show the list of directories from which it is safe to auto-load files."), _("\
Various files loaded automatically for the 'set auto-load ...' options must\n\
be located in one of the directories listed by this option. Warning will be\n\
printed and file will not be used otherwise. Use empty string (or even\n\
empty directory entry) to allow any file for the 'set auto-load ...' options.\n\
This option is ignored for the kinds of files having 'set auto-load ... off'.\n\
This options has security implications for untrusted inferiors."),
set_auto_load_safe_path,
show_auto_load_safe_path,
auto_load_set_cmdlist_get (),
auto_load_show_cmdlist_get ());
cmd = add_cmd ("add-auto-load-safe-path", class_support,
add_auto_load_safe_path,
_("Add entries to the list of directories from which it is safe "
"to auto-load files.\n\
See the commands 'set auto-load safe-path' and 'show auto-load safe-path' to\n\
access the current full list setting."),
&cmdlist);
set_cmd_completer (cmd, filename_completer);
}