X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Fconfig%2Fconfig.c;h=f93c5a678f12df5e8024bc21197a7900df12ce84;hp=c9777d63f673728313c9f1d0fb0d8cc783e6af21;hb=6c1c0768320135c6936c371b09731851b508c023;hpb=5252df626db3d88190b6fa67d7ee712e4500c4e4 diff --git a/src/common/config/config.c b/src/common/config/config.c index c9777d63f..f93c5a678 100644 --- a/src/common/config/config.c +++ b/src/common/config/config.c @@ -16,6 +16,7 @@ */ #define _GNU_SOURCE +#define _LGPL_SOURCE #include #include #include @@ -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);