From 98ecef3256466e76ec8b0936ab1b7da3fa3a2c3f Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Fri, 16 Dec 2016 07:24:07 +0100 Subject: [PATCH] Handle system and home plugin paths MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Mathieu Desnoyers Signed-off-by: Jérémie Galarneau --- converter/Makefile.am | 3 +- converter/babeltrace-cfg.c | 136 ++++++++++++++++++++++++++++++------- converter/babeltrace.c | 46 +++++++++---- 3 files changed, 147 insertions(+), 38 deletions(-) diff --git a/converter/Makefile.am b/converter/Makefile.am index 262214f7..4be27f98 100644 --- a/converter/Makefile.am +++ b/converter/Makefile.am @@ -1,4 +1,5 @@ -AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include +AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include \ + -DINSTALL_LIBDIR=\"$(libdir)\" AM_LDFLAGS = -lpopt bin_PROGRAMS = babeltrace babeltrace-log diff --git a/converter/babeltrace-cfg.c b/converter/babeltrace-cfg.c index c9744475..d3072488 100644 --- a/converter/babeltrace-cfg.c +++ b/converter/babeltrace-cfg.c @@ -33,9 +33,14 @@ #include #include #include +#include +#include #include "babeltrace-cfg.h" +#define SYSTEM_PLUGIN_PATH INSTALL_LIBDIR "/babeltrace/plugins" #define DEFAULT_SOURCE_COMPONENT_NAME "ctf.fs" +#define HOME_ENV_VAR "HOME" +#define HOME_SUBPATH "/.babeltrace/plugins" /* * Error printf() macro which prepends "Error: " the first time it's @@ -142,6 +147,9 @@ enum legacy_output_format { LEGACY_OUTPUT_FORMAT_DUMMY, }; +static bool omit_system_plugin_path; +static bool omit_home_plugin_path; + /* * Prints the "out of memory" error. */ @@ -782,6 +790,8 @@ void print_usage(FILE *fp) fprintf(fp, " --begin Start time: [YYYY-MM-DD [hh:mm:]]ss[.nnnnnnnnn]\n"); fprintf(fp, " --end End time: [YYYY-MM-DD [hh:mm:]]ss[.nnnnnnnnn]\n"); fprintf(fp, " --timerange Time range: begin,end or [begin,end] (where [] are actual brackets)\n"); + fprintf(fp, " --omit-system-plugin-path Omit system plugins from plugin search path\n"); + fprintf(fp, " --omit-home-plugin-path Omit home plugins from plugin search path\n"); fprintf(fp, " -h --help Show this help\n"); fprintf(fp, " --help-legacy Show Babeltrace 1.x legacy options\n"); fprintf(fp, " -v, --verbose Enable verbose output\n"); @@ -956,6 +966,12 @@ end: return; } +static +bool is_setuid_setgid(void) +{ + return (geteuid() != getuid() || getegid() != getgid()); +} + /* * Extracts the various paths from the string arg, delimited by ':', * and converts them to an array value object. @@ -965,18 +981,12 @@ end: * Return value is owned by the caller. */ static -struct bt_value *plugin_paths_from_arg(const char *arg) +enum bt_value_status plugin_paths_from_arg(struct bt_value *plugin_paths, + const char *arg) { - struct bt_value *plugin_paths; const char *at = arg; const char *end = arg + strlen(arg); - plugin_paths = bt_value_array_create(); - if (!plugin_paths) { - print_err_oom(); - goto error; - } - while (at < end) { int ret; GString *path; @@ -1011,13 +1021,9 @@ struct bt_value *plugin_paths_from_arg(const char *arg) } } - goto end; - + return BT_VALUE_STATUS_OK; error: - BT_PUT(plugin_paths); - -end: - return plugin_paths; + return BT_VALUE_STATUS_ERROR; } /* @@ -2145,6 +2151,8 @@ enum { OPT_TIMERANGE, OPT_VERBOSE, OPT_VERSION, + OPT_OMIT_SYSTEM_PLUGIN_PATH, + OPT_OMIT_HOME_PLUGIN_PATH, }; /* popt long option descriptions */ @@ -2183,6 +2191,8 @@ static struct poptOption long_options[] = { { "timerange", '\0', POPT_ARG_STRING, NULL, OPT_TIMERANGE, NULL, NULL }, { "verbose", 'v', POPT_ARG_NONE, NULL, OPT_VERBOSE, NULL, NULL }, { "version", 'V', POPT_ARG_NONE, NULL, OPT_VERSION, NULL, NULL }, + { "omit-system-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_SYSTEM_PLUGIN_PATH, NULL, NULL }, + { "omit-home-plugin-path", '\0', POPT_ARG_NONE, NULL, OPT_OMIT_HOME_PLUGIN_PATH, NULL, NULL }, { NULL, 0, 0, NULL, 0, NULL, NULL }, }; @@ -2248,6 +2258,72 @@ not_found: return -1; } +static char *bt_secure_getenv(const char *name) +{ + if (is_setuid_setgid()) { + printf_err("Disregarding %s environment variable for setuid/setgid binary", name); + return NULL; + } + return getenv(name); +} + +static const char *get_home_dir(void) +{ + char *val = NULL; + struct passwd *pwd; + + val = bt_secure_getenv(HOME_ENV_VAR); + if (val) { + goto end; + } + /* Fallback on password file. */ + pwd = getpwuid(getuid()); + if (!pwd) { + goto end; + } + val = pwd->pw_dir; +end: + return val; +} + +static int add_internal_plugin_paths(struct bt_config *cfg) +{ + if (!omit_home_plugin_path) { + char path[PATH_MAX]; + const char *home_dir; + + if (is_setuid_setgid()) { + printf_debug("Skipping non-system plugin paths for setuid/setgid binary."); + } else { + home_dir = get_home_dir(); + if (home_dir) { + if (strlen(home_dir) + strlen(HOME_SUBPATH) + 1 + >= PATH_MAX) { + printf_err("Home directory path too long\n"); + goto error; + } + strcpy(path, home_dir); + strcat(path, HOME_SUBPATH); + if (plugin_paths_from_arg(cfg->plugin_paths, path)) { + printf_err("Invalid home plugin path\n"); + goto error; + } + } + } + } + + if (!omit_system_plugin_path) { + if (plugin_paths_from_arg(cfg->plugin_paths, + SYSTEM_PLUGIN_PATH)) { + printf_err("Invalid system plugin path\n"); + goto error; + } + } + return 0; +error: + return -1; +} + /* * Returns a Babeltrace configuration, out of command-line arguments, * containing everything that is needed to instanciate specific @@ -2348,6 +2424,12 @@ struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_co DEFAULT_SOURCE_COMPONENT_NAME); } + cfg->plugin_paths = bt_value_array_create(); + if (!cfg->plugin_paths) { + print_err_oom(); + goto error; + } + /* Parse options */ pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 0); if (!pc) { @@ -2362,17 +2444,21 @@ struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_co switch (opt) { case OPT_PLUGIN_PATH: - if (cfg->plugin_paths) { - printf_err("Duplicate --plugin-path option\n"); - goto error; - } - - cfg->plugin_paths = plugin_paths_from_arg(arg); - if (!cfg->plugin_paths) { - printf_err("Invalid --plugin-path option's argument\n"); - goto error; + if (is_setuid_setgid()) { + printf_debug("Skipping non-system plugin paths for setuid/setgid binary."); + } else { + if (plugin_paths_from_arg(cfg->plugin_paths, arg)) { + printf_err("Invalid --plugin-path option's argument\n"); + goto error; + } } break; + case OPT_OMIT_SYSTEM_PLUGIN_PATH: + omit_system_plugin_path = true; + break; + case OPT_OMIT_HOME_PLUGIN_PATH: + omit_home_plugin_path = true; + break; case OPT_OUTPUT_PATH: if (text_legacy_opts.output->len > 0) { printf_err("Duplicate --output option\n"); @@ -2753,6 +2839,10 @@ struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_co arg = NULL; } + if (add_internal_plugin_paths(cfg)) { + goto error; + } + /* Append current component configuration, if any */ if (cur_cfg_comp && !cur_is_implicit_source) { add_cfg_comp(cfg, cur_cfg_comp, cur_cfg_comp_dest); diff --git a/converter/babeltrace.c b/converter/babeltrace.c index 49f4cc2c..f969f8d7 100644 --- a/converter/babeltrace.c +++ b/converter/babeltrace.c @@ -369,6 +369,34 @@ end: return ret; } +static int load_plugins(struct bt_config *cfg) +{ + int nr_paths, i; + + nr_paths = bt_value_array_size(cfg->plugin_paths); + if (nr_paths < 0) { + return -1; + } + for (i = 0; i < nr_paths; i++) { + struct bt_value *plugin_path_value = NULL; + const char *plugin_path; + + plugin_path_value = bt_value_array_get(cfg->plugin_paths, i); + if (bt_value_string_get(plugin_path_value, + &plugin_path)) { + BT_PUT(plugin_path_value); + continue; + } + if (bt_component_factory_load_recursive(component_factory, + plugin_path)) { + printf_debug("Unable to dynamically load plugins from path %s.\n", + plugin_path); + } + BT_PUT(plugin_path_value); + } + return 0; +} + int main(int argc, const char **argv) { int ret; @@ -378,8 +406,6 @@ int main(int argc, const char **argv) struct bt_value *source_params = NULL, *sink_params = NULL; struct bt_config *cfg; enum bt_component_status sink_status; - struct bt_value *first_plugin_path_value = NULL; - const char *first_plugin_path; struct bt_config_component *source_cfg = NULL, *sink_cfg = NULL; cfg = bt_config_from_args(argc, argv, &ret); @@ -408,17 +434,10 @@ int main(int argc, const char **argv) goto end; } - if (cfg->plugin_paths && !bt_value_array_is_empty(cfg->plugin_paths)) { - first_plugin_path_value = bt_value_array_get( - cfg->plugin_paths, 0); - bt_value_string_get(first_plugin_path_value, - &first_plugin_path); - ret = bt_component_factory_load_recursive(component_factory, - first_plugin_path); - if (ret) { - fprintf(stderr, "Failed to dynamically load plugins.\n"); - goto end; - } + if (load_plugins(cfg)) { + fprintf(stderr, "Failed to load plugins.\n"); + ret = -1; + goto end; } ret = bt_component_factory_load_static(component_factory); @@ -501,7 +520,6 @@ end: BT_PUT(source_params); BT_PUT(sink_params); BT_PUT(cfg); - BT_PUT(first_plugin_path_value); BT_PUT(sink_cfg); BT_PUT(source_cfg); return ret ? 1 : 0; -- 2.34.1