Handle system and home plugin paths
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 16 Dec 2016 06:24:07 +0000 (07:24 +0100)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Sat, 27 May 2017 18:09:08 +0000 (14:09 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
converter/Makefile.am
converter/babeltrace-cfg.c
converter/babeltrace.c

index 262214f7cc8999548395e59dcefc31c9028e04c1..4be27f987271b9a3128c303f4f0147c00e7dfd14 100644 (file)
@@ -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
index c9744475fc7b88fc18168135952333954f566371..d3072488e0643f414c2cfe6014542919e2ec1fb0 100644 (file)
 #include <babeltrace/values.h>
 #include <popt.h>
 #include <glib.h>
+#include <sys/types.h>
+#include <pwd.h>
 #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);
index 49f4cc2c02eea36b45daa366fd2e24327a2cddf6..f969f8d73cc0d728ea4d373d932d820d3b0b2b22 100644 (file)
@@ -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;
This page took 0.029306 seconds and 4 git commands to generate.