trace_path is leaked in some error paths of ust_app_snapshot_record().
Lift trace_path to the function's scope and free it whenever it is not
NULL. This is not clean, but this function should be cleaned-up in a
separate patch.
Moreover, this fixes a use after free in the PER_PID-case as
trace_path is free'd when a channel is not found.
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
enum lttng_error_code status = LTTNG_OK;
struct lttng_ht_iter iter;
struct ust_app *app;
enum lttng_error_code status = LTTNG_OK;
struct lttng_ht_iter iter;
struct ust_app *app;
+ char *trace_path = NULL;
assert(usess);
assert(output);
assert(usess);
assert(output);
cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
struct buffer_reg_channel *reg_chan;
struct consumer_socket *socket;
cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
struct buffer_reg_channel *reg_chan;
struct consumer_socket *socket;
- char *trace_path = NULL;
char pathname[PATH_MAX];
if (!reg->registry->reg.ust->metadata_key) {
char pathname[PATH_MAX];
if (!reg->registry->reg.ust->metadata_key) {
status = LTTNG_ERR_INVALID;
goto error;
}
status = LTTNG_ERR_INVALID;
goto error;
}
+ /* Free path allowed on previous iteration. */
+ free(trace_path);
trace_path = setup_channel_trace_path(usess->consumer, pathname);
if (!trace_path) {
status = LTTNG_ERR_INVALID;
trace_path = setup_channel_trace_path(usess->consumer, pathname);
if (!trace_path) {
status = LTTNG_ERR_INVALID;
usess->gid, trace_path, wait,
nb_packets_per_stream);
if (status != LTTNG_OK) {
usess->gid, trace_path, wait,
nb_packets_per_stream);
if (status != LTTNG_OK) {
goto error;
}
}
status = consumer_snapshot_channel(socket,
reg->registry->reg.ust->metadata_key, output, 1,
usess->uid, usess->gid, trace_path, wait, 0);
goto error;
}
}
status = consumer_snapshot_channel(socket,
reg->registry->reg.ust->metadata_key, output, 1,
usess->uid, usess->gid, trace_path, wait, 0);
if (status != LTTNG_OK) {
goto error;
}
if (status != LTTNG_OK) {
goto error;
}
struct ust_app_channel *ua_chan;
struct ust_app_session *ua_sess;
struct ust_registry_session *registry;
struct ust_app_channel *ua_chan;
struct ust_app_session *ua_sess;
struct ust_registry_session *registry;
- char *trace_path = NULL;
char pathname[PATH_MAX];
ua_sess = lookup_session_by_app(usess, app);
char pathname[PATH_MAX];
ua_sess = lookup_session_by_app(usess, app);
PERROR("snprintf snapshot path");
goto error;
}
PERROR("snprintf snapshot path");
goto error;
}
+ /* Free path allowed on previous iteration. */
+ free(trace_path);
trace_path = setup_channel_trace_path(usess->consumer, pathname);
if (!trace_path) {
status = LTTNG_ERR_INVALID;
trace_path = setup_channel_trace_path(usess->consumer, pathname);
if (!trace_path) {
status = LTTNG_ERR_INVALID;
case LTTNG_OK:
break;
case LTTNG_ERR_CHAN_NOT_FOUND:
case LTTNG_OK:
break;
case LTTNG_ERR_CHAN_NOT_FOUND:
ua_sess->effective_credentials.uid,
ua_sess->effective_credentials.gid,
trace_path, wait, 0);
ua_sess->effective_credentials.uid,
ua_sess->effective_credentials.gid,
trace_path, wait, 0);
switch (status) {
case LTTNG_OK:
break;
switch (status) {
case LTTNG_OK:
break;
rcu_read_unlock();
return status;
}
rcu_read_unlock();
return status;
}