Move file creation/unlink from liblttng-ust-ctl to consumerd
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 16 Dec 2014 01:24:46 +0000 (20:24 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 26 Mar 2015 22:07:38 +0000 (18:07 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/bin/lttng-sessiond/ust-registry.c
src/bin/lttng-sessiond/ust-registry.h
src/common/consumer.h
src/common/runas.c
src/common/runas.h
src/common/ust-consumer/ust-consumer.c

index f9ddd25a5928e197d15834446fa9710ec665a44b..2ba41ed45dffbb91d272c4561dcf040290f6ed58 100644 (file)
@@ -572,6 +572,8 @@ int ust_registry_session_init(struct ust_registry_session **sessionp,
        session->long_alignment = long_alignment;
        session->byte_order = byte_order;
        session->metadata_fd = -1;
+       session->uid = euid;
+       session->gid = egid;
        strncpy(session->root_shm_path, root_shm_path,
                sizeof(session->root_shm_path));
        session->root_shm_path[sizeof(session->root_shm_path) - 1] = '\0';
@@ -591,16 +593,18 @@ int ust_registry_session_init(struct ust_registry_session **sessionp,
                        S_IRWXU | S_IRWXG,
                        euid, egid);
                if (ret) {
+                       errno = -ret;
                        PERROR("run_as_mkdir_recursive");
                        goto error;
                }
        }
        if (session->metadata_path[0]) {
                /* Create metadata file */
-               ret = open(session->metadata_path,
+               ret = run_as_open(session->metadata_path,
                        O_WRONLY | O_CREAT | O_EXCL,
-                       S_IRUSR | S_IWUSR);
+                       S_IRUSR | S_IWUSR, euid, egid);
                if (ret < 0) {
+                       errno = -ret;
                        PERROR("Opening metadata file");
                        goto error;
                }
@@ -675,7 +679,8 @@ void ust_registry_session_destroy(struct ust_registry_session *reg)
                if (ret) {
                        PERROR("close");
                }
-               ret = unlink(reg->metadata_path);
+               ret = run_as_unlink(reg->metadata_path,
+                               reg->uid, reg->gid);
                if (ret) {
                        PERROR("unlink");
                }
@@ -684,6 +689,7 @@ void ust_registry_session_destroy(struct ust_registry_session *reg)
                /*
                 * Try deleting the directory hierarchy.
                 */
-               (void) utils_recursive_rmdir(reg->root_shm_path);
+               (void) run_as_recursive_rmdir(reg->root_shm_path,
+                               reg->uid, reg->gid);
        }
 }
index 91a0534e9a8cbde5084878d45125da310589644a..77d4d919518fa1a9cb2eb71eabd4f0ed85e9d108 100644 (file)
@@ -87,6 +87,10 @@ struct ust_registry_session {
         * deletes its sessions.
         */
        unsigned int metadata_closed;
+
+       /* User and group owning the session. */
+       uid_t uid;
+       gid_t gid;
 };
 
 struct ust_registry_channel {
index 7f885370e33127448edcc3cf623346d3ce1642f9..509e24e01af7bb391ba2ddaeb207b90688be6313 100644 (file)
@@ -207,6 +207,8 @@ struct lttng_consumer_channel {
        /* Timer value in usec for live streaming. */
        unsigned int live_timer_interval;
 
+       int *stream_fds;
+       int nr_stream_fds;
        char root_shm_path[PATH_MAX];
        char shm_path[PATH_MAX];
 };
index 471bb22046c3d3bf9f44dbf24c176f089a3e3c2e..9d9091638a5a9910c8cec2b6810357ca087e4499 100644 (file)
@@ -79,6 +79,14 @@ struct run_as_open_data {
        mode_t mode;
 };
 
+struct run_as_unlink_data {
+       const char *path;
+};
+
+struct run_as_recursive_rmdir_data {
+       const char *path;
+};
+
 #ifdef VALGRIND
 static
 int use_clone(void)
@@ -130,6 +138,34 @@ int _open(void *_data)
        return open(data->path, data->flags, data->mode);
 }
 
+static
+int _unlink(void *_data)
+{
+       int ret;
+       struct run_as_unlink_data *data = _data;
+
+       ret = unlink(data->path);
+       if (ret < 0) {
+               ret = -errno;
+       }
+
+       return ret;
+}
+
+static
+int _recursive_rmdir(void *_data)
+{
+       int ret;
+       struct run_as_recursive_rmdir_data *data = _data;
+
+       ret = utils_recursive_rmdir(data->path);
+       if (ret < 0) {
+               ret = -errno;
+       }
+
+       return ret;
+}
+
 static
 int child_run_as(void *_data)
 {
@@ -341,3 +377,25 @@ int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid)
        data.mode = mode;
        return run_as(_open, &data, uid, gid);
 }
+
+LTTNG_HIDDEN
+int run_as_unlink(const char *path, uid_t uid, gid_t gid)
+{
+       struct run_as_unlink_data data;
+
+       DBG3("unlink() %s with for uid %d and gid %d",
+                       path, uid, gid);
+       data.path = path;
+       return run_as(_unlink, &data, uid, gid);
+}
+
+LTTNG_HIDDEN
+int run_as_recursive_rmdir(const char *path, uid_t uid, gid_t gid)
+{
+       struct run_as_recursive_rmdir_data data;
+
+       DBG3("recursive_rmdir() %s with for uid %d and gid %d",
+                       path, uid, gid);
+       data.path = path;
+       return run_as(_recursive_rmdir, &data, uid, gid);
+}
index 9840eb056942ad7eb56fb83ee8a3aef4c29d49e4..dc25322ccabd0f4dd7aaf05b69e14ca16f09461b 100644 (file)
@@ -25,6 +25,8 @@
 int run_as_mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid);
 int run_as_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid);
 int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid);
+int run_as_unlink(const char *path, uid_t uid, gid_t gid);
+int run_as_recursive_rmdir(const char *path, uid_t uid, gid_t gid);
 
 /*
  * We need to lock pthread exit, which deadlocks __nptl_setxid in the
index 6898bb115f0a41cfd783d42df6c4270a397d0369..fbc3bbb43d5e3d9164606676dc38875d05473823 100644 (file)
@@ -47,6 +47,8 @@
 
 #include "ust-consumer.h"
 
+#define UINT_MAX_STR_LEN 11    /* includes \0 */
+
 extern struct lttng_consumer_global_data consumer_data;
 extern int consumer_poll_timeout;
 extern volatile int consumer_quit;
@@ -81,10 +83,6 @@ static void destroy_channel(struct lttng_consumer_channel *channel)
        if (channel->uchan) {
                lttng_ustconsumer_del_channel(channel);
        }
-       /* Try to rmdir all directories under shm_path root. */
-       if (channel->root_shm_path[0]) {
-               (void) utils_recursive_rmdir(channel->root_shm_path);
-       }
        free(channel);
 }
 
@@ -246,6 +244,26 @@ error:
        return ret;
 }
 
+static
+int get_stream_shm_path(char *stream_shm_path, const char *shm_path, int cpu)
+{
+       char cpu_nr[UINT_MAX_STR_LEN];  /* unsigned int max len */
+       int ret;
+
+       strncpy(stream_shm_path, shm_path, PATH_MAX);
+       stream_shm_path[PATH_MAX - 1] = '\0';
+       ret = snprintf(cpu_nr, UINT_MAX_STR_LEN, "%u", cpu);
+       if (ret != 1) {
+               ret = -1;
+               goto end;
+       }
+       strncat(stream_shm_path, cpu_nr,
+               PATH_MAX - strlen(stream_shm_path) - 1);
+       ret = 0;
+end:
+       return ret;
+}
+
 /*
  * Create streams for the given channel using liblttng-ust-ctl.
  *
@@ -346,20 +364,87 @@ error_alloc:
        return ret;
 }
 
+/*
+ * create_posix_shm is never called concurrently within a process.
+ */
+static
+int create_posix_shm(void)
+{
+       char tmp_name[NAME_MAX];
+       int shmfd, ret;
+
+       ret = snprintf(tmp_name, NAME_MAX, "/ust-shm-consumer-%d", getpid());
+       if (ret < 0) {
+               PERROR("snprintf");
+               return -1;
+       }
+       /*
+        * Allocate shm, and immediately unlink its shm oject, keeping
+        * only the file descriptor as a reference to the object.
+        * We specifically do _not_ use the / at the beginning of the
+        * pathname so that some OS implementations can keep it local to
+        * the process (POSIX leaves this implementation-defined).
+        */
+       shmfd = shm_open(tmp_name, O_CREAT | O_EXCL | O_RDWR, 0700);
+       if (shmfd < 0) {
+               PERROR("shm_open");
+               goto error_shm_open;
+       }
+       ret = shm_unlink(tmp_name);
+       if (ret < 0 && errno != ENOENT) {
+               PERROR("shm_unlink");
+               goto error_shm_release;
+       }
+       return shmfd;
+
+error_shm_release:
+       ret = close(shmfd);
+       if (ret) {
+               PERROR("close");
+       }
+error_shm_open:
+       return -1;
+}
+
+static int open_ust_stream_fd(struct lttng_consumer_channel *channel,
+               struct ustctl_consumer_channel_attr *attr,
+               int cpu)
+{
+       char shm_path[PATH_MAX];
+       int ret;
+
+       if (!channel->shm_path[0]) {
+               return create_posix_shm();
+       }
+       ret = get_stream_shm_path(shm_path, channel->shm_path, cpu);
+       if (ret) {
+               goto error_shm_path;
+       }
+       return run_as_open(shm_path,
+               O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR,
+               channel->uid, channel->gid);
+
+error_shm_path:
+       return -1;
+}
+
 /*
  * Create an UST channel with the given attributes and send it to the session
  * daemon using the ust ctl API.
  *
  * Return 0 on success or else a negative value.
  */
-static int create_ust_channel(struct ustctl_consumer_channel_attr *attr,
-               struct ustctl_consumer_channel **chanp)
+static int create_ust_channel(struct lttng_consumer_channel *channel,
+               struct ustctl_consumer_channel_attr *attr,
+               struct ustctl_consumer_channel **ust_chanp)
 {
-       int ret;
-       struct ustctl_consumer_channel *channel;
+       int ret, nr_stream_fds, i, j;
+       int *stream_fds;
+       struct ustctl_consumer_channel *ust_channel;
 
+       assert(channel);
        assert(attr);
-       assert(chanp);
+       assert(ust_chanp);
 
        DBG3("Creating channel to ustctl with attr: [overwrite: %d, "
                        "subbuf_size: %" PRIu64 ", num_subbuf: %" PRIu64 ", "
@@ -368,17 +453,65 @@ static int create_ust_channel(struct ustctl_consumer_channel_attr *attr,
                        attr->num_subbuf, attr->switch_timer_interval,
                        attr->read_timer_interval, attr->output, attr->type);
 
-       channel = ustctl_create_channel(attr);
-       if (!channel) {
+       if (channel->type == CONSUMER_CHANNEL_TYPE_METADATA)
+               nr_stream_fds = 1;
+       else
+               nr_stream_fds = ustctl_get_nr_stream_per_channel();
+       stream_fds = zmalloc(nr_stream_fds * sizeof(*stream_fds));
+       if (!stream_fds) {
+               ret = -1;
+               goto error_alloc;
+       }
+       for (i = 0; i < nr_stream_fds; i++) {
+               stream_fds[i] = open_ust_stream_fd(channel, attr, i);
+               if (stream_fds[i] < 0) {
+                       ret = -1;
+                       goto error_open;
+               }
+       }
+       ust_channel = ustctl_create_channel(attr, stream_fds, nr_stream_fds);
+       if (!ust_channel) {
                ret = -1;
                goto error_create;
        }
-
-       *chanp = channel;
+       channel->nr_stream_fds = nr_stream_fds;
+       channel->stream_fds = stream_fds;
+       *ust_chanp = ust_channel;
 
        return 0;
 
 error_create:
+error_open:
+       for (j = i - 1; j >= 0; j--) {
+               int closeret;
+
+               closeret = close(stream_fds[j]);
+               if (closeret) {
+                       PERROR("close");
+               }
+               if (channel->shm_path[0]) {
+                       char shm_path[PATH_MAX];
+
+                       closeret = get_stream_shm_path(shm_path,
+                                       channel->shm_path, j);
+                       if (closeret) {
+                               ERR("Cannot get stream shm path");
+                       }
+                       closeret = run_as_unlink(shm_path,
+                                       channel->uid, channel->gid);
+                       if (closeret) {
+                               errno = -closeret;
+                               PERROR("unlink %s", shm_path);
+                       }
+               }
+       }
+       /* Try to rmdir all directories under shm_path root. */
+       if (channel->root_shm_path[0]) {
+               (void) run_as_recursive_rmdir(channel->root_shm_path,
+                               channel->uid, channel->gid);
+       }
+       free(stream_fds);
+error_alloc:
        return ret;
 }
 
@@ -532,7 +665,7 @@ static int ask_channel(struct lttng_consumer_local_data *ctx, int sock,
        channel->nb_init_stream_left = 0;
 
        /* The reply msg status is handled in the following call. */
-       ret = create_ust_channel(attr, &channel->uchan);
+       ret = create_ust_channel(channel, attr, &channel->uchan);
        if (ret < 0) {
                goto end;
        }
@@ -1238,9 +1371,6 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                attr.read_timer_interval = msg.u.ask_channel.read_timer_interval;
                attr.chan_id = msg.u.ask_channel.chan_id;
                memcpy(attr.uuid, msg.u.ask_channel.uuid, sizeof(attr.uuid));
-               strncpy(attr.shm_path, channel->shm_path,
-                       sizeof(attr.shm_path));
-               attr.shm_path[sizeof(attr.shm_path) - 1] = '\0';
 
                /* Match channel buffer type to the UST abi. */
                switch (msg.u.ask_channel.output) {
@@ -1675,6 +1805,8 @@ void lttng_ustconsumer_on_stream_hangup(struct lttng_consumer_stream *stream)
 
 void lttng_ustconsumer_del_channel(struct lttng_consumer_channel *chan)
 {
+       int i;
+
        assert(chan);
        assert(chan->uchan);
 
@@ -1683,9 +1815,32 @@ void lttng_ustconsumer_del_channel(struct lttng_consumer_channel *chan)
        }
        consumer_metadata_cache_destroy(chan);
        ustctl_destroy_channel(chan->uchan);
+       for (i = 0; i < chan->nr_stream_fds; i++) {
+               int ret;
+
+               ret = close(chan->stream_fds[i]);
+               if (ret) {
+                       PERROR("close");
+               }
+               if (chan->shm_path[0]) {
+                       char shm_path[PATH_MAX];
+
+                       ret = get_stream_shm_path(shm_path, chan->shm_path, i);
+                       if (ret) {
+                               ERR("Cannot get stream shm path");
+                       }
+                       ret = run_as_unlink(shm_path, chan->uid, chan->gid);
+                       if (ret) {
+                               errno = -ret;
+                               PERROR("unlink %s", shm_path);
+                       }
+               }
+       }
+       free(chan->stream_fds);
        /* Try to rmdir all directories under shm_path root. */
        if (chan->root_shm_path[0]) {
-               (void) utils_recursive_rmdir(chan->root_shm_path);
+               (void) run_as_recursive_rmdir(chan->root_shm_path,
+                               chan->uid, chan->gid);
        }
 }
 
This page took 0.045592 seconds and 4 git commands to generate.