uint32_t state; /* enum lttcomm_consumer_fd_state */
enum lttng_event_output output; /* use splice or mmap to consume this fd */
uint64_t mmap_len;
+ uid_t uid; /* User ID owning the session */
+ gid_t gid; /* Group ID owning the session */
char path_name[PATH_MAX];
} stream;
} u;
#include <limits.h>
#include <poll.h>
+#include <unistd.h>
#include <urcu/list.h>
#include <lttng/lttng.h>
struct lttng_ust_lib_ring_buffer *buf;
int cpu;
int hangup_flush_done;
+ /* UID/GID of the user owning the session to which stream belongs */
+ uid_t uid;
+ gid_t gid;
};
/*
enum lttng_consumer_stream_state state,
uint64_t mmap_len,
enum lttng_event_output output,
- const char *path_name);
+ const char *path_name,
+ uid_t uid,
+ gid_t gid);
extern int consumer_add_stream(struct lttng_consumer_stream *stream);
extern void consumer_del_stream(struct lttng_consumer_stream *stream);
extern void consumer_change_stream_state(int stream_key,
enum lttng_consumer_stream_state state,
uint64_t mmap_len,
enum lttng_event_output output,
- const char *path_name)
+ const char *path_name,
+ uid_t uid,
+ gid_t gid)
{
struct lttng_consumer_stream *stream;
int ret;
stream->mmap_len = mmap_len;
stream->mmap_base = NULL;
stream->output = output;
+ stream->uid = uid;
+ stream->gid = gid;
strncpy(stream->path_name, path_name, PATH_MAX - 1);
stream->path_name[PATH_MAX - 1] = '\0';
msg.u.stream.state,
msg.u.stream.mmap_len,
msg.u.stream.output,
- msg.u.stream.path_name);
+ msg.u.stream.path_name,
+ msg.u.stream.uid,
+ msg.u.stream.gid);
if (new_stream == NULL) {
lttng_consumer_send_error(ctx, CONSUMERD_OUTFD_ERROR);
goto end;
goto error;
}
stream->out_fd = ret;
+ ret = chown(stream->path_name, stream->uid, stream->gid);
+ if (ret < 0) {
+ ERR("Changing ownership of %s", stream->path_name);
+ perror("chown");
+ }
}
if (stream->output == LTTNG_EVENT_MMAP) {
msg.u.stream.state,
msg.u.stream.mmap_len,
msg.u.stream.output,
- msg.u.stream.path_name);
+ msg.u.stream.path_name,
+ msg.u.stream.uid,
+ msg.u.stream.gid);
if (new_stream == NULL) {
lttng_consumer_send_error(ctx, CONSUMERD_OUTFD_ERROR);
goto end;
goto error;
}
stream->out_fd = ret;
+ ret = chown(stream->path_name, stream->uid, stream->gid);
+ if (ret < 0) {
+ ERR("Changing ownership of %s", stream->path_name);
+ perror("chown");
+ }
}
/* we return 0 to let the library handle the FD internally */
* 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;
}
* 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;
- gid_t gid;
struct ltt_ust_session *lus = NULL;
+ int ret;
switch (domain->type) {
case LTTNG_DOMAIN_UST:
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 = 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);
+ 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;
/*
* 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;
}
/* 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;
}
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:
/*
* Create a brand new session and add it to the session list.
*/
-int session_create(char *name, char *path)
+int session_create(char *name, char *path, uid_t uid, gid_t gid)
{
int ret;
struct ltt_session *new_session;
/* Init lock */
pthread_mutex_init(&new_session->lock, NULL);
+ new_session->uid = uid;
+ new_session->gid = gid;
+
/* Add new session to the session list */
session_lock_list();
new_session->id = add_session_list(new_session);
session_unlock_list();
- DBG("Tracing session %s created in %s with ID %d", name, path, new_session->id);
+ DBG("Tracing session %s created in %s with ID %d by UID %d GID %d",
+ name, path, new_session->id,
+ new_session->uid, new_session->gid);
return LTTCOMM_OK;
#define _LTT_SESSION_H
#include <pthread.h>
+#include <unistd.h>
#include <urcu/list.h>
#include "trace-kernel.h"
struct cds_list_head list;
int enabled; /* enabled/started flag */
int id; /* session unique identifier */
+ /* UID/GID of the user owning the session */
+ uid_t uid;
+ gid_t gid;
};
/* Prototypes */
-int session_create(char *name, char *path);
+int session_create(char *name, char *path, uid_t uid, gid_t gid);
int session_destroy(struct ltt_session *session);
void session_lock(struct ltt_session *session);
char *trace_path;
struct ltt_kernel_metadata *metadata;
struct ltt_kernel_channel_list channel_list;
+ /* UID/GID of the user owning the session */
+ uid_t uid;
+ gid_t gid;
};
/*
*/
struct cds_lfht *domain_pid;
struct cds_lfht *domain_exec;
+ /* UID/GID of the user owning the session */
+ uid_t uid;
+ gid_t gid;
};
#ifdef HAVE_LIBLTTNG_UST_CTL
DBG2("Shadow copy of session handle %d", ua_sess->handle);
ua_sess->id = usess->id;
+ ua_sess->uid = usess->uid;
+ ua_sess->gid = usess->gid;
ret = snprintf(ua_sess->path, PATH_MAX,
"%s/%s-%d-%s",
PERROR("mkdir UST metadata");
goto error;
}
+ ret = chown(ua_sess->path, ua_sess->uid, ua_sess->gid);
+ if (ret < 0) {
+ ERR("Unable to change owner of %s", ua_sess->path);
+ perror("chown");
+ }
umask(old_umask);
ret = snprintf(ua_sess->metadata->pathname, PATH_MAX,
struct ltt_ust_metadata *metadata;
struct cds_lfht *channels; /* Registered channels */
struct cds_lfht_node node;
+ /* UID/GID of the user owning the session */
+ uid_t uid;
+ gid_t gid;
char path[PATH_MAX];
};
* Send all stream fds of UST channel to the consumer.
*/
static int send_channel_streams(int sock,
- struct ust_app_channel *uchan)
+ struct ust_app_channel *uchan,
+ uid_t uid, gid_t gid)
{
int ret, fd;
struct lttcomm_consumer_msg lum;
*/
lum.u.stream.output = DEFAULT_UST_CHANNEL_OUTPUT;
lum.u.stream.mmap_len = stream->obj->memory_map_size;
+ lum.u.stream.uid = uid;
+ lum.u.stream.gid = gid;
strncpy(lum.u.stream.path_name, stream->pathname, PATH_MAX - 1);
lum.u.stream.path_name[PATH_MAX - 1] = '\0';
DBG("Sending stream %d to consumer", lum.u.stream.stream_key);
lum.u.stream.state = LTTNG_CONSUMER_ACTIVE_STREAM;
lum.u.stream.output = DEFAULT_UST_CHANNEL_OUTPUT;
lum.u.stream.mmap_len = usess->metadata->stream_obj->memory_map_size;
+ lum.u.stream.uid = usess->uid;
+ lum.u.stream.gid = usess->gid;
strncpy(lum.u.stream.path_name, usess->metadata->pathname, PATH_MAX - 1);
lum.u.stream.path_name[PATH_MAX - 1] = '\0';
DBG("Sending metadata stream %d to consumer", lum.u.stream.stream_key);
while ((node = hashtable_iter_get_node(&iter)) != NULL) {
uchan = caa_container_of(node, struct ust_app_channel, node);
- ret = send_channel_streams(sock, uchan);
+ ret = send_channel_streams(sock, uchan, usess->uid,
+ usess->gid);
if (ret < 0) {
rcu_read_unlock();
goto error;
#include <string.h>
#include <unistd.h>
#include <time.h>
+#include <sys/types.h>
#include <lttng-sessiond-comm.h>
{
int ret;
- ret = session_create(name, path);
+ ret = session_create(name, path, geteuid(), getegid());
if (ret == LTTCOMM_OK) {
/* Validate */
ret = find_session_name(name);