diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2012-04-17 15:54:35 +0000 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2012-04-17 15:54:35 +0000 |
commit | bccbefd2aab863e24a122ea686cbd263041b4709 (patch) | |
tree | 10470bdc16fff1f1e020d6c8e58913e84ab39575 /gdb/auto-load.c | |
parent | bf88dd68493db2b646b42165e6258573d3a597b5 (diff) | |
download | gdb-bccbefd2aab863e24a122ea686cbd263041b4709.zip gdb-bccbefd2aab863e24a122ea686cbd263041b4709.tar.gz gdb-bccbefd2aab863e24a122ea686cbd263041b4709.tar.bz2 |
gdb/
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.
Diffstat (limited to 'gdb/auto-load.c')
-rw-r--r-- | gdb/auto-load.c | 228 |
1 files changed, 223 insertions, 5 deletions
diff --git a/gdb/auto-load.c b/gdb/auto-load.c index c10d45a..076e50b 100644 --- a/gdb/auto-load.c +++ b/gdb/auto-load.c @@ -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); } |