#include <config.h>
#include <lttng-consumerd.h>
+#include <lttng-ht.h>
#include <lttng-sessiond-comm.h>
#include <lttng/lttng-consumer.h>
#include <lttngerr.h>
+#include "common/runas.h"
#include "channel.h"
#include "compat/poll.h"
#include "context.h"
#include "event.h"
#include "futex.h"
-#include "hashtable.h"
#include "kernel.h"
#include "lttng-sessiond.h"
#include "shm.h"
int ust_consumerd64_fd = -1;
int ust_consumerd32_fd = -1;
-static const char *consumerd32_bin =
- __stringify(CONFIG_CONSUMERD32_BIN);
-static const char *consumerd64_bin =
- __stringify(CONFIG_CONSUMERD64_BIN);
-static const char *consumerd32_libdir =
- __stringify(CONFIG_CONSUMERD32_LIBDIR);
-static const char *consumerd64_libdir =
- __stringify(CONFIG_CONSUMERD64_LIBDIR);
+static const char *consumerd32_bin = CONFIG_CONSUMERD32_BIN;
+static const char *consumerd64_bin = CONFIG_CONSUMERD64_BIN;
+static const char *consumerd32_libdir = CONFIG_CONSUMERD32_LIBDIR;
+static const char *consumerd64_libdir = CONFIG_CONSUMERD64_LIBDIR;
static
void setup_consumerd_path(void)
* Send all stream fds of kernel channel to the consumer.
*/
static int send_kconsumer_channel_streams(struct consumer_data *consumer_data,
- int sock, struct ltt_kernel_channel *channel)
+ int sock, struct ltt_kernel_channel *channel,
+ uid_t uid, gid_t gid)
{
int ret;
struct ltt_kernel_stream *stream;
lkm.u.stream.state = stream->state;
lkm.u.stream.output = channel->channel->attr.output;
lkm.u.stream.mmap_len = 0; /* for kernel */
+ lkm.u.stream.uid = uid;
+ lkm.u.stream.gid = gid;
strncpy(lkm.u.stream.path_name, stream->pathname, PATH_MAX - 1);
lkm.u.stream.path_name[PATH_MAX - 1] = '\0';
DBG("Sending stream %d to consumer", lkm.u.stream.stream_key);
lkm.u.stream.state = LTTNG_CONSUMER_ACTIVE_STREAM;
lkm.u.stream.output = DEFAULT_KERNEL_CHANNEL_OUTPUT;
lkm.u.stream.mmap_len = 0; /* for kernel */
+ lkm.u.stream.uid = session->uid;
+ lkm.u.stream.gid = session->gid;
strncpy(lkm.u.stream.path_name, session->metadata->pathname, PATH_MAX - 1);
lkm.u.stream.path_name[PATH_MAX - 1] = '\0';
DBG("Sending metadata stream %d to consumer", lkm.u.stream.stream_key);
}
cds_list_for_each_entry(chan, &session->channel_list.head, list) {
- ret = send_kconsumer_channel_streams(consumer_data, sock, chan);
+ ret = send_kconsumer_channel_streams(consumer_data, sock, chan,
+ session->uid, session->gid);
if (ret < 0) {
goto error;
}
*/
if (session->kernel_session->consumer_fds_sent == 1) {
ret = send_kconsumer_channel_streams(consumer_data,
- session->kernel_session->consumer_fd, channel);
+ session->kernel_session->consumer_fd, channel,
+ session->uid, session->gid);
if (ret < 0) {
goto error;
}
*/
update_ust_app(ust_cmd.sock);
- ret = ustctl_register_done(ust_cmd.sock);
+ ret = ust_app_register_done(ust_cmd.sock);
if (ret < 0) {
/*
* If the registration is not possible, we simply
/*
* Exec consumerd.
*/
- if (opt_verbose > 1 || opt_verbose_consumer) {
+ if (opt_verbose_consumer) {
verbosity = "--verbose";
} else {
verbosity = "--quiet";
* sessiond's installation directory, and
* fallback on the 32-bit one,
*/
+ DBG3("Looking for a kernel consumer at these locations:");
+ DBG3(" 1) %s", consumerd64_bin);
+ DBG3(" 2) %s/%s", INSTALL_BIN_PATH, CONSUMERD_FILE);
+ DBG3(" 3) %s", consumerd32_bin);
if (stat(consumerd64_bin, &st) == 0) {
+ DBG3("Found location #1");
consumer_to_use = consumerd64_bin;
} else if (stat(INSTALL_BIN_PATH "/" CONSUMERD_FILE, &st) == 0) {
+ DBG3("Found location #2");
consumer_to_use = INSTALL_BIN_PATH "/" CONSUMERD_FILE;
} else if (stat(consumerd32_bin, &st) == 0) {
+ DBG3("Found location #3");
consumer_to_use = consumerd32_bin;
} else {
+ DBG("Could not find any valid consumerd executable");
break;
}
DBG("Using kernel consumer at: %s", consumer_to_use);
int ret;
char *type = "debugfs";
- ret = mkdir_recursive(path, S_IRWXU | S_IRWXG, geteuid(), getegid());
+ ret = run_as_mkdir_recursive(path, S_IRWXU | S_IRWXG, geteuid(), getegid());
if (ret < 0) {
PERROR("Cannot create debugfs path");
goto error;
* Create an UST session and add it to the session ust list.
*/
static int create_ust_session(struct ltt_session *session,
- struct lttng_domain *domain, struct ucred *creds)
+ struct lttng_domain *domain)
{
- int ret;
- unsigned int sess_uid;
- gid_t gid;
struct ltt_ust_session *lus = NULL;
+ int ret;
switch (domain->type) {
case LTTNG_DOMAIN_UST:
DBG("Creating UST session");
- sess_uid = session->uid;
- lus = trace_ust_create_session(session->path, sess_uid, domain);
+ lus = trace_ust_create_session(session->path, session->id, domain);
if (lus == NULL) {
ret = LTTCOMM_UST_SESS_FAIL;
goto error;
}
- /*
- * Get the right group ID. To use the tracing group, the daemon must be
- * running with root credentials or else it's the user GID used.
- */
- gid = allowed_group();
- if (gid < 0 || !is_root) {
- gid = creds->gid;
- }
-
- ret = mkdir_recursive(lus->pathname, S_IRWXU | S_IRWXG, creds->uid, gid);
+ ret = run_as_mkdir_recursive(lus->pathname, S_IRWXU | S_IRWXG,
+ session->uid, session->gid);
if (ret < 0) {
if (ret != -EEXIST) {
ERR("Trace directory creation error");
ERR("Unknown UST domain on create session %d", domain->type);
goto error;
}
+ lus->uid = session->uid;
+ lus->gid = session->gid;
session->ust_session = lus;
return LTTCOMM_OK;
/*
* Create a kernel tracer session then create the default channel.
*/
-static int create_kernel_session(struct ltt_session *session,
- struct ucred *creds)
+static int create_kernel_session(struct ltt_session *session)
{
int ret;
- gid_t gid;
DBG("Creating kernel session");
session->kernel_session->consumer_fd = kconsumer_data.cmd_sock;
}
- gid = allowed_group();
- if (gid < 0) {
- /*
- * Use GID 0 has a fallback since kernel session is only allowed under
- * root or the gid of the calling user
- */
- is_root ? (gid = 0) : (gid = creds->gid);
- }
-
- ret = mkdir_recursive(session->kernel_session->trace_path,
- S_IRWXU | S_IRWXG, creds->uid, gid);
+ ret = run_as_mkdir_recursive(session->kernel_session->trace_path,
+ S_IRWXU | S_IRWXG, session->uid, session->gid);
if (ret < 0) {
if (ret != -EEXIST) {
ERR("Trace directory creation error");
goto error;
}
}
+ session->kernel_session->uid = session->uid;
+ session->kernel_session->gid = session->gid;
error:
return ret;
}
+/*
+ * Check if the UID or GID match the session. Root user has access to
+ * all sessions.
+ */
+static int session_access_ok(struct ltt_session *session,
+ uid_t uid, gid_t gid)
+{
+ if (uid != session->uid && gid != session->gid
+ && uid != 0) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+static unsigned int lttng_sessions_count(uid_t uid, gid_t gid)
+{
+ unsigned int i = 0;
+ struct ltt_session *session;
+
+ DBG("Counting number of available session for UID %d GID %d",
+ uid, gid);
+ cds_list_for_each_entry(session, &session_list_ptr->head, list) {
+ /*
+ * Only list the sessions the user can control.
+ */
+ if (!session_access_ok(session, uid, gid)) {
+ continue;
+ }
+ i++;
+ }
+ return i;
+}
+
/*
* Using the session list, filled a lttng_session array to send back to the
* client for session listing.
* The session list lock MUST be acquired before calling this function. Use
* session_lock_list() and session_unlock_list().
*/
-static void list_lttng_sessions(struct lttng_session *sessions)
+static void list_lttng_sessions(struct lttng_session *sessions,
+ uid_t uid, gid_t gid)
{
- int i = 0;
+ unsigned int i = 0;
struct ltt_session *session;
- DBG("Getting all available session");
+ DBG("Getting all available session for UID %d GID %d",
+ uid, gid);
/*
* Iterate over session list and append data after the control struct in
* the buffer.
*/
cds_list_for_each_entry(session, &session_list_ptr->head, list) {
+ /*
+ * Only list the sessions the user can control.
+ */
+ if (!session_access_ok(session, uid, gid)) {
+ continue;
+ }
strncpy(sessions[i].path, session->path, PATH_MAX);
sessions[i].path[PATH_MAX - 1] = '\0';
strncpy(sessions[i].name, session->name, NAME_MAX);
break;
case LTTNG_DOMAIN_UST:
{
- struct cds_lfht_iter iter;
+ struct lttng_ht_iter iter;
struct ltt_ust_channel *uchan;
- cds_lfht_for_each_entry(session->ust_session->domain_global.channels,
- &iter, uchan, node) {
+ cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
+ &iter.iter, uchan, node.node) {
strncpy(channels[i].name, uchan->name, LTTNG_SYMBOL_NAME_LEN);
channels[i].attr.overwrite = uchan->attr.overwrite;
channels[i].attr.subbuf_size = uchan->attr.subbuf_size;
{
int i = 0, ret = 0;
unsigned int nb_event = 0;
- struct cds_lfht_iter iter;
- struct cds_lfht_node *node;
+ struct lttng_ht_iter iter;
+ struct lttng_ht_node_str *node;
struct ltt_ust_channel *uchan;
struct ltt_ust_event *uevent;
struct lttng_event *tmp;
rcu_read_lock();
- node = hashtable_lookup(ust_global->channels, (void *) channel_name,
- strlen(channel_name), &iter);
+ lttng_ht_lookup(ust_global->channels, (void *)channel_name, &iter);
+ node = lttng_ht_iter_get_node_str(&iter);
if (node == NULL) {
ret = -LTTCOMM_UST_CHAN_NOT_FOUND;
goto error;
}
- uchan = caa_container_of(node, struct ltt_ust_channel, node);
+ uchan = caa_container_of(&node->node, struct ltt_ust_channel, node.node);
- nb_event += hashtable_get_count(uchan->events);
+ nb_event += lttng_ht_get_count(uchan->events);
if (nb_event == 0) {
ret = nb_event;
goto error;
}
- cds_lfht_for_each_entry(uchan->events, &iter, uevent, node) {
+ cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent, node.node) {
strncpy(tmp[i].name, uevent->attr.name, LTTNG_SYMBOL_NAME_LEN);
tmp[i].name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
tmp[i].enabled = uevent->enabled;
case LTTNG_DOMAIN_UST:
{
struct ltt_ust_channel *uchan;
- struct cds_lfht *chan_ht;
+ struct lttng_ht *chan_ht;
chan_ht = usess->domain_global.channels;
{
int ret;
struct ltt_ust_session *usess = session->ust_session;
- struct cds_lfht *chan_ht;
+ struct lttng_ht *chan_ht;
DBG("Enabling channel %s for session %s", attr->name, session->name);
}
/* At this point, the session and channel exist on the tracer */
-
ret = event_ust_enable_tracepoint(usess, domain, uchan, event);
if (ret != LTTCOMM_OK) {
goto error;
usess = session->ust_session;
if (!session->enabled) {
- ret = LTTCOMM_UST_START_FAIL;
+ ret = LTTCOMM_UST_STOP_FAIL;
goto error;
}
ret = ust_app_stop_trace_all(usess);
if (ret < 0) {
- ret = LTTCOMM_UST_START_FAIL;
+ ret = LTTCOMM_UST_STOP_FAIL;
goto error;
}
}
/*
* Command LTTNG_CREATE_SESSION processed by the client thread.
*/
-static int cmd_create_session(char *name, char *path)
+static int cmd_create_session(char *name, char *path, struct ucred *creds)
{
int ret;
- ret = session_create(name, path);
+ ret = session_create(name, path, creds->uid, creds->gid);
if (ret != LTTCOMM_OK) {
goto error;
}
break;
case LTTNG_DOMAIN_UST:
if (session->ust_session != NULL) {
- nb_chan = hashtable_get_count(
+ nb_chan = lttng_ht_get_count(
session->ust_session->domain_global.channels);
}
DBG3("Number of UST global channels %zd", nb_chan);
/* Need a session for kernel command */
if (need_tracing_session) {
if (cmd_ctx->session->kernel_session == NULL) {
- ret = create_kernel_session(cmd_ctx->session, &cmd_ctx->creds);
+ ret = create_kernel_session(cmd_ctx->session);
if (ret < 0) {
ret = LTTCOMM_KERN_SESS_FAIL;
goto error;
if (need_tracing_session) {
if (cmd_ctx->session->ust_session == NULL) {
ret = create_ust_session(cmd_ctx->session,
- &cmd_ctx->lsm->domain, &cmd_ctx->creds);
+ &cmd_ctx->lsm->domain);
if (ret != LTTCOMM_OK) {
goto error;
}
break;
}
+ /*
+ * Check that the UID or GID match that of the tracing session.
+ * The root user can interact with all sessions.
+ */
+ if (need_tracing_session) {
+ if (!session_access_ok(cmd_ctx->session,
+ cmd_ctx->creds.uid, cmd_ctx->creds.gid)) {
+ ret = LTTCOMM_EPERM;
+ goto error;
+ }
+ }
+
/* Process by command type */
switch (cmd_ctx->lsm->cmd_type) {
case LTTNG_ADD_CONTEXT:
case LTTNG_CREATE_SESSION:
{
ret = cmd_create_session(cmd_ctx->lsm->session.name,
- cmd_ctx->lsm->session.path);
+ cmd_ctx->lsm->session.path, &cmd_ctx->creds);
break;
}
case LTTNG_DESTROY_SESSION:
}
case LTTNG_LIST_SESSIONS:
{
- session_lock_list();
+ unsigned int nr_sessions;
- if (session_list_ptr->count == 0) {
+ session_lock_list();
+ nr_sessions = lttng_sessions_count(cmd_ctx->creds.uid, cmd_ctx->creds.gid);
+ if (nr_sessions == 0) {
ret = LTTCOMM_NO_SESSION;
session_unlock_list();
goto error;
}
-
- ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_session) *
- session_list_ptr->count);
+ ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_session) * nr_sessions);
if (ret < 0) {
session_unlock_list();
goto setup_error;
}
/* Filled the session array */
- list_lttng_sessions((struct lttng_session *)(cmd_ctx->llm->payload));
+ list_lttng_sessions((struct lttng_session *)(cmd_ctx->llm->payload),
+ cmd_ctx->creds.uid, cmd_ctx->creds.gid);
session_unlock_list();