Fix: change session file loading order
[lttng-tools.git] / src / common / config / config.c
index e3fe74ac284973b6912236dfec89be2904d4bca1..8c926b53ed74ea90151d19bb8097c73cfda26b67 100644 (file)
@@ -154,6 +154,7 @@ const char * const config_event_context_vppid = "VPPID";
 const char * const config_event_context_pthread_id = "PTHREAD_ID";
 const char * const config_event_context_hostname = "HOSTNAME";
 const char * const config_event_context_ip = "IP";
+const char * const config_event_context_perf_thread_counter = "PERF_THREAD_COUNTER";
 
 struct consumer_output {
        int enabled;
@@ -191,54 +192,73 @@ int config_get_section_entries(const char *override_path, const char *section,
                config_entry_handler_cb handler, void *user_data)
 {
        int ret = 0;
+       char *path;
        FILE *config_file = NULL;
        struct handler_filter_args filter = { section, handler, user_data };
 
-       if (override_path) {
-               config_file = fopen(override_path, "r");
-               if (config_file) {
-                       DBG("Loaded daemon configuration file at %s",
-                               override_path);
-               } else {
-                       ERR("Failed to open daemon configuration file at %s",
-                               override_path);
-                       ret = -ENOENT;
-                       goto end;
-               }
-       } else {
-               char *path = utils_get_home_dir();
+       /* First, try system-wide conf. file. */
+       path = DEFAULT_DAEMON_SYSTEM_CONFIGPATH;
 
-               /* Try to open the user's daemon configuration file */
-               if (path) {
-                       ret = asprintf(&path, DEFAULT_DAEMON_HOME_CONFIGPATH, path);
-                       if (ret < 0) {
-                               goto end;
-                       }
+       config_file = fopen(path, "r");
+       if (config_file) {
+               DBG("Loading daemon conf file at %s", path);
+               /*
+                * Return value is not very important here since error or not, we
+                * continue and try the next possible conf. file.
+                */
+               (void) ini_parse_file(config_file,
+                               (ini_entry_handler) config_entry_handler_filter,
+                               (void *) &filter);
+               fclose(config_file);
+       }
 
-                       ret = 0;
-                       config_file = fopen(path, "r");
-                       if (config_file) {
-                               DBG("Loaded daemon configuration file at %s", path);
-                       }
+       /* Second is the user local configuration. */
+       path = utils_get_home_dir();
+       if (path) {
+               char fullpath[PATH_MAX];
 
-                       free(path);
+               ret = snprintf(fullpath, sizeof(fullpath),
+                               DEFAULT_DAEMON_HOME_CONFIGPATH, path);
+               if (ret < 0) {
+                       PERROR("snprintf user conf. path");
+                       goto error;
                }
 
-               /* Try to open the system daemon configuration file */
-               if (!config_file) {
-                       config_file = fopen(DEFAULT_DAEMON_HOME_CONFIGPATH, "r");
+               config_file = fopen(fullpath, "r");
+               if (config_file) {
+                       DBG("Loading daemon user conf file at %s", path);
+                       /*
+                        * Return value is not very important here since error or not, we
+                        * continue and try the next possible conf. file.
+                        */
+                       (void) ini_parse_file(config_file,
+                                       (ini_entry_handler) config_entry_handler_filter,
+                                       (void *) &filter);
+                       fclose(config_file);
                }
        }
 
-       if (!config_file) {
-               DBG("No daemon configuration file found.");
-               goto end;
+       /* Final path is the one that the user might have provided. */
+       if (override_path) {
+               config_file = fopen(override_path, "r");
+               if (config_file) {
+                       DBG("Loading daemon command line conf file at %s", override_path);
+                       (void) ini_parse_file(config_file,
+                                       (ini_entry_handler) config_entry_handler_filter,
+                                       (void *) &filter);
+                       fclose(config_file);
+               } else {
+                       ERR("Failed to open daemon configuration file at %s",
+                               override_path);
+                       ret = -ENOENT;
+                       goto error;
+               }
        }
 
-       ret = ini_parse_file(config_file,
-                       (ini_entry_handler) config_entry_handler_filter, (void *) &filter);
+       /* Everything went well. */
+       ret = 0;
 
-end:
+error:
        return ret;
 }
 
@@ -2136,7 +2156,7 @@ int process_session_node(xmlNodePtr session_node, const char *session_name,
                        xmlChar *node_content = xmlNodeGetContent(node);
                        if (!node_content) {
                                ret = -LTTNG_ERR_NOMEM;
-                               goto end;
+                               goto error;
                        }
 
                        name = (char *) node_content;
@@ -2150,14 +2170,14 @@ int process_session_node(xmlNodePtr session_node, const char *session_name,
                        xmlChar *node_content = xmlNodeGetContent(node);
                        if (!node_content) {
                                ret = -LTTNG_ERR_NOMEM;
-                               goto end;
+                               goto error;
                        }
 
                        ret = parse_bool(node_content, &started);
                        free(node_content);
                        if (ret) {
                                ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
-                               goto end;
+                               goto error;
                        }
                } else if (!output_node && !strcmp((const char *) node->name,
                        config_element_output)) {
@@ -2175,14 +2195,14 @@ int process_session_node(xmlNodePtr session_node, const char *session_name,
                                        xmlNodeGetContent(attributes_child);
                                if (!snapshot_mode_content) {
                                        ret = -LTTNG_ERR_NOMEM;
-                                       goto end;
+                                       goto error;
                                }
 
                                ret = parse_bool(snapshot_mode_content, &snapshot_mode);
                                free(snapshot_mode_content);
                                if (ret) {
                                        ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
-                                       goto end;
+                                       goto error;
                                }
                        } else {
                                /* live_timer_interval */
@@ -2190,14 +2210,14 @@ int process_session_node(xmlNodePtr session_node, const char *session_name,
                                        xmlNodeGetContent(attributes_child);
                                if (!timer_interval_content) {
                                        ret = -LTTNG_ERR_NOMEM;
-                                       goto end;
+                                       goto error;
                                }
 
                                ret = parse_uint(timer_interval_content, &live_timer_interval);
                                free(timer_interval_content);
                                if (ret) {
                                        ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
-                                       goto end;
+                                       goto error;
                                }
                        }
                }
@@ -2206,13 +2226,13 @@ int process_session_node(xmlNodePtr session_node, const char *session_name,
        if (!name) {
                /* Mandatory attribute, as defined in the session XSD */
                ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
-               goto end;
+               goto error;
        }
 
        if (session_name && strcmp(name, session_name)) {
                /* This is not the session we are looking for */
-               ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
-               goto end;
+               ret = -LTTNG_ERR_NO_SESSION;
+               goto error;
        }
 
        /* Init domains to create the session handles */
@@ -2223,7 +2243,7 @@ int process_session_node(xmlNodePtr session_node, const char *session_name,
                domain = zmalloc(sizeof(*domain));
                if (!domain) {
                        ret = -LTTNG_ERR_NOMEM;
-                       goto end;
+                       goto error;
                }
 
                ret = init_domain(node, domain);
@@ -2261,7 +2281,7 @@ int process_session_node(xmlNodePtr session_node, const char *session_name,
 domain_init_error:
                free(domain);
                ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
-               goto end;
+               goto error;
        }
 
        if (override) {
@@ -2269,7 +2289,7 @@ domain_init_error:
                ret = lttng_destroy_session(name);
                if (ret && ret != -LTTNG_ERR_SESS_NOT_FOUND) {
                        ERR("Failed to destroy existing session.");
-                       goto end;
+                       goto error;
                }
        }
 
@@ -2285,9 +2305,8 @@ domain_init_error:
                ret = create_session(name, kernel_domain, ust_domain, jul_domain,
                                output_node, UINT64_MAX);
        }
-
        if (ret) {
-               goto end;
+               goto error;
        }
 
        for (node = xmlFirstElementChild(domains_node); node;
@@ -2304,12 +2323,14 @@ domain_init_error:
                        goto end;
                }
        }
+
 end:
        if (ret < 0) {
                ERR("Failed to load session %s: %s", name, lttng_strerror(ret));
                lttng_destroy_session(name);
        }
 
+error:
        free(kernel_domain);
        free(ust_domain);
        free(jul_domain);
@@ -2483,9 +2504,43 @@ end:
        return ret;
 }
 
+/*
+ * Validate that the given path's credentials and the current process have the
+ * same UID. If so, return 0 else return 1 if it does NOT match.
+ */
+static int validate_path_creds(const char *path)
+{
+       int ret, uid = getuid();
+       struct stat buf;
+
+       assert(path);
+
+       if (uid != 0) {
+               goto valid;
+       }
+
+       ret = stat(path, &buf);
+       if (ret < 0) {
+               if (errno != ENOENT) {
+                       PERROR("stat");
+               }
+               ret = -LTTNG_ERR_INVALID;
+               goto valid;
+       }
+
+       if (buf.st_uid != uid) {
+               goto invalid;
+       }
+
+valid:
+       return 0;
+invalid:
+       return 1;
+}
+
 LTTNG_HIDDEN
 int config_load_session(const char *path, const char *session_name,
-               int override)
+               int override, unsigned int autoload)
 {
        int ret;
        struct session_config_validation_ctx validation_ctx = { 0 };
@@ -2496,33 +2551,57 @@ int config_load_session(const char *path, const char *session_name,
        }
 
        if (!path) {
+               char *home_path;
+               const char *sys_path;
+
                /* Try home path */
-               char *home_path = utils_get_home_dir();
+               home_path = utils_get_home_dir();
                if (home_path) {
-                       char *path;
+                       char path[PATH_MAX];
 
-                       ret = asprintf(&path, DEFAULT_SESSION_HOME_CONFIGPATH,
-                               home_path);
+                       /*
+                        * Try user session configuration path. Ignore error here so we can
+                        * continue loading the system wide sessions.
+                        */
+                       if (autoload) {
+                               ret = snprintf(path, sizeof(path),
+                                               DEFAULT_SESSION_HOME_CONFIGPATH "/"
+                                               DEFAULT_SESSION_CONFIG_AUTOLOAD, home_path);
+                       } else {
+                               ret = snprintf(path, sizeof(path),
+                                               DEFAULT_SESSION_HOME_CONFIGPATH, home_path);
+                       }
                        if (ret < 0) {
+                               PERROR("snprintf session home config path");
                                goto end;
                        }
 
-                       ret = load_session_from_path(path, session_name,
-                               &validation_ctx, 0);
-                       if (!ret || (ret && ret != -LTTNG_ERR_LOAD_SESSION_NOENT)) {
-                               /* Session found or an error occured */
-                               free(path);
-                               goto end;
+                       ret = validate_path_creds(path);
+                       if (!ret && autoload) {
+                               ret = load_session_from_path(path, session_name,
+                                               &validation_ctx, override);
+                               if (ret && ret != -LTTNG_ERR_LOAD_SESSION_NOENT) {
+                                       goto end;
+                               }
+                               /*
+                                * Continue even if the session was found since we have to try
+                                * the system wide sessions.
+                                */
                        }
+               }
 
-                       free(path);
+               /* Try system wide configuration directory. */
+               if (autoload) {
+                       sys_path = DEFAULT_SESSION_SYSTEM_CONFIGPATH "/"
+                               DEFAULT_SESSION_CONFIG_AUTOLOAD;
+               } else {
+                       sys_path = DEFAULT_SESSION_HOME_CONFIGPATH;
                }
 
-               /* Try system session configuration path */
-               ret = load_session_from_path(DEFAULT_SESSION_SYSTEM_CONFIGPATH,
-                       session_name, &validation_ctx, 0);
-               if (!ret || (ret && ret != -LTTNG_ERR_LOAD_SESSION_NOENT)) {
-                       /* Session found or an error occured */
+               ret = validate_path_creds(sys_path);
+               if (!ret && autoload) {
+                       ret = load_session_from_path(sys_path, session_name,
+                                       &validation_ctx, override);
                        goto end;
                }
        } else {
This page took 0.027997 seconds and 4 git commands to generate.