librarize run_as
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 20 Dec 2011 23:01:10 +0000 (18:01 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 20 Dec 2011 23:01:10 +0000 (18:01 -0500)
still TODO: finish open_run_as -- need to pass the file descriptor back
to the parent. Currently using a racy open+fchown work-around.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
15 files changed:
Makefile.am
configure.ac
include/Makefile.am
include/runas.h [new file with mode: 0644]
liblttng-kconsumer/lttng-kconsumer.c
liblttng-ustconsumer/Makefile.am
liblttng-ustconsumer/lttng-ustconsumer.c
librunas/Makefile.am [new file with mode: 0644]
librunas/runas.c [new file with mode: 0644]
lttng-consumerd/Makefile.am
lttng-sessiond/Makefile.am
lttng-sessiond/main.c
lttng-sessiond/ust-app.c
lttng-sessiond/utils.c
lttng-sessiond/utils.h

index fa5beea9a9df6ddd0d5cdcdd4ee1d7ea0191cbb2..4d203b55ce6254f13e3715a79448ab77c89c1a98 100644 (file)
@@ -2,6 +2,7 @@ ACLOCAL_AMFLAGS = -I config
 
 SUBDIRS = liblttng-sessiond-comm \
                  libkernelctl \
+                 librunas \
                  liblttng-kconsumer \
                  liblttng-ustconsumer \
                  liblttng-consumer \
index 65b352c7d4205406dc7eea3eaf27a4da81aed3b6..1c4bc1620a362914e9f6b4f607447383186e6f36 100644 (file)
@@ -138,6 +138,7 @@ AC_CONFIG_FILES([
        liblttng-ustconsumer/Makefile
        liblttngctl/Makefile
        liblttng-sessiond-comm/Makefile
+       librunas/Makefile
        lttng-consumerd/Makefile
        lttng-sessiond/Makefile
        lttng/Makefile
index d53444f4e11d8de351d0ebb6ef72e8e8279af115..10caa69584506b06b049de4a3079e954ad7607d8 100644 (file)
@@ -2,4 +2,5 @@ lttnginclude_HEADERS = lttng/lttng.h lttng/lttng-kconsumer.h \
                        lttng/lttng-ustconsumer.h lttng/lttng-consumer.h
 
 noinst_HEADERS = lttngerr.h lttng-kernel.h lttng-consumerd.h lttng-share.h \
-                       lttng-sessiond-comm.h lttng-kernel-ctl.h
+                       lttng-sessiond-comm.h lttng-kernel-ctl.h \
+                       runas.h
diff --git a/include/runas.h b/include/runas.h
new file mode 100644 (file)
index 0000000..544653d
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef _RUNAS_H
+#define _RUNAS_H
+
+/*
+ * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *                      Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; only verion 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <unistd.h>
+
+int mkdir_recursive_run_as(const char *path, mode_t mode, uid_t uid, gid_t gid);
+int mkdir_run_as(const char *path, mode_t mode, uid_t uid, gid_t gid);
+int open_run_as(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid);
+
+#endif /* _RUNAS_H */
index 242047ef0237a9af9f6914a6a2cbc969bde2f1ed..388cc5b20f8f4e67853a01b4ee7038f8a398cf1f 100644 (file)
@@ -33,6 +33,7 @@
 #include <lttng-sessiond-comm.h>
 #include <lttng/lttng-kconsumer.h>
 #include <lttngerr.h>
+#include <runas.h>
 
 extern struct lttng_consumer_global_data consumer_data;
 extern int consumer_poll_timeout;
@@ -395,19 +396,16 @@ int lttng_kconsumer_on_recv_stream(struct lttng_consumer_stream *stream)
 
        /* Opening the tracefile in write mode */
        if (stream->path_name != NULL) {
-               ret = open(stream->path_name,
-                               O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU|S_IRWXG|S_IRWXO);
+               ret = open_run_as(stream->path_name,
+                               O_WRONLY|O_CREAT|O_TRUNC,
+                               S_IRWXU|S_IRWXG|S_IRWXO,
+                               stream->uid, stream->gid);
                if (ret < 0) {
                        ERR("Opening %s", stream->path_name);
                        perror("open");
                        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) {
index 284eccf97c4b4626df5488fe70044ade92898642..e01064fd74f7e7c7ecaa682a3c9764e2eb2fc0f7 100644 (file)
@@ -6,4 +6,5 @@ noinst_LTLIBRARIES = liblttng-ustconsumer.la
 liblttng_ustconsumer_la_SOURCES = lttng-ustconsumer.c
 
 liblttng_ustconsumer_la_LIBADD = -llttng-ust-ctl
+
 endif
index efb6be42490812d45f911b7f650254264efdc57f..26e680a9cd757d6bc5974dda20d6a30df3ccb9b2 100644 (file)
@@ -33,6 +33,7 @@
 #include <lttng/lttng-ustconsumer.h>
 #include <lttng/ust-ctl.h>
 #include <lttngerr.h>
+#include <runas.h>
 
 extern struct lttng_consumer_global_data consumer_data;
 extern int consumer_poll_timeout;
@@ -397,19 +398,16 @@ int lttng_ustconsumer_on_recv_stream(struct lttng_consumer_stream *stream)
 
        /* Opening the tracefile in write mode */
        if (stream->path_name != NULL) {
-               ret = open(stream->path_name,
-                               O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU|S_IRWXG|S_IRWXO);
+               ret = open_run_as(stream->path_name,
+                               O_WRONLY|O_CREAT|O_TRUNC,
+                               S_IRWXU|S_IRWXG|S_IRWXO,
+                               stream->uid, stream->gid);
                if (ret < 0) {
                        ERR("Opening %s", stream->path_name);
                        perror("open");
                        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/librunas/Makefile.am b/librunas/Makefile.am
new file mode 100644 (file)
index 0000000..92ec272
--- /dev/null
@@ -0,0 +1,5 @@
+AM_CPPFLAGS = -I$(top_srcdir)/include
+
+noinst_LTLIBRARIES = librunas.la
+
+librunas_la_SOURCES = runas.c
diff --git a/librunas/runas.c b/librunas/runas.c
new file mode 100644 (file)
index 0000000..24a772c
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *                      Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; only version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <lttngerr.h>
+
+struct mkdir_data {
+       const char *path;
+       mode_t mode;
+};
+
+struct open_data {
+       const char *path;
+       int flags;
+       mode_t mode;
+};
+
+/*
+ * Create recursively directory using the FULL path.
+ */
+static
+int _mkdir_recursive(void *_data)
+{
+       struct mkdir_data *data = _data;
+       const char *path;
+       char *p, tmp[PATH_MAX];
+       struct stat statbuf;
+       mode_t mode;
+       size_t len;
+       int ret;
+
+       path = data->path;
+       mode = data->mode;
+
+       ret = snprintf(tmp, sizeof(tmp), "%s", path);
+       if (ret < 0) {
+               PERROR("snprintf mkdir");
+               goto error;
+       }
+
+       len = ret;
+       if (tmp[len - 1] == '/') {
+               tmp[len - 1] = 0;
+       }
+
+       for (p = tmp + 1; *p; p++) {
+               if (*p == '/') {
+                       *p = 0;
+                       ret = stat(tmp, &statbuf);
+                       if (ret < 0) {
+                               ret = mkdir(tmp, mode);
+                               if (ret < 0) {
+                                       if (!(errno == EEXIST)) {
+                                               PERROR("mkdir recursive");
+                                               ret = -errno;
+                                               goto error;
+                                       }
+                               }
+                       }
+                       *p = '/';
+               }
+       }
+
+       ret = mkdir(tmp, mode);
+       if (ret < 0) {
+               if (!(errno == EEXIST)) {
+                       PERROR("mkdir recursive last piece");
+                       ret = -errno;
+               } else {
+                       ret = 0;
+               }
+       }
+
+error:
+       return ret;
+}
+
+static
+int _mkdir(void *_data)
+{
+       struct mkdir_data *data = _data;
+       return mkdir(data->path, data->mode);
+}
+
+static
+int _open(void *_data)
+{
+       struct open_data *data = _data;
+       return open(data->path, data->flags, data->mode);
+}
+
+static
+int run_as(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid)
+{
+       int ret = 0;
+       pid_t pid;
+
+       /*
+        * If we are non-root, we can only deal with our own uid.
+        */
+       if (geteuid() != 0) {
+               if (uid != geteuid()) {
+                       ERR("Client (%d)/Server (%d) UID mismatch (and sessiond is not root)",
+                               uid, geteuid());
+                       return -EPERM;
+               }
+               return (*cmd)(data);
+       }
+
+       pid = fork();
+       if (pid > 0) {
+               int status;
+               /*
+                * Parent: wait for child to return, in which case the
+                * shared memory map will have been created.
+                */
+               pid = wait(&status);
+               if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+                       ret = -1;
+                       goto end;
+               }
+               goto end;
+       } else if (pid == 0) {
+               /* Child */
+               setegid(gid);
+               if (ret < 0) {
+                       perror("setegid");
+                       exit(EXIT_FAILURE);
+               }
+               ret = seteuid(uid);
+               if (ret < 0) {
+                       perror("seteuid");
+                       exit(EXIT_FAILURE);
+               }
+               umask(0);
+               ret = (*cmd)(data);
+               if (!ret)
+                       exit(EXIT_SUCCESS);
+               else
+                       exit(EXIT_FAILURE);
+       } else {
+               return -1;
+       }
+end:
+       return ret;
+}
+
+int mkdir_recursive_run_as(const char *path, mode_t mode, uid_t uid, gid_t gid)
+{
+       struct mkdir_data data;
+
+       DBG3("mkdir() recursive %s with mode %d for uid %d and gid %d",
+                       path, mode, uid, gid);
+       data.path = path;
+       data.mode = mode;
+       return run_as(_mkdir_recursive, &data, uid, gid);
+}
+
+int mkdir_run_as(const char *path, mode_t mode, uid_t uid, gid_t gid)
+{
+       struct mkdir_data data;
+
+       DBG3("mkdir() %s with mode %d for uid %d and gid %d",
+                       path, mode, uid, gid);
+       data.path = path;
+       data.mode = mode;
+       return run_as(_mkdir, &data, uid, gid);
+}
+
+/*
+ * Note: open_run_as is currently not working. We'd need to pass the fd
+ * opened in the child to the parent.
+ */
+int open_run_as(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid)
+{
+       //struct open_data data;
+       int fd, ret;
+
+       DBG3("open() %s with flags %d mode %d for uid %d and gid %d",
+                       path, flags, mode, uid, gid);
+       fd = open(path, flags, mode);
+       if (fd < 0) {
+               perror("open");
+               return fd;
+       }
+       ret = fchown(fd, uid, gid);
+       if (ret < 0) {
+               perror("fchown");
+               close(fd);
+               return ret;
+       }
+       return fd;
+#if 0
+       data.path = path;
+       data.flags = flags;
+       data.mode = mode;
+       return run_as(_open, &data, uid, gid);
+#endif
+}
index 70ebc50356e67a072bbeafcdc0e2dfd73989f273..a808e3ca8631b76b28aad03c8e44288ec08b5b26 100644 (file)
@@ -7,7 +7,8 @@ lttng_consumerd_SOURCES = lttng-consumerd.c
 lttng_consumerd_LDADD = \
           $(top_builddir)/libkernelctl/libkernelctl.la \
           $(top_builddir)/liblttng-consumer/liblttng-consumer.la \
-          $(top_builddir)/liblttng-sessiond-comm/liblttng-sessiond-comm.la
+          $(top_builddir)/liblttng-sessiond-comm/liblttng-sessiond-comm.la \
+          $(top_builddir)/librunas/librunas.la
 
 if HAVE_LIBLTTNG_UST_CTL
 lttng_consumerd_LDADD += -llttng-ust-ctl
index 592d55a13320e41d5caaad17387d5e7e4a21ca9f..d3900d22d8cf4c1d49306fb8ea8ced1e51894544 100644 (file)
@@ -40,7 +40,8 @@ lttng_sessiond_SOURCES += lttng-sessiond.h main.c
 lttng_sessiond_LDADD = -lrt -lurcu-common -lurcu \
                 $(top_builddir)/liblttng-sessiond-comm/liblttng-sessiond-comm.la \
                 $(top_builddir)/libkernelctl/libkernelctl.la \
-                $(top_builddir)/liblttngctl/liblttngctl.la
+                $(top_builddir)/liblttngctl/liblttngctl.la \
+                $(top_builddir)/librunas/librunas.la
 
 if HAVE_LIBLTTNG_UST_CTL
 lttng_sessiond_LDADD += -llttng-ust-ctl
index 80505b3caf34fcc525a83b9fc2300638ef88f270..10139448aee3dcbe811c75adb3ca55a99c9b5d4d 100644 (file)
@@ -43,6 +43,7 @@
 #include <lttng/lttng-consumer.h>
 
 #include <lttngerr.h>
+#include <runas.h>
 
 #include "channel.h"
 #include "compat/poll.h"
index 09989ff49ea7af21f1cb116d62923e193043e2cb..384d85e23a07df05ee73b9fd8ab617aa5f4485aa 100644 (file)
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <runas.h>
 
 #include <urcu/compiler.h>
 #include <lttngerr.h>
 #include <lttng-share.h>
+#include <runas.h>
 
 #include "hashtable.h"
 #include "ust-app.h"
 #include "ust-consumer.h"
 #include "ust-ctl.h"
-#include "utils.h"
 
 /*
  * Delete ust context safely. RCU read lock must be held before calling
index 1e08de77d4ca2854611c6a7372a769a9c7bdeb5e..22a07ffaefd4174d7e2bb2cad1878eefd78d66b4 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <unistd.h>
-#include <fcntl.h>
 
 #include <lttngerr.h>
 
 #include "utils.h"
 
-struct mkdir_data {
-       const char *path;
-       mode_t mode;
-};
-
-struct open_data {
-       const char *path;
-       int flags;
-       mode_t mode;
-};
-
 /*
  * Write to writable pipe used to notify a thread.
  */
@@ -67,168 +52,3 @@ const char *get_home_dir(void)
 {
        return ((const char *) getenv("HOME"));
 }
-
-/*
- * Create recursively directory using the FULL path.
- */
-static
-int _mkdir_recursive(void *_data)
-{
-       struct mkdir_data *data = _data;
-       const char *path;
-       char *p, tmp[PATH_MAX];
-       struct stat statbuf;
-       mode_t mode;
-       size_t len;
-       int ret;
-
-       path = data->path;
-       mode = data->mode;
-
-       ret = snprintf(tmp, sizeof(tmp), "%s", path);
-       if (ret < 0) {
-               PERROR("snprintf mkdir");
-               goto error;
-       }
-
-       len = ret;
-       if (tmp[len - 1] == '/') {
-               tmp[len - 1] = 0;
-       }
-
-       for (p = tmp + 1; *p; p++) {
-               if (*p == '/') {
-                       *p = 0;
-                       ret = stat(tmp, &statbuf);
-                       if (ret < 0) {
-                               ret = mkdir(tmp, mode);
-                               if (ret < 0) {
-                                       if (!(errno == EEXIST)) {
-                                               PERROR("mkdir recursive");
-                                               ret = -errno;
-                                               goto error;
-                                       }
-                               }
-                       }
-                       *p = '/';
-               }
-       }
-
-       ret = mkdir(tmp, mode);
-       if (ret < 0) {
-               if (!(errno == EEXIST)) {
-                       PERROR("mkdir recursive last piece");
-                       ret = -errno;
-               } else {
-                       ret = 0;
-               }
-       }
-
-error:
-       return ret;
-}
-
-static
-int _mkdir(void *_data)
-{
-       struct mkdir_data *data = _data;
-       return mkdir(data->path, data->mode);
-}
-
-static
-int _open(void *_data)
-{
-       struct open_data *data = _data;
-       return open(data->path, data->flags, data->mode);
-}
-
-static
-int run_as(int (*cmd)(void *data), void *data, uid_t uid, gid_t gid)
-{
-       int ret = 0;
-       pid_t pid;
-
-       /*
-        * If we are non-root, we can only deal with our own uid.
-        */
-       if (geteuid() != 0) {
-               if (uid != geteuid()) {
-                       ERR("Client (%d)/Server (%d) UID mismatch (and sessiond is not root)",
-                               uid, geteuid());
-                       return -EPERM;
-               }
-               return (*cmd)(data);
-       }
-
-       pid = fork();
-       if (pid > 0) {
-               int status;
-
-               /*
-                * Parent: wait for child to return, in which case the
-                * shared memory map will have been created.
-                */
-               pid = wait(&status);
-               if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
-                       ret = -1;
-                       goto end;
-               }
-               goto end;
-       } else if (pid == 0) {
-               /* Child */
-               setegid(gid);
-               if (ret < 0) {
-                       perror("setegid");
-                       exit(EXIT_FAILURE);
-               }
-               ret = seteuid(uid);
-               if (ret < 0) {
-                       perror("seteuid");
-                       exit(EXIT_FAILURE);
-               }
-               umask(0);
-               ret = (*cmd)(data);
-               if (!ret)
-                       exit(EXIT_SUCCESS);
-               else
-                       exit(EXIT_FAILURE);
-       } else {
-               return -1;
-       }
-end:
-       return ret;
-}
-
-int mkdir_recursive_run_as(const char *path, mode_t mode, uid_t uid, gid_t gid)
-{
-       struct mkdir_data data;
-
-       DBG3("mkdir() recursive %s with mode %d for uid %d and gid %d",
-                       path, mode, uid, gid);
-       data.path = path;
-       data.mode = mode;
-       return run_as(_mkdir_recursive, &data, uid, gid);
-}
-
-int mkdir_run_as(const char *path, mode_t mode, uid_t uid, gid_t gid)
-{
-       struct mkdir_data data;
-
-       DBG3("mkdir() %s with mode %d for uid %d and gid %d",
-                       path, mode, uid, gid);
-       data.path = path;
-       data.mode = mode;
-       return run_as(_mkdir, &data, uid, gid);
-}
-
-int open_run_as(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid)
-{
-       struct open_data data;
-
-       DBG3("open() %s with flags %d mode %d for uid %d and gid %d",
-                       path, flags, mode, uid, gid);
-       data.path = path;
-       data.flags = flags;
-       data.mode = mode;
-       return run_as(_open, &data, uid, gid);
-}
index b6c57c7e266a8d897f8cfff1c41258098e71b368..7bcd1a87eb224f2eb654766f2f2b09bd6ea57510 100644 (file)
 #ifndef _LTT_UTILS_H
 #define _LTT_UTILS_H
 
-#include <unistd.h>
-
 #ifndef __stringify
 #define __stringify1(x)        #x
 #define __stringify(x) __stringify1(x)
 #endif
 
-int mkdir_recursive_run_as(const char *path, mode_t mode, uid_t uid, gid_t gid);
-int mkdir_run_as(const char *path, mode_t mode, uid_t uid, gid_t gid);
-int open_run_as(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid);
-
 const char *get_home_dir(void);
 int notify_thread_pipe(int wpipe);
 
This page took 0.051258 seconds and 4 git commands to generate.