From: Mathieu Desnoyers Date: Tue, 20 Dec 2011 20:19:01 +0000 (-0500) Subject: Create all trace directories and files with client user credentials X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=commitdiff_plain;h=6df2e2c977b698cc6b8f15c90b649516674028f9 Create all trace directories and files with client user credentials Keep the client user credentials that created a session along with the session. Use exactly those credentials to chown the created directories and files. Signed-off-by: Mathieu Desnoyers --- diff --git a/include/lttng-sessiond-comm.h b/include/lttng-sessiond-comm.h index 0fa6569da..c72a2471e 100644 --- a/include/lttng-sessiond-comm.h +++ b/include/lttng-sessiond-comm.h @@ -229,6 +229,8 @@ struct lttcomm_consumer_msg { 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; diff --git a/include/lttng/lttng-consumer.h b/include/lttng/lttng-consumer.h index e5672d7b7..81fd83e0f 100644 --- a/include/lttng/lttng-consumer.h +++ b/include/lttng/lttng-consumer.h @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -120,6 +121,9 @@ struct lttng_consumer_stream { 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; }; /* @@ -265,7 +269,9 @@ extern struct lttng_consumer_stream *consumer_allocate_stream( 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, diff --git a/liblttng-consumer/lttng-consumer.c b/liblttng-consumer/lttng-consumer.c index 893df7208..0811e68ca 100644 --- a/liblttng-consumer/lttng-consumer.c +++ b/liblttng-consumer/lttng-consumer.c @@ -174,7 +174,9 @@ struct lttng_consumer_stream *consumer_allocate_stream( 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; @@ -199,6 +201,8 @@ struct lttng_consumer_stream *consumer_allocate_stream( 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'; diff --git a/liblttng-kconsumer/lttng-kconsumer.c b/liblttng-kconsumer/lttng-kconsumer.c index e9861f20f..242047ef0 100644 --- a/liblttng-kconsumer/lttng-kconsumer.c +++ b/liblttng-kconsumer/lttng-kconsumer.c @@ -256,7 +256,9 @@ int lttng_kconsumer_recv_cmd(struct lttng_consumer_local_data *ctx, 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; @@ -401,6 +403,11 @@ int lttng_kconsumer_on_recv_stream(struct lttng_consumer_stream *stream) 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) { diff --git a/liblttng-ustconsumer/lttng-ustconsumer.c b/liblttng-ustconsumer/lttng-ustconsumer.c index 89dbefa36..efb6be424 100644 --- a/liblttng-ustconsumer/lttng-ustconsumer.c +++ b/liblttng-ustconsumer/lttng-ustconsumer.c @@ -215,7 +215,9 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx, 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; @@ -403,6 +405,11 @@ int lttng_ustconsumer_on_recv_stream(struct lttng_consumer_stream *stream) 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 */ diff --git a/lttng-sessiond/main.c b/lttng-sessiond/main.c index 759b276a6..fbf8d7975 100644 --- a/lttng-sessiond/main.c +++ b/lttng-sessiond/main.c @@ -512,7 +512,8 @@ static void clean_command_ctx(struct command_ctx **cmd_ctx) * 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; @@ -544,6 +545,8 @@ static int send_kconsumer_channel_streams(struct consumer_data *consumer_data, 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); @@ -605,6 +608,8 @@ static int send_kconsumer_session_streams(struct consumer_data *consumer_data, 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); @@ -621,7 +626,8 @@ static int send_kconsumer_session_streams(struct consumer_data *consumer_data, } 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; } @@ -777,7 +783,8 @@ static int update_kernel_stream(struct consumer_data *consumer_data, int fd) */ 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; } @@ -1871,11 +1878,10 @@ 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: @@ -1893,16 +1899,8 @@ static int create_ust_session(struct ltt_session *session, 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"); @@ -1920,6 +1918,8 @@ static int create_ust_session(struct ltt_session *session, 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; @@ -1932,11 +1932,9 @@ error: /* * 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"); @@ -1951,23 +1949,16 @@ static int create_kernel_session(struct ltt_session *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; @@ -2934,11 +2925,11 @@ 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; } @@ -3252,7 +3243,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) /* 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; @@ -3279,7 +3270,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) 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; } @@ -3421,7 +3412,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) 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: diff --git a/lttng-sessiond/session.c b/lttng-sessiond/session.c index 30ae681b3..7a580fdd9 100644 --- a/lttng-sessiond/session.c +++ b/lttng-sessiond/session.c @@ -164,7 +164,7 @@ int session_destroy(struct ltt_session *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; @@ -214,12 +214,17 @@ int session_create(char *name, char *path) /* 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; diff --git a/lttng-sessiond/session.h b/lttng-sessiond/session.h index fd164007f..6264e14ac 100644 --- a/lttng-sessiond/session.h +++ b/lttng-sessiond/session.h @@ -20,6 +20,7 @@ #define _LTT_SESSION_H #include +#include #include #include "trace-kernel.h" @@ -69,10 +70,13 @@ struct ltt_session { 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); diff --git a/lttng-sessiond/trace-kernel.h b/lttng-sessiond/trace-kernel.h index bcea65148..1057c1e07 100644 --- a/lttng-sessiond/trace-kernel.h +++ b/lttng-sessiond/trace-kernel.h @@ -97,6 +97,9 @@ struct ltt_kernel_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; }; /* diff --git a/lttng-sessiond/trace-ust.h b/lttng-sessiond/trace-ust.h index a2ed3cb91..5a6cade9a 100644 --- a/lttng-sessiond/trace-ust.h +++ b/lttng-sessiond/trace-ust.h @@ -110,6 +110,9 @@ struct ltt_ust_session { */ 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 diff --git a/lttng-sessiond/ust-app.c b/lttng-sessiond/ust-app.c index 1b5d6fbf1..77dcc71a6 100644 --- a/lttng-sessiond/ust-app.c +++ b/lttng-sessiond/ust-app.c @@ -770,6 +770,8 @@ static void shadow_copy_session(struct ust_app_session *ua_sess, 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", @@ -1197,6 +1199,11 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, 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, diff --git a/lttng-sessiond/ust-app.h b/lttng-sessiond/ust-app.h index 00a421864..0c753ab36 100644 --- a/lttng-sessiond/ust-app.h +++ b/lttng-sessiond/ust-app.h @@ -93,6 +93,9 @@ struct ust_app_session { 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]; }; diff --git a/lttng-sessiond/ust-consumer.c b/lttng-sessiond/ust-consumer.c index 8a2ba728d..b87d61120 100644 --- a/lttng-sessiond/ust-consumer.c +++ b/lttng-sessiond/ust-consumer.c @@ -34,7 +34,8 @@ * 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; @@ -84,6 +85,8 @@ static int send_channel_streams(int sock, */ 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); @@ -158,6 +161,8 @@ int ust_consumer_send_session(int consumer_fd, struct ust_app_session *usess) 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); @@ -181,7 +186,8 @@ int ust_consumer_send_session(int consumer_fd, struct ust_app_session *usess) 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; diff --git a/tests/test_sessions.c b/tests/test_sessions.c index 3e45c21b6..01a54b3ce 100644 --- a/tests/test_sessions.c +++ b/tests/test_sessions.c @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -118,7 +119,7 @@ static int create_one_session(char *name, char *path) { int ret; - ret = session_create(name, path); + ret = session_create(name, path, geteuid(), getegid()); if (ret == LTTCOMM_OK) { /* Validate */ ret = find_session_name(name);