Add file creation/unlinking utils to directory handle
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 9 May 2019 18:10:58 +0000 (14:10 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 18 Jul 2019 19:58:25 +0000 (15:58 -0400)
This commit adds file creation and unlinking functions to the
directory handle interface and corresponding run_as wrappers.

This allows the creation and unlinking of files relative to
an existing directory handle using either openat/unlinkat when
directory file descriptors are supported or open/unlink when
they are not.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/common/compat/directory-handle.c
src/common/compat/directory-handle.h
src/common/runas.c
src/common/runas.h

index 5bfdd699ddd175658dc731f1d07d9760601d5ded..80e9e118b8c46994751f8b7267d52f0718552f89 100644 (file)
 #include <fcntl.h>
 #include <unistd.h>
 
+/*
+ * This compatibility layer shares a common "base" that is implemented
+ * in terms of an internal API. This file contains two implementations
+ * of the internal API below.
+ */
 static
 int lttng_directory_handle_stat(const struct lttng_directory_handle *handle,
                const char *path, struct stat *st);
@@ -42,6 +47,20 @@ static
 int _run_as_mkdir_recursive(const struct lttng_directory_handle *handle,
                const char *path, mode_t mode, uid_t uid, gid_t gid);
 static
+int lttng_directory_handle_open(const struct lttng_directory_handle *handle,
+               const char *filename, int flags, mode_t mode);
+static
+int _run_as_open(const struct lttng_directory_handle *handle,
+               const char *filename,
+               int flags, mode_t mode, uid_t uid, gid_t gid);
+static
+int lttng_directory_handle_unlink(
+               const struct lttng_directory_handle *handle,
+               const char *filename);
+static
+int _run_as_unlink(const struct lttng_directory_handle *handle,
+               const char *filename, uid_t uid, gid_t gid);
+static
 void lttng_directory_handle_invalidate(struct lttng_directory_handle *handle);
 
 #ifdef COMPAT_DIRFD
@@ -151,8 +170,38 @@ int lttng_directory_handle_mkdir(
 }
 
 static
-int _run_as_mkdir(const struct lttng_directory_handle *handle, const char *path,
-               mode_t mode, uid_t uid, gid_t gid)
+int lttng_directory_handle_open(const struct lttng_directory_handle *handle,
+               const char *filename, int flags, mode_t mode)
+{
+       return openat(handle->dirfd, filename, flags, mode);
+}
+
+static
+int _run_as_open(const struct lttng_directory_handle *handle,
+               const char *filename,
+               int flags, mode_t mode, uid_t uid, gid_t gid)
+{
+       return run_as_openat(handle->dirfd, filename, flags, mode, uid, gid);
+}
+
+static
+int _run_as_unlink(const struct lttng_directory_handle *handle,
+               const char *filename, uid_t uid, gid_t gid)
+{
+       return run_as_unlinkat(handle->dirfd, filename, uid, gid);
+}
+
+static
+int lttng_directory_handle_unlink(
+               const struct lttng_directory_handle *handle,
+               const char *filename)
+{
+       return unlinkat(handle->dirfd, filename, 0);
+}
+
+static
+int _run_as_mkdir(const struct lttng_directory_handle *handle,
+               const char *path, mode_t mode, uid_t uid, gid_t gid)
 {
        return run_as_mkdirat(handle->dirfd, path, mode, uid, gid);
 }
@@ -386,6 +435,43 @@ end:
        return ret;
 }
 
+static
+int lttng_directory_handle_open(const struct lttng_directory_handle *handle,
+               const char *filename, int flags, mode_t mode)
+{
+       int ret;
+       char fullpath[LTTNG_PATH_MAX];
+
+       ret = get_full_path(handle, filename, fullpath, sizeof(fullpath));
+       if (ret) {
+               errno = ENOMEM;
+               goto end;
+       }
+
+       ret = open(fullpath, flags, mode);
+end:
+       return ret;
+}
+
+static
+int lttng_directory_handle_unlink(
+               const struct lttng_directory_handle *handle,
+               const char *filename)
+{
+       int ret;
+       char fullpath[LTTNG_PATH_MAX];
+
+       ret = get_full_path(handle, filename, fullpath, sizeof(fullpath));
+       if (ret) {
+               errno = ENOMEM;
+               goto end;
+       }
+
+       ret = unlink(fullpath);
+end:
+       return ret;
+}
+
 static
 int _run_as_mkdir(const struct lttng_directory_handle *handle, const char *path,
                mode_t mode, uid_t uid, gid_t gid)
@@ -404,6 +490,43 @@ end:
        return ret;
 }
 
+static
+int _run_as_open(const struct lttng_directory_handle *handle,
+               const char *filename,
+               int flags, mode_t mode, uid_t uid, gid_t gid)
+{
+       int ret;
+       char fullpath[LTTNG_PATH_MAX];
+
+       ret = get_full_path(handle, filename, fullpath, sizeof(fullpath));
+       if (ret) {
+               errno = ENOMEM;
+               goto end;
+       }
+
+       ret = run_as_open(fullpath, flags, mode, uid, gid);
+end:
+       return ret;
+}
+
+static
+int _run_as_unlink(const struct lttng_directory_handle *handle,
+               const char *filename, uid_t uid, gid_t gid)
+{
+       int ret;
+       char fullpath[LTTNG_PATH_MAX];
+
+       ret = get_full_path(handle, filename, fullpath, sizeof(fullpath));
+       if (ret) {
+               errno = ENOMEM;
+               goto end;
+       }
+
+       ret = run_as_unlink(fullpath, uid, gid);
+end:
+       return ret;
+}
+
 static
 int _run_as_mkdir_recursive(const struct lttng_directory_handle *handle,
                const char *path, mode_t mode, uid_t uid, gid_t gid)
@@ -587,3 +710,59 @@ int lttng_directory_handle_create_subdirectory_recursive(
        return lttng_directory_handle_create_subdirectory_recursive_as_user(
                        handle, subdirectory_path, mode, NULL);
 }
+
+LTTNG_HIDDEN
+int lttng_directory_handle_open_file_as_user(
+               const struct lttng_directory_handle *handle,
+               const char *filename,
+               int flags, mode_t mode,
+               const struct lttng_credentials *creds)
+{
+       int ret;
+
+       if (!creds) {
+               /* Run as current user. */
+               ret = lttng_directory_handle_open(handle, filename, flags,
+                               mode);
+       } else {
+               ret = _run_as_open(handle, filename, flags, mode,
+                               creds->uid, creds->gid);
+       }
+       return ret;
+}
+
+LTTNG_HIDDEN
+int lttng_directory_handle_open_file(
+               const struct lttng_directory_handle *handle,
+               const char *filename,
+               int flags, mode_t mode)
+{
+       return lttng_directory_handle_open_file_as_user(handle, filename, flags,
+                       mode, NULL);
+}
+
+LTTNG_HIDDEN
+int lttng_directory_handle_unlink_file_as_user(
+               const struct lttng_directory_handle *handle,
+               const char *filename,
+               const struct lttng_credentials *creds)
+{
+       int ret;
+
+       if (!creds) {
+               /* Run as current user. */
+               ret = lttng_directory_handle_unlink(handle, filename);
+       } else {
+               ret = _run_as_unlink(handle, filename, creds->uid, creds->gid);
+       }
+       return ret;
+}
+
+LTTNG_HIDDEN
+int lttng_directory_handle_unlink_file(
+               const struct lttng_directory_handle *handle,
+               const char *filename)
+{
+       return lttng_directory_handle_unlink_file_as_user(handle,
+                       filename, NULL);
+}
index 605c3dc814743e3ab43a3d206f4f87436a9b7da6..bdf216200a4c1b84b77e64ebfdbfdb36b9639f1c 100644 (file)
@@ -153,4 +153,28 @@ int lttng_directory_handle_create_subdirectory_recursive_as_user(
                const char *subdirectory_path,
                mode_t mode, const struct lttng_credentials *creds);
 
+LTTNG_HIDDEN
+int lttng_directory_handle_open_file(
+               const struct lttng_directory_handle *handle,
+               const char *filename,
+               int flags, mode_t mode);
+
+LTTNG_HIDDEN
+int lttng_directory_handle_open_file_as_user(
+               const struct lttng_directory_handle *handle,
+               const char *filename,
+               int flags, mode_t mode,
+               const struct lttng_credentials *creds);
+
+LTTNG_HIDDEN
+int lttng_directory_handle_unlink_file(
+               const struct lttng_directory_handle *handle,
+               const char *filename);
+
+LTTNG_HIDDEN
+int lttng_directory_handle_unlink_file_as_user(
+               const struct lttng_directory_handle *handle,
+               const char *filename,
+               const struct lttng_credentials *creds);
+
 #endif /* _COMPAT_PATH_HANDLE_H */
index bba0aa49d47292d383dd7e09b968779168bc8d44..c77f198c4d4061adade2b550846d38efbd387cf8 100644 (file)
@@ -108,7 +108,9 @@ enum run_as_cmd {
        RUN_AS_MKDIR_RECURSIVE,
        RUN_AS_MKDIRAT_RECURSIVE,
        RUN_AS_OPEN,
+       RUN_AS_OPENAT,
        RUN_AS_UNLINK,
+       RUN_AS_UNLINKAT,
        RUN_AS_RMDIR_RECURSIVE,
        RUN_AS_EXTRACT_ELF_SYMBOL_OFFSET,
        RUN_AS_EXTRACT_SDT_PROBE_OFFSETS,
@@ -231,7 +233,8 @@ int _mkdirat(struct run_as_data *data, struct run_as_ret *ret_value)
 static
 int _open(struct run_as_data *data, struct run_as_ret *ret_value)
 {
-       ret_value->u.open.ret = open(data->u.open.path, data->u.open.flags, data->u.open.mode);
+       ret_value->u.open.ret = openat(data->fd, data->u.open.path,
+                       data->u.open.flags, data->u.open.mode);
        ret_value->fd = ret_value->u.open.ret;
        ret_value->_errno = errno;
        ret_value->_error = ret_value->u.open.ret < 0;
@@ -241,7 +244,7 @@ int _open(struct run_as_data *data, struct run_as_ret *ret_value)
 static
 int _unlink(struct run_as_data *data, struct run_as_ret *ret_value)
 {
-       ret_value->u.unlink.ret = unlink(data->u.unlink.path);
+       ret_value->u.unlink.ret = unlinkat(data->fd, data->u.unlink.path, 0);
        ret_value->_errno = errno;
        ret_value->_error = (ret_value->u.unlink.ret) ? true : false;
        return ret_value->u.unlink.ret;
@@ -344,8 +347,10 @@ run_as_fct run_as_enum_to_fct(enum run_as_cmd cmd)
        case RUN_AS_MKDIRAT_RECURSIVE:
                return _mkdirat_recursive;
        case RUN_AS_OPEN:
+       case RUN_AS_OPENAT:
                return _open;
        case RUN_AS_UNLINK:
+       case RUN_AS_UNLINKAT:
                return _unlink;
        case RUN_AS_RMDIR_RECURSIVE:
                return _rmdir_recursive;
@@ -410,6 +415,8 @@ int send_fd_to_worker(struct run_as_worker *worker, enum run_as_cmd cmd, int fd)
        case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS:
        case RUN_AS_MKDIRAT:
        case RUN_AS_MKDIRAT_RECURSIVE:
+       case RUN_AS_OPENAT:
+       case RUN_AS_UNLINKAT:
                break;
        default:
                return 0;
@@ -436,6 +443,7 @@ int send_fd_to_master(struct run_as_worker *worker, enum run_as_cmd cmd, int fd)
 
        switch (cmd) {
        case RUN_AS_OPEN:
+       case RUN_AS_OPENAT:
                break;
        default:
                return 0;
@@ -466,6 +474,7 @@ int recv_fd_from_worker(struct run_as_worker *worker, enum run_as_cmd cmd, int *
 
        switch (cmd) {
        case RUN_AS_OPEN:
+       case RUN_AS_OPENAT:
                break;
        default:
                return 0;
@@ -490,9 +499,13 @@ int recv_fd_from_master(struct run_as_worker *worker, enum run_as_cmd cmd, int *
        case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS:
        case RUN_AS_MKDIRAT:
        case RUN_AS_MKDIRAT_RECURSIVE:
+       case RUN_AS_OPENAT:
+       case RUN_AS_UNLINKAT:
                break;
        case RUN_AS_MKDIR:
        case RUN_AS_MKDIR_RECURSIVE:
+       case RUN_AS_OPEN:
+       case RUN_AS_UNLINK:
                *fd = AT_FDCWD;
                /* fall-through */
        default:
@@ -518,6 +531,10 @@ int cleanup_received_fd(enum run_as_cmd cmd, int fd)
        case RUN_AS_EXTRACT_SDT_PROBE_OFFSETS:
        case RUN_AS_MKDIRAT:
        case RUN_AS_MKDIRAT_RECURSIVE:
+       case RUN_AS_OPEN:
+       case RUN_AS_OPENAT:
+       case RUN_AS_UNLINK:
+       case RUN_AS_UNLINKAT:
                break;
        default:
                return 0;
@@ -1200,7 +1217,15 @@ error:
 }
 
 LTTNG_HIDDEN
-int run_as_open(const char *path, int flags, 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)
+{
+       return run_as_openat(AT_FDCWD, path, flags, mode, uid, gid);
+}
+
+LTTNG_HIDDEN
+int run_as_openat(int dirfd, const char *path, int flags, mode_t mode,
+               uid_t uid, gid_t gid)
 {
        struct run_as_data data;
        struct run_as_ret ret;
@@ -1208,13 +1233,16 @@ int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid)
        memset(&data, 0, sizeof(data));
        memset(&ret, 0, sizeof(ret));
 
-       DBG3("open() %s with flags %X mode %d for uid %d and gid %d",
+       DBG3("openat() fd = %d%s, path = %s, flags = %X, mode = %d, uid %d, gid %d",
+                       dirfd, dirfd == AT_FDCWD ? " (AT_FDCWD)" : "",
                        path, flags, (int) mode, (int) uid, (int) gid);
        strncpy(data.u.open.path, path, PATH_MAX - 1);
        data.u.open.path[PATH_MAX - 1] = '\0';
        data.u.open.flags = flags;
        data.u.open.mode = mode;
-       run_as(RUN_AS_OPEN, &data, &ret, uid, gid);
+       data.fd = dirfd;
+       run_as(dirfd == AT_FDCWD ? RUN_AS_OPEN : RUN_AS_OPENAT,
+                       &data, &ret, uid, gid);
        errno = ret._errno;
        ret.u.open.ret = ret.fd;
        return ret.u.open.ret;
@@ -1222,6 +1250,12 @@ int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid)
 
 LTTNG_HIDDEN
 int run_as_unlink(const char *path, uid_t uid, gid_t gid)
+{
+       return run_as_unlinkat(AT_FDCWD, path, uid, gid);
+}
+
+LTTNG_HIDDEN
+int run_as_unlinkat(int dirfd, const char *path, uid_t uid, gid_t gid)
 {
        struct run_as_data data;
        struct run_as_ret ret;
@@ -1229,10 +1263,12 @@ int run_as_unlink(const char *path, uid_t uid, gid_t gid)
        memset(&data, 0, sizeof(data));
        memset(&ret, 0, sizeof(ret));
 
-       DBG3("unlink() %s with for uid %d and gid %d",
+       DBG3("unlinkat() fd = %d%s, path = %s, uid = %d, gid = %d",
+                       dirfd, dirfd == AT_FDCWD ? " (AT_FDCWD)" : "",
                        path, (int) uid, (int) gid);
        strncpy(data.u.unlink.path, path, PATH_MAX - 1);
        data.u.unlink.path[PATH_MAX - 1] = '\0';
+       data.fd = dirfd;
        run_as(RUN_AS_UNLINK, &data, &ret, uid, gid);
        errno = ret._errno;
        return ret.u.unlink.ret;
index 82737177485b43c381c3834a2c577c367113f61a..55734eb41be39cbbe0e28fa05c9ecd04bc86e340 100644 (file)
@@ -23,6 +23,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <common/macros.h>
+
 /*
  * The run-as process is launched by forking without an exec*() call. This means
  * that any resource allocated before the run-as worker is launched should be
@@ -51,8 +53,13 @@ int run_as_mkdirat(int dirfd, const char *path, mode_t mode,
 LTTNG_HIDDEN
 int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid);
 LTTNG_HIDDEN
+int run_as_openat(int dirfd, const char *filename, int flags, mode_t mode,
+               uid_t uid, gid_t gid);
+LTTNG_HIDDEN
 int run_as_unlink(const char *path, uid_t uid, gid_t gid);
 LTTNG_HIDDEN
+int run_as_unlinkat(int dirfd, const char *filename, uid_t uid, gid_t gid);
+LTTNG_HIDDEN
 int run_as_rmdir_recursive(const char *path, uid_t uid, gid_t gid);
 LTTNG_HIDDEN
 int run_as_extract_elf_symbol_offset(int fd, const char* function,
This page took 0.033092 seconds and 5 git commands to generate.