X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Fconfig%2Fsession-config.c;h=518fde70b5e63d1d244369ca634d0a647bb75f21;hp=4d5045f09237bf068f6fba08d13643c1acf17d12;hb=ff86d8d0bd96d3660ad79aa6158fbeb9055652b2;hpb=259c267446a63c501298f39a5d2397314b11f729 diff --git a/src/common/config/session-config.c b/src/common/config/session-config.c index 4d5045f09..518fde70b 100644 --- a/src/common/config/session-config.c +++ b/src/common/config/session-config.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -133,6 +134,7 @@ const char * const config_element_targets = "targets"; const char * const config_element_target_pid = "pid_target"; LTTNG_HIDDEN const char * const config_element_rotation_timer_interval = "rotation_schedule_timer_period"; +LTTNG_HIDDEN const char * const config_element_rotation_size = "rotation_schedule_size"; LTTNG_HIDDEN const char * const config_element_rotation_schedule = "rotation_schedule"; const char * const config_domain_type_kernel = "KERNEL"; @@ -676,13 +678,12 @@ char *get_session_config_xsd_path() goto end; } - strncpy(xsd_path, base_path, max_path_len); + strcpy(xsd_path, base_path); if (xsd_path[base_path_len - 1] != '/') { xsd_path[base_path_len++] = '/'; } - strncpy(xsd_path + base_path_len, DEFAULT_SESSION_CONFIG_XSD_FILENAME, - max_path_len - base_path_len); + strcpy(xsd_path + base_path_len, DEFAULT_SESSION_CONFIG_XSD_FILENAME); end: return xsd_path; } @@ -1344,10 +1345,6 @@ end: static 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, const struct config_load_session_override_attr *overrides) @@ -1499,7 +1496,6 @@ int process_probe_attribute_node(xmlNodePtr probe_attribute_node, } else if (!strcmp((const char *) probe_attribute_node->name, config_element_symbol_name)) { xmlChar *content; - size_t name_len; /* symbol_name */ content = xmlNodeGetContent(probe_attribute_node); @@ -1508,15 +1504,18 @@ int process_probe_attribute_node(xmlNodePtr probe_attribute_node, goto end; } - name_len = strlen((char *) content); - if (name_len >= LTTNG_SYMBOL_NAME_LEN) { - WARN("symbol_name too long."); + ret = lttng_strncpy(attr->symbol_name, + (const char *) content, + LTTNG_SYMBOL_NAME_LEN); + if (ret == -1) { + ERR("symbol name \"%s\"'s length (%zu) exceeds the maximal permitted length (%d) in session configuration", + (const char *) content, + strlen((const char *) content), + LTTNG_SYMBOL_NAME_LEN); ret = -LTTNG_ERR_LOAD_INVALID_CONFIG; free(content); goto end; } - - strncpy(attr->symbol_name, (const char *) content, name_len); free(content); } ret = 0; @@ -1565,7 +1564,6 @@ int process_event_node(xmlNodePtr event_node, struct lttng_handle *handle, node = xmlNextElementSibling(node)) { if (!strcmp((const char *) node->name, config_element_name)) { xmlChar *content; - size_t name_len; /* name */ content = xmlNodeGetContent(node); @@ -1574,15 +1572,18 @@ int process_event_node(xmlNodePtr event_node, struct lttng_handle *handle, goto end; } - name_len = strlen((char *) content); - if (name_len >= LTTNG_SYMBOL_NAME_LEN) { - WARN("Channel name too long."); + ret = lttng_strncpy(event.name, + (const char *) content, + LTTNG_SYMBOL_NAME_LEN); + if (ret == -1) { + WARN("Event \"%s\"'s name length (%zu) exceeds the maximal permitted length (%d) in session configuration", + (const char *) content, + strlen((const char *) content), + LTTNG_SYMBOL_NAME_LEN); ret = -LTTNG_ERR_LOAD_INVALID_CONFIG; free(content); goto end; } - - strncpy(event.name, (const char *) content, name_len); free(content); } else if (!strcmp((const char *) node->name, config_element_enabled)) { @@ -1773,8 +1774,14 @@ int process_event_node(xmlNodePtr event_node, struct lttng_handle *handle, goto end; } - strncpy(event.attr.ftrace.symbol_name, (char *) content, - sym_len); + ret = lttng_strncpy( + event.attr.ftrace.symbol_name, + (char *) content, sym_len); + if (ret == -1) { + ret = -LTTNG_ERR_LOAD_INVALID_CONFIG; + free(content); + goto end; + } free(content); } } @@ -1789,6 +1796,7 @@ int process_event_node(xmlNodePtr event_node, struct lttng_handle *handle, goto end; } } + ret = 0; end: for (i = 0; i < exclusion_count; i++) { free(exclusions[i]); @@ -1858,7 +1866,6 @@ int process_channel_attr_node(xmlNodePtr attr_node, if (!strcmp((const char *) attr_node->name, config_element_name)) { xmlChar *content; - size_t name_len; /* name */ content = xmlNodeGetContent(attr_node); @@ -1867,15 +1874,18 @@ int process_channel_attr_node(xmlNodePtr attr_node, goto end; } - name_len = strlen((char *) content); - if (name_len >= LTTNG_SYMBOL_NAME_LEN) { - WARN("Channel name too long."); + ret = lttng_strncpy(channel->name, + (const char *) content, + LTTNG_SYMBOL_NAME_LEN); + if (ret == -1) { + WARN("Channel \"%s\"'s name length (%zu) exceeds the maximal permitted length (%d) in session configuration", + (const char *) content, + strlen((const char *) content), + LTTNG_SYMBOL_NAME_LEN); ret = -LTTNG_ERR_LOAD_INVALID_CONFIG; free(content); goto end; } - - strncpy(channel->name, (const char *) content, name_len); free(content); } else if (!strcmp((const char *) attr_node->name, config_element_enabled)) { @@ -2243,7 +2253,6 @@ int process_context_node(xmlNodePtr context_node, } else if (!strcmp((const char *) perf_attr_node->name, config_element_name)) { xmlChar *content; - size_t name_len; /* name */ content = xmlNodeGetContent(perf_attr_node); @@ -2252,16 +2261,18 @@ int process_context_node(xmlNodePtr context_node, goto end; } - name_len = strlen((char *) content); - if (name_len >= LTTNG_SYMBOL_NAME_LEN) { - WARN("perf context name too long."); + ret = lttng_strncpy(context.u.perf_counter.name, + (const char *) content, + LTTNG_SYMBOL_NAME_LEN); + if (ret == -1) { + WARN("Perf counter \"%s\"'s name length (%zu) exceeds the maximal permitted length (%d) in session configuration", + (const char *) content, + strlen((const char *) content), + LTTNG_SYMBOL_NAME_LEN); ret = -LTTNG_ERR_LOAD_INVALID_CONFIG; free(content); goto end; } - - strncpy(context.u.perf_counter.name, (const char *) content, - name_len); free(content); } } @@ -2436,10 +2447,31 @@ int process_domain_node(xmlNodePtr domain_node, const char *session_name) /* create all channels */ for (node = xmlFirstElementChild(channels_node); node; node = xmlNextElementSibling(node)) { + const enum lttng_domain_type original_domain = domain.type; xmlNodePtr contexts_node = NULL; xmlNodePtr events_node = NULL; xmlNodePtr channel_attr_node; + /* + * Channels of the "agent" types cannot be created directly. + * They are meant to be created implicitly through the + * activation of events in their domain. However, a user + * can override the default channel configuration attributes + * by creating the underlying UST channel _before_ enabling + * an agent domain event. + * + * Hence, the channel's type is substituted before the creation + * and restored by the time the events are created. + */ + switch (domain.type) { + case LTTNG_DOMAIN_JUL: + case LTTNG_DOMAIN_LOG4J: + case LTTNG_DOMAIN_PYTHON: + domain.type = LTTNG_DOMAIN_UST; + default: + break; + } + channel = lttng_channel_create(&domain); if (!channel) { ret = -1; @@ -2461,6 +2493,9 @@ int process_domain_node(xmlNodePtr domain_node, const char *session_name) goto end; } + /* Restore the original channel domain. */ + domain.type = original_domain; + ret = process_events_node(events_node, handle, channel->name); if (ret) { goto end; @@ -2518,12 +2553,14 @@ int process_session_node(xmlNodePtr session_node, const char *session_name, { int ret, started = -1, snapshot_mode = -1; uint64_t live_timer_interval = UINT64_MAX, - rotation_timer_interval = 0; + rotation_timer_interval = 0, + rotation_size = 0; xmlChar *name = NULL; xmlChar *shm_path = NULL; xmlNodePtr domains_node = NULL; xmlNodePtr output_node = NULL; xmlNodePtr node; + xmlNodePtr attributes_child; struct lttng_domain *kernel_domain = NULL; struct lttng_domain *ust_domain = NULL; struct lttng_domain *jul_domain = NULL; @@ -2578,58 +2615,76 @@ int process_session_node(xmlNodePtr session_node, const char *session_name, } else { /* * attributes, snapshot_mode, live_timer_interval, rotation_size, - * rotation_timer_interval. */ - xmlNodePtr attributes_child = - xmlFirstElementChild(node); - - if (!strcmp((const char *) attributes_child->name, - config_element_snapshot_mode)) { - /* snapshot_mode */ - xmlChar *snapshot_mode_content = - xmlNodeGetContent(attributes_child); - if (!snapshot_mode_content) { - ret = -LTTNG_ERR_NOMEM; - goto error; - } + * rotation_timer_interval. + */ + for (attributes_child = xmlFirstElementChild(node); attributes_child; + attributes_child = xmlNextElementSibling(attributes_child)) { + if (!strcmp((const char *) attributes_child->name, + config_element_snapshot_mode)) { + /* snapshot_mode */ + xmlChar *snapshot_mode_content = + xmlNodeGetContent(attributes_child); + if (!snapshot_mode_content) { + ret = -LTTNG_ERR_NOMEM; + goto error; + } - ret = parse_bool(snapshot_mode_content, &snapshot_mode); - free(snapshot_mode_content); - if (ret) { - ret = -LTTNG_ERR_LOAD_INVALID_CONFIG; - goto error; - } - } else if (!strcmp((const char *) attributes_child->name, - config_element_live_timer_interval)) { - /* live_timer_interval */ - xmlChar *timer_interval_content = - xmlNodeGetContent(attributes_child); - if (!timer_interval_content) { - ret = -LTTNG_ERR_NOMEM; - goto error; - } + ret = parse_bool(snapshot_mode_content, &snapshot_mode); + free(snapshot_mode_content); + if (ret) { + ret = -LTTNG_ERR_LOAD_INVALID_CONFIG; + goto error; + } + } else if (!strcmp((const char *) attributes_child->name, + config_element_live_timer_interval)) { + /* live_timer_interval */ + xmlChar *timer_interval_content = + xmlNodeGetContent(attributes_child); + if (!timer_interval_content) { + ret = -LTTNG_ERR_NOMEM; + goto error; + } - ret = parse_uint(timer_interval_content, &live_timer_interval); - free(timer_interval_content); - if (ret) { - ret = -LTTNG_ERR_LOAD_INVALID_CONFIG; - goto error; + ret = parse_uint(timer_interval_content, &live_timer_interval); + free(timer_interval_content); + if (ret) { + ret = -LTTNG_ERR_LOAD_INVALID_CONFIG; + goto error; + } } - } - if (!strcmp((const char *) attributes_child->name, - config_element_rotation_timer_interval)) { - /* rotation_timer_interval */ - xmlChar *timer_interval_content = - xmlNodeGetContent(attributes_child); - if (!timer_interval_content) { - ret = -LTTNG_ERR_NOMEM; - goto error; + if (!strcmp((const char *) attributes_child->name, + config_element_rotation_timer_interval)) { + /* rotation_timer_interval */ + xmlChar *timer_interval_content = + xmlNodeGetContent(attributes_child); + if (!timer_interval_content) { + ret = -LTTNG_ERR_NOMEM; + goto error; + } + + ret = parse_uint(timer_interval_content, &rotation_timer_interval); + free(timer_interval_content); + if (ret) { + ret = -LTTNG_ERR_LOAD_INVALID_CONFIG; + goto error; + } } + if (!strcmp((const char *) attributes_child->name, + config_element_rotation_size)) { + /* rotation_size */ + xmlChar *rotation_size_content = + xmlNodeGetContent(attributes_child); + if (!rotation_size_content) { + ret = -LTTNG_ERR_NOMEM; + goto error; + } - ret = parse_uint(timer_interval_content, &rotation_timer_interval); - free(timer_interval_content); - if (ret) { - ret = -LTTNG_ERR_LOAD_INVALID_CONFIG; - goto error; + ret = parse_uint(rotation_size_content, &rotation_size); + free(rotation_size_content); + if (ret) { + ret = -LTTNG_ERR_LOAD_INVALID_CONFIG; + goto error; + } } } } @@ -2740,13 +2795,11 @@ domain_init_error: overrides); } else if (live_timer_interval && live_timer_interval != UINT64_MAX) { - ret = create_session((const char *) name, kernel_domain, - ust_domain, jul_domain, log4j_domain, + ret = create_session((const char *) name, output_node, live_timer_interval, overrides); } else { /* regular session */ - ret = create_session((const char *) name, kernel_domain, - ust_domain, jul_domain, log4j_domain, + ret = create_session((const char *) name, output_node, UINT64_MAX, overrides); } if (ret) { @@ -2769,7 +2822,7 @@ domain_init_error: } } - if (rotation_timer_interval) { + if (rotation_timer_interval || rotation_size) { struct lttng_rotation_schedule_attr *rotation_attr = lttng_rotation_schedule_attr_create(); if (!rotation_attr) { @@ -2782,6 +2835,7 @@ domain_init_error: } lttng_rotation_schedule_attr_set_timer_period(rotation_attr, rotation_timer_interval); + lttng_rotation_schedule_attr_set_size(rotation_attr, rotation_size); ret = lttng_rotation_set_schedule(rotation_attr); lttng_rotation_schedule_attr_destroy(rotation_attr); if (ret) { @@ -2899,23 +2953,6 @@ end: return ret; } -/* Allocate dirent as recommended by READDIR(3), NOTES on readdir_r */ -static -struct dirent *alloc_dirent(const char *path) -{ - size_t len; - long name_max; - struct dirent *entry; - - name_max = pathconf(path, _PC_NAME_MAX); - if (name_max == -1) { - name_max = PATH_MAX; - } - len = offsetof(struct dirent, d_name) + name_max + 1; - entry = zmalloc(len); - return entry; -} - static int load_session_from_path(const char *path, const char *session_name, struct session_config_validation_ctx *validation_ctx, int overwrite, @@ -2923,9 +2960,19 @@ int load_session_from_path(const char *path, const char *session_name, { int ret, session_found = !session_name; DIR *directory = NULL; + struct lttng_dynamic_buffer file_path; + size_t path_len; assert(path); assert(validation_ctx); + path_len = strlen(path); + lttng_dynamic_buffer_init(&file_path); + if (path_len >= LTTNG_PATH_MAX) { + ERR("Session configuration load path \"%s\" length (%zu) exceeds the maximal length allowed (%d)", + path, path_len, LTTNG_PATH_MAX); + ret = -LTTNG_ERR_INVALID; + goto end; + } directory = opendir(path); if (!directory) { @@ -2942,67 +2989,107 @@ int load_session_from_path(const char *path, const char *session_name, } } if (directory) { - struct dirent *entry; - struct dirent *result; - char *file_path = NULL; - size_t path_len = strlen(path); - - if (path_len >= PATH_MAX) { - ret = -LTTNG_ERR_INVALID; - goto end; - } + size_t file_path_root_len; - entry = alloc_dirent(path); - if (!entry) { + ret = lttng_dynamic_buffer_set_capacity(&file_path, + LTTNG_PATH_MAX); + if (ret) { ret = -LTTNG_ERR_NOMEM; goto end; } - file_path = zmalloc(PATH_MAX); - if (!file_path) { + ret = lttng_dynamic_buffer_append(&file_path, path, path_len); + if (ret) { ret = -LTTNG_ERR_NOMEM; - free(entry); goto end; } - strncpy(file_path, path, path_len); - if (file_path[path_len - 1] != '/') { - file_path[path_len++] = '/'; + if (file_path.data[file_path.size - 1] != '/') { + ret = lttng_dynamic_buffer_append(&file_path, "/", 1); + if (ret) { + ret = -LTTNG_ERR_NOMEM; + goto end; + } } + file_path_root_len = file_path.size; - ret = 0; /* Search for *.lttng files */ - while (!readdir_r(directory, entry, &result) && result) { - size_t file_name_len = strlen(result->d_name); + for (;;) { + size_t file_name_len; + struct dirent *result; + + /* + * When the end of the directory stream is reached, NULL + * is returned and errno is kept unchanged. When an + * error occurs, NULL is returned and errno is set + * accordingly. To distinguish between the two, set + * errno to zero before calling readdir(). + * + * On success, readdir() returns a pointer to a dirent + * structure. This structure may be statically + * allocated, do not attempt to free(3) it. + */ + errno = 0; + result = readdir(directory); + + /* Reached end of dir stream or error out. */ + if (!result) { + if (errno) { + PERROR("Failed to enumerate the contents of path \"%s\" while loading session, readdir returned", path); + ret = -LTTNG_ERR_LOAD_IO_FAIL; + goto end; + } + break; + } + + file_name_len = strlen(result->d_name); if (file_name_len <= sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION)) { continue; } - if (path_len + file_name_len >= PATH_MAX) { + if (file_path.size + file_name_len >= LTTNG_PATH_MAX) { + WARN("Ignoring file \"%s\" since the path's length (%zu) would exceed the maximal permitted size (%d)", + result->d_name, + /* +1 to account for NULL terminator. */ + file_path.size + file_name_len + 1, + LTTNG_PATH_MAX); continue; } + /* Does the file end with .lttng? */ if (strcmp(DEFAULT_SESSION_CONFIG_FILE_EXTENSION, - result->d_name + file_name_len - sizeof( - DEFAULT_SESSION_CONFIG_FILE_EXTENSION) + 1)) { + result->d_name + file_name_len - sizeof( + DEFAULT_SESSION_CONFIG_FILE_EXTENSION) + 1)) { continue; } - strncpy(file_path + path_len, result->d_name, file_name_len); - file_path[path_len + file_name_len] = '\0'; + ret = lttng_dynamic_buffer_append(&file_path, result->d_name, + file_name_len + 1); + if (ret) { + ret = -LTTNG_ERR_NOMEM; + goto end; + } - ret = load_session_from_file(file_path, session_name, + ret = load_session_from_file(file_path.data, session_name, validation_ctx, overwrite, overrides); if (session_name && !ret) { session_found = 1; break; } + /* + * Reset the buffer's size to the location of the + * path's trailing '/'. + */ + ret = lttng_dynamic_buffer_set_size(&file_path, + file_path_root_len); + if (ret) { + ret = -LTTNG_ERR_UNK; + goto end; + } } - free(entry); - free(file_path); } else { ret = load_session_from_file(path, session_name, validation_ctx, overwrite, overrides); @@ -3019,11 +3106,10 @@ end: PERROR("closedir"); } } - if (session_found && !ret) { ret = 0; } - + lttng_dynamic_buffer_reset(&file_path); return ret; }