From 6b1b734ffae65a195b92d81e4f94fb62b4db1abd Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Sun, 26 Oct 2014 08:33:08 -0600 Subject: [PATCH] Add a flag argument to sudo_conf_read() so we can decide which bits get parsed. This lets us parse Debug statements first and init the debug subsystem early. --- include/sudo_conf.h | 15 +++- lib/util/regress/sudo_conf/conf_test.c | 2 +- lib/util/sudo_conf.c | 109 ++++++++++++------------- lib/util/util.exp.in | 1 + plugins/sudoers/sudoers_debug.c | 12 +-- plugins/sudoers/sudoreplay.c | 9 +- plugins/sudoers/testsudoers.c | 8 +- plugins/sudoers/visudo.c | 8 +- src/load_plugins.c | 8 +- src/sudo.c | 31 ++++--- src/sudo_plugin_int.h | 2 +- 11 files changed, 102 insertions(+), 103 deletions(-) diff --git a/include/sudo_conf.h b/include/sudo_conf.h index ed7267164..d9236deef 100644 --- a/include/sudo_conf.h +++ b/include/sudo_conf.h @@ -19,6 +19,14 @@ #include "sudo_queue.h" +/* Flags for sudo_conf_read() */ +#define SUDO_CONF_DEBUG 0x01 +#define SUDO_CONF_PATHS 0x02 +#define SUDO_CONF_PLUGINS 0x04 +#define SUDO_CONF_SETTINGS 0x08 +#define SUDO_CONF_ALL 0x0f + +/* Values of sudo_conf_group_source() */ #define GROUP_SOURCE_ADAPTIVE 0 #define GROUP_SOURCE_STATIC 1 #define GROUP_SOURCE_DYNAMIC 2 @@ -28,7 +36,6 @@ TAILQ_HEAD(sudo_conf_debug_file_list, sudo_debug_file); struct plugin_info { TAILQ_ENTRY(plugin_info) entries; - struct sudo_conf_debug_file_list debug_files; const char *path; const char *symbol_name; char * const * options; @@ -44,8 +51,8 @@ struct sudo_conf_debug { TAILQ_HEAD(sudo_conf_debug_list, sudo_conf_debug); /* Read main sudo.conf file. */ -__dso_public void sudo_conf_read_v1(const char *conf_file); -#define sudo_conf_read(_a) sudo_conf_read_v1((_a)) +__dso_public void sudo_conf_read_v1(const char *conf_file, int conf_types); +#define sudo_conf_read(_a, _b) sudo_conf_read_v1((_a), (_b)) /* Accessor functions. */ __dso_public const char *sudo_conf_askpass_path_v1(void); @@ -53,6 +60,7 @@ __dso_public const char *sudo_conf_sesh_path_v1(void); __dso_public const char *sudo_conf_noexec_path_v1(void); __dso_public const char *sudo_conf_plugin_dir_path_v1(void); __dso_public struct sudo_conf_debug_list *sudo_conf_debugging_v1(void); +__dso_public struct sudo_conf_debug_file_list *sudo_conf_debug_files_v1(const char *progname); __dso_public struct plugin_info_list *sudo_conf_plugins_v1(void); __dso_public bool sudo_conf_disable_coredump_v1(void); __dso_public bool sudo_conf_probe_interfaces_v1(void); @@ -63,6 +71,7 @@ __dso_public int sudo_conf_max_groups_v1(void); #define sudo_conf_noexec_path() sudo_conf_noexec_path_v1() #define sudo_conf_plugin_dir_path() sudo_conf_plugin_dir_path_v1() #define sudo_conf_debugging() sudo_conf_debugging_v1() +#define sudo_conf_debug_files(_a) sudo_conf_debug_files_v1((_a)) #define sudo_conf_plugins() sudo_conf_plugins_v1() #define sudo_conf_disable_coredump() sudo_conf_disable_coredump_v1() #define sudo_conf_probe_interfaces() sudo_conf_probe_interfaces_v1() diff --git a/lib/util/regress/sudo_conf/conf_test.c b/lib/util/regress/sudo_conf/conf_test.c index c6062bf82..94cf5af77 100644 --- a/lib/util/regress/sudo_conf/conf_test.c +++ b/lib/util/regress/sudo_conf/conf_test.c @@ -63,7 +63,7 @@ main(int argc, char *argv[]) fprintf(stderr, "usage: %s conf_file\n", getprogname()); exit(1); } - sudo_conf_read(argv[1]); + sudo_conf_read(argv[1], SUDO_CONF_ALL); sudo_conf_dump(); exit(0); diff --git a/lib/util/sudo_conf.c b/lib/util/sudo_conf.c index b62fd4b34..99568ede0 100644 --- a/lib/util/sudo_conf.c +++ b/lib/util/sudo_conf.c @@ -323,58 +323,9 @@ store_plugin(const char *cp, unsigned int lineno) info->path = sudo_estrndup(path, pathlen); info->options = options; info->lineno = lineno; - TAILQ_INIT(&info->debug_files); TAILQ_INSERT_TAIL(&sudo_conf_data.plugins, info, entries); } -/* - * Initialize debugging subsystem for the running program. - * Also stores plugin-specific debug info in sudo_conf_data.plugins. - */ -static void -set_debugging(const char *conf_file) -{ - struct sudo_conf_debug *debug_spec; - struct plugin_info *plugin_info; - const char *progname; - size_t prognamelen; - debug_decl(main, SUDO_DEBUG_UTIL, SUDO_DEBUG_INSTANCE_DEFAULT) - - progname = getprogname(); - prognamelen = strlen(progname); - if (prognamelen > 4 && strcmp(progname + 4, "edit") == 0) - prognamelen -= 4; - TAILQ_FOREACH(debug_spec, &sudo_conf_data.debugging, entries) { - if (strncmp(debug_spec->progname, progname, prognamelen) == 0 && - debug_spec->progname[prognamelen] == '\0') { - /* - * Register debug instance for the main program, making it - * the default instance if one is not already set. - */ - sudo_debug_register(progname, NULL, NULL, &debug_spec->debug_files); - sudo_debug_enter(__func__, __FILE__, __LINE__, sudo_debug_subsys); - continue; - } - /* Move debug_files to plugin if it matches. */ - TAILQ_FOREACH(plugin_info, &sudo_conf_data.plugins, entries) { - const char *plugin_name = plugin_info->path; - if (debug_spec->progname[0] != '/') { - /* Match basename(path). */ - plugin_name = strrchr(plugin_info->path, '/'); - if (plugin_name++ == NULL) - plugin_name = plugin_info->path; - } - if (strcmp(debug_spec->progname, plugin_name) == 0) { - /* Move debug_files into plugin_info. */ - TAILQ_SWAP(&plugin_info->debug_files, &debug_spec->debug_files, - sudo_debug_file, entries); - break; - } - } - /* XXX - free up remaining structs */ - } -} - /* * Update path settings. */ @@ -558,6 +509,42 @@ sudo_conf_debugging_v1(void) return &sudo_conf_data.debugging; } +/* Return the debug files list for a program, or NULL if none. */ +struct sudo_conf_debug_file_list * +sudo_conf_debug_files_v1(const char *progname) +{ + struct sudo_conf_debug *debug_spec; + size_t prognamelen, progbaselen; + const char *progbase = progname; + debug_decl(sudo_conf_debug_files, SUDO_DEBUG_UTIL, SUDO_DEBUG_INSTANCE_DEFAULT) + + /* Determine basename if program is fully qualified (like for plugins). */ + prognamelen = progbaselen = strlen(progname); + if (*progname == '/') { + progbase = strrchr(progname, '/'); + progbaselen = strlen(++progbase); + } + /* Convert sudoedit -> sudo. */ + if (progbaselen > 4 && strcmp(progbase + 4, "edit") == 0) { + progbaselen -= 4; + } + TAILQ_FOREACH(debug_spec, &sudo_conf_data.debugging, entries) { + const char *prog = progbase; + size_t len = progbaselen; + + if (debug_spec->progname[0] == '/') { + /* Match fully-qualified name, if possible. */ + prog = progname; + len = prognamelen; + } + if (strncmp(debug_spec->progname, prog, len) == 0 && + debug_spec->progname[len] == '\0') { + debug_return_ptr(&debug_spec->debug_files); + } + } + debug_return_ptr(NULL); +} + bool sudo_conf_disable_coredump_v1(void) { @@ -574,12 +561,11 @@ sudo_conf_probe_interfaces_v1(void) * Reads in /etc/sudo.conf and populates sudo_conf_data. */ void -sudo_conf_read_v1(const char *conf_file) +sudo_conf_read_v1(const char *conf_file, int conf_types) { - struct sudo_conf_table *cur; struct stat sb; FILE *fp; - char *cp, *line = NULL; + char *line = NULL; char *prev_locale = sudo_estrdup(setlocale(LC_ALL, NULL)); unsigned int conf_lineno = 0; size_t linesize = 0; @@ -624,10 +610,16 @@ sudo_conf_read_v1(const char *conf_file) } while (sudo_parseln(&line, &linesize, &conf_lineno, fp) != -1) { + struct sudo_conf_table *cur; + unsigned int i; + char *cp; + if (*(cp = line) == '\0') continue; /* empty line or comment */ - for (cur = sudo_conf_table; cur->name != NULL; cur++) { + for (i = 0, cur = sudo_conf_table; cur->name != NULL; i++, cur++) { + if (!ISSET(conf_types, (1 << i))) + continue; if (strncasecmp(cp, cur->name, cur->namelen) == 0 && isblank((unsigned char)cp[cur->namelen])) { cp += cur->namelen; @@ -641,12 +633,11 @@ sudo_conf_read_v1(const char *conf_file) fclose(fp); free(line); - /* First, init the debug system. */ - set_debugging(conf_file); - - /* Then set paths and variables. */ - set_paths(conf_file); - set_variables(conf_file); + /* Parse paths and variables as needed. */ + if (ISSET(conf_types, SUDO_CONF_PATHS)) + set_paths(conf_file); + if (ISSET(conf_types, SUDO_CONF_SETTINGS)) + set_variables(conf_file); done: /* Restore locale if needed. */ diff --git a/lib/util/util.exp.in b/lib/util/util.exp.in index f4fed73e6..83b86c1d7 100644 --- a/lib/util/util.exp.in +++ b/lib/util/util.exp.in @@ -1,5 +1,6 @@ @COMPAT_EXP@initprogname sudo_conf_askpass_path_v1 +sudo_conf_debug_files_v1 sudo_conf_debugging_v1 sudo_conf_disable_coredump_v1 sudo_conf_group_source_v1 diff --git a/plugins/sudoers/sudoers_debug.c b/plugins/sudoers/sudoers_debug.c index 6ad3f611a..6734a5875 100644 --- a/plugins/sudoers/sudoers_debug.c +++ b/plugins/sudoers/sudoers_debug.c @@ -106,19 +106,19 @@ sudoers_debug_parse_flags(struct sudo_conf_debug_file_list *debug_files, } /* - * Register the specified debug files and plugin_path with the - * debug subsystem. + * Register the specified debug files and program with the + * debug subsystem, freeing the debug list when done. */ void sudoers_debug_register(struct sudo_conf_debug_file_list *debug_files, - const char *plugin_path) + const char *program) { struct sudo_debug_file *debug_file, *debug_next; /* Setup debugging if indicated. */ - if (!TAILQ_EMPTY(debug_files)) { - if (plugin_path != NULL) { - sudoers_debug_instance = sudo_debug_register(plugin_path, + if (debug_files != NULL && !TAILQ_EMPTY(debug_files)) { + if (program != NULL) { + sudoers_debug_instance = sudo_debug_register(program, sudoers_subsystem_names, sudoers_subsystem_ids, debug_files); } TAILQ_FOREACH_SAFE(debug_file, debug_files, entries, debug_next) { diff --git a/plugins/sudoers/sudoreplay.c b/plugins/sudoers/sudoreplay.c index f54726574..2185437bf 100644 --- a/plugins/sudoers/sudoreplay.c +++ b/plugins/sudoers/sudoreplay.c @@ -256,11 +256,10 @@ main(int argc, char *argv[]) /* Register fatal/fatalx callback. */ sudo_fatal_callback_register(sudoreplay_cleanup); - /* Read sudo.conf. */ - sudo_conf_read(NULL); - - /* Set debug instance to use (if configured). */ - sudoreplay_debug_instance = sudo_debug_get_instance(getprogname()); + /* Read sudo.conf and initialize the debug subsystem. */ + sudo_conf_read(NULL, SUDO_CONF_DEBUG); + sudoreplay_debug_instance = sudo_debug_register(getprogname(), + NULL, NULL, sudo_conf_debug_files(getprogname())); while ((ch = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { switch (ch) { diff --git a/plugins/sudoers/testsudoers.c b/plugins/sudoers/testsudoers.c index 1f08ad10f..10ab05afa 100644 --- a/plugins/sudoers/testsudoers.c +++ b/plugins/sudoers/testsudoers.c @@ -138,11 +138,9 @@ main(int argc, char *argv[]) bindtextdomain("sudoers", LOCALEDIR); /* XXX - should have own domain */ textdomain("sudoers"); - /* Read sudo.conf. */ - sudo_conf_read(NULL); - - /* Set debug instance to use (if configured). */ - sudoers_debug_instance = sudo_debug_get_instance(getprogname()); + /* Initialize the debug subsystem. */ + sudo_conf_read(NULL, SUDO_CONF_DEBUG); + sudoers_debug_register(sudo_conf_debug_files(getprogname()), getprogname()); dflag = 0; grfile = pwfile = NULL; diff --git a/plugins/sudoers/visudo.c b/plugins/sudoers/visudo.c index 44bfd7ef8..7e44be610 100644 --- a/plugins/sudoers/visudo.c +++ b/plugins/sudoers/visudo.c @@ -169,11 +169,9 @@ main(int argc, char *argv[]) /* Register fatal/fatalx callback. */ sudo_fatal_callback_register(visudo_cleanup); - /* Read sudo.conf. */ - sudo_conf_read(NULL); - - /* Set debug instance to use (if configured). */ - sudoers_debug_instance = sudo_debug_get_instance(getprogname()); + /* Initialize the debug subsystem. */ + sudo_conf_read(NULL, SUDO_CONF_DEBUG); + sudoers_debug_register(sudo_conf_debug_files(getprogname()), getprogname()); /* * Arg handling. diff --git a/src/load_plugins.c b/src/load_plugins.c index d7185cd9f..e63e08a58 100644 --- a/src/load_plugins.c +++ b/src/load_plugins.c @@ -240,9 +240,7 @@ sudo_load_plugin(struct plugin_container *policy_plugin, policy_plugin->options = info->options; policy_plugin->debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER; policy_plugin->u.generic = plugin; - TAILQ_INIT(&policy_plugin->debug_files); - TAILQ_SWAP(&policy_plugin->debug_files, &info->debug_files, - sudo_debug_file, entries); + policy_plugin->debug_files = sudo_conf_debug_files(path); } } else if (plugin->type == SUDO_IO_PLUGIN) { /* Check for duplicate entries. */ @@ -263,9 +261,7 @@ sudo_load_plugin(struct plugin_container *policy_plugin, container->options = info->options; container->debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER; container->u.generic = plugin; - TAILQ_INIT(&container->debug_files); - TAILQ_SWAP(&container->debug_files, &info->debug_files, - sudo_debug_file, entries); + policy_plugin->debug_files = sudo_conf_debug_files(path); TAILQ_INSERT_TAIL(io_plugins, container, entries); } } diff --git a/src/sudo.c b/src/sudo.c index 08ec40189..d621875c5 100644 --- a/src/sudo.c +++ b/src/sudo.c @@ -154,6 +154,8 @@ main(int argc, char *argv[], char *envp[]) sigset_t mask; debug_decl(main, SUDO_DEBUG_MAIN, sudo_debug_instance) + /* Make sure fds 0-2 are open and do OS-specific initialization. */ + fix_fds(); os_init(argc, argv, envp); setlocale(LC_ALL, ""); @@ -175,6 +177,11 @@ main(int argc, char *argv[], char *envp[]) /* Use conversation function for sudo_(warn|fatal)x?. */ sudo_warn_set_conversation(sudo_conversation); + /* Initialize the debug subsystem. */ + sudo_conf_read(NULL, SUDO_CONF_DEBUG); + sudo_debug_instance = sudo_debug_register(getprogname(), + NULL, NULL, sudo_conf_debug_files(getprogname())); + /* Make sure we are setuid root. */ sudo_check_suid(argv[0]); @@ -182,13 +189,9 @@ main(int argc, char *argv[], char *envp[]) (void) sigemptyset(&mask); (void) sigprocmask(SIG_SETMASK, &mask, NULL); save_signals(); - fix_fds(); - - /* Read sudo.conf. */ - sudo_conf_read(NULL); - /* Set debug instance to use with sudo front end (if configured). */ - sudo_debug_instance = sudo_debug_get_instance(getprogname()); + /* Parse the rest of sudo.conf. */ + sudo_conf_read(NULL, SUDO_CONF_ALL & ~SUDO_CONF_DEBUG); /* Fill in user_info with user name, uid, cwd, etc. */ memset(&user_details, 0, sizeof(user_details)); @@ -1101,8 +1104,10 @@ format_plugin_settings(struct plugin_container *plugin, plugin_settings_size = 2; for (setting = sudo_settings; setting->name != NULL; setting++) plugin_settings_size++; - TAILQ_FOREACH(debug_file, &plugin->debug_files, entries) - plugin_settings_size++; + if (plugin->debug_files != NULL) { + TAILQ_FOREACH(debug_file, plugin->debug_files, entries) + plugin_settings_size++; + } /* Allocate and fill in. */ plugin_settings = sudo_emallocarray(plugin_settings_size, sizeof(char *)); @@ -1119,10 +1124,12 @@ format_plugin_settings(struct plugin_container *plugin, num_plugin_settings++; } } - TAILQ_FOREACH(debug_file, &plugin->debug_files, entries) { - /* XXX - quote filename? */ - sudo_easprintf(&plugin_settings[num_plugin_settings++], - "debug_flags=%s %s", debug_file->debug_file, debug_file->debug_flags); + if (plugin->debug_files != NULL) { + TAILQ_FOREACH(debug_file, plugin->debug_files, entries) { + /* XXX - quote filename? */ + sudo_easprintf(&plugin_settings[num_plugin_settings++], + "debug_flags=%s %s", debug_file->debug_file, debug_file->debug_flags); + } } plugin_settings[num_plugin_settings] = NULL; diff --git a/src/sudo_plugin_int.h b/src/sudo_plugin_int.h index 9999ddfe5..1cbd67383 100644 --- a/src/sudo_plugin_int.h +++ b/src/sudo_plugin_int.h @@ -82,7 +82,7 @@ struct io_plugin_1_1 { */ struct plugin_container { TAILQ_ENTRY(plugin_container) entries; - struct sudo_conf_debug_file_list debug_files; + struct sudo_conf_debug_file_list *debug_files; const char *name; const char *path; char * const *options; -- 2.50.1