Fix: define _LGPL_SOURCE in C files
[lttng-tools.git] / src / common / config / config.c
index c9777d63f673728313c9f1d0fb0d8cc783e6af21..f93c5a678f12df5e8024bc21197a7900df12ce84 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #define _GNU_SOURCE
+#define _LGPL_SOURCE
 #include <assert.h>
 #include <ctype.h>
 #include <stdio.h>
@@ -117,6 +118,8 @@ const char * const config_element_max_size = "max_size";
 const char * const config_domain_type_kernel = "KERNEL";
 const char * const config_domain_type_ust = "UST";
 const char * const config_domain_type_jul = "JUL";
+const char * const config_domain_type_log4j = "LOG4J";
+const char * const config_domain_type_python = "PYTHON";
 
 const char * const config_buffer_type_per_pid = "PER_PID";
 const char * const config_buffer_type_per_uid = "PER_UID";
@@ -353,7 +356,7 @@ end:
 }
 
 LTTNG_HIDDEN
-struct config_writer *config_writer_create(int fd_output)
+struct config_writer *config_writer_create(int fd_output, int indent)
 {
        int ret;
        struct config_writer *writer;
@@ -379,12 +382,12 @@ struct config_writer *config_writer_create(int fd_output)
 
        ret = xmlTextWriterSetIndentString(writer->writer,
                BAD_CAST config_xml_indent_string);
-       if (ret)  {
+       if (ret) {
                goto error_destroy;
        }
 
-       ret = xmlTextWriterSetIndent(writer->writer, 1);
-       if (ret)  {
+       ret = xmlTextWriterSetIndent(writer->writer, indent);
+       if (ret) {
                goto error_destroy;
        }
 
@@ -749,6 +752,10 @@ int get_domain_type(xmlChar *domain)
                ret = LTTNG_DOMAIN_UST;
        } else if (!strcmp((char *) domain, config_domain_type_jul)) {
                ret = LTTNG_DOMAIN_JUL;
+       } else if (!strcmp((char *) domain, config_domain_type_log4j)) {
+               ret = LTTNG_DOMAIN_LOG4J;
+       } else if (!strcmp((char *) domain, config_domain_type_python)) {
+               ret = LTTNG_DOMAIN_PYTHON;
        } else {
                goto error;
        }
@@ -1236,6 +1243,7 @@ int create_session(const char *name,
        struct lttng_domain *kernel_domain,
        struct lttng_domain *ust_domain,
        struct lttng_domain *jul_domain,
+       struct lttng_domain *log4j_domain,
        xmlNodePtr output_node,
        uint64_t live_timer_interval)
 {
@@ -1276,7 +1284,7 @@ int create_session(const char *name,
                int i;
                struct lttng_domain *domain;
                struct lttng_domain *domains[] =
-                       { kernel_domain, ust_domain, jul_domain };
+                       { kernel_domain, ust_domain, jul_domain, log4j_domain};
 
                /* network destination */
                if (live_timer_interval && live_timer_interval != UINT64_MAX) {
@@ -1956,7 +1964,9 @@ int process_context_node(xmlNodePtr context_node,
                xmlNodePtr perf_attr_node;
 
                /* perf */
-               context.ctx = LTTNG_EVENT_CONTEXT_PERF_COUNTER;
+               context.ctx = handle->domain.type == LTTNG_DOMAIN_KERNEL ?
+                       LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER :
+                       LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER;
                for (perf_attr_node = xmlFirstElementChild(context_child_node);
                        perf_attr_node; perf_attr_node =
                                xmlNextElementSibling(perf_attr_node)) {
@@ -2147,6 +2157,8 @@ int process_session_node(xmlNodePtr session_node, const char *session_name,
        struct lttng_domain *kernel_domain = NULL;
        struct lttng_domain *ust_domain = NULL;
        struct lttng_domain *jul_domain = NULL;
+       struct lttng_domain *log4j_domain = NULL;
+       struct lttng_domain *python_domain = NULL;
 
        for (node = xmlFirstElementChild(session_node); node;
                node = xmlNextElementSibling(node)) {
@@ -2273,6 +2285,20 @@ int process_session_node(xmlNodePtr session_node, const char *session_name,
                        }
                        jul_domain = domain;
                        break;
+               case LTTNG_DOMAIN_LOG4J:
+                       if (log4j_domain) {
+                               /* Same domain seen twice, invalid! */
+                               goto domain_init_error;
+                       }
+                       log4j_domain = domain;
+                       break;
+               case LTTNG_DOMAIN_PYTHON:
+                       if (python_domain) {
+                               /* Same domain seen twice, invalid! */
+                               goto domain_init_error;
+                       }
+                       python_domain = domain;
+                       break;
                default:
                        WARN("Invalid domain type");
                        goto domain_init_error;
@@ -2299,11 +2325,11 @@ domain_init_error:
        } else if (live_timer_interval &&
                live_timer_interval != UINT64_MAX) {
                ret = create_session(name, kernel_domain, ust_domain, jul_domain,
-                               output_node, live_timer_interval);
+                               log4j_domain, output_node, live_timer_interval);
        } else {
                /* regular session */
                ret = create_session(name, kernel_domain, ust_domain, jul_domain,
-                               output_node, UINT64_MAX);
+                               log4j_domain, output_node, UINT64_MAX);
        }
        if (ret) {
                goto error;
@@ -2334,10 +2360,37 @@ error:
        free(kernel_domain);
        free(ust_domain);
        free(jul_domain);
+       free(log4j_domain);
+       free(python_domain);
        free(name);
        return ret;
 }
 
+/*
+ * Return 1 if the given path is readable by the current UID or 0 if not.
+ * Return -1 if the path is EPERM.
+ */
+static int validate_file_read_creds(const char *path)
+{
+       int ret;
+
+       assert(path);
+
+       /* Can we read the file. */
+       ret = access(path, R_OK);
+       if (!ret) {
+               goto valid;
+       }
+       if (errno == EACCES) {
+               return -1;
+       } else {
+               /* Invalid. */
+               return 0;
+       }
+valid:
+       return 1;
+}
+
 static
 int load_session_from_file(const char *path, const char *session_name,
        struct session_config_validation_ctx *validation_ctx, int override)
@@ -2346,14 +2399,17 @@ int load_session_from_file(const char *path, const char *session_name,
        xmlDocPtr doc = NULL;
        xmlNodePtr sessions_node;
        xmlNodePtr session_node;
-       struct stat sb;
 
        assert(path);
        assert(validation_ctx);
 
-       ret = stat(path, &sb);
-       if (ret) {
-               ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
+       ret = validate_file_read_creds(path);
+       if (ret != 1) {
+               if (ret == -1) {
+                       ret = -LTTNG_ERR_EPERM;
+               } else {
+                       ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
+               }
                goto end;
        }
 
@@ -2504,11 +2560,46 @@ end:
        return ret;
 }
 
+/*
+ * Validate that the given path's credentials and the current process have the
+ * same UID. If so, return 1 else return 0 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 1;
+invalid:
+       return 0;
+}
+
 LTTNG_HIDDEN
 int config_load_session(const char *path, const char *session_name,
-               int override)
+               int override, unsigned int autoload)
 {
        int ret;
+       const char *path_ptr = NULL;
        struct session_config_validation_ctx validation_ctx = { 0 };
 
        ret = init_session_config_validation_ctx(&validation_ctx);
@@ -2517,34 +2608,77 @@ 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);
-                       if (ret < 0) {
-                               goto end;
-                       }
+                       /*
+                        * 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);
+                               if (ret < 0) {
+                                       PERROR("snprintf session autoload home config path");
+                                       goto end;
+                               }
 
-                       ret = load_session_from_path(path, session_name,
-                               &validation_ctx, override);
-                       if (!ret || (ret && ret != -LTTNG_ERR_LOAD_SESSION_NOENT)) {
-                               /* Session found or an error occured */
-                               free(path);
-                               goto end;
+                               /*
+                                * Credentials are only validated for the autoload in order to
+                                * avoid any user session daemon to try to load kernel sessions
+                                * automatically and failing all the times.
+                                */
+                               ret = validate_path_creds(path);
+                               if (ret) {
+                                       path_ptr = path;
+                               }
+                       } else {
+                               ret = snprintf(path, sizeof(path),
+                                               DEFAULT_SESSION_HOME_CONFIGPATH, home_path);
+                               if (ret < 0) {
+                                       PERROR("snprintf session home config path");
+                                       goto end;
+                               }
+                               path_ptr = path;
+                       }
+                       if (path_ptr) {
+                               ret = load_session_from_path(path_ptr, 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.
+                                */
                        }
+               }
+
+               /* Reset path pointer for the system wide dir. */
+               path_ptr = NULL;
 
-                       free(path);
+               /* Try system wide configuration directory. */
+               if (autoload) {
+                       sys_path = DEFAULT_SESSION_SYSTEM_CONFIGPATH "/"
+                               DEFAULT_SESSION_CONFIG_AUTOLOAD;
+                       ret = validate_path_creds(sys_path);
+                       if (ret) {
+                               path_ptr = sys_path;
+                       }
+               } else {
+                       sys_path = DEFAULT_SESSION_SYSTEM_CONFIGPATH;
+                       path_ptr = sys_path;
                }
 
-               /* Try system session configuration path */
-               ret = load_session_from_path(DEFAULT_SESSION_SYSTEM_CONFIGPATH,
-                       session_name, &validation_ctx, override);
-               if (!ret || (ret && ret != -LTTNG_ERR_LOAD_SESSION_NOENT)) {
-                       /* Session found or an error occured */
-                       goto end;
+               if (path_ptr) {
+                       ret = load_session_from_path(path_ptr, session_name,
+                                       &validation_ctx, override);
                }
        } else {
                ret = access(path, F_OK);
This page took 0.028837 seconds and 4 git commands to generate.