]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
attach: harden open calls
authorChristian Brauner <christian.brauner@ubuntu.com>
Mon, 1 Feb 2021 19:03:29 +0000 (20:03 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Mon, 1 Feb 2021 19:27:51 +0000 (20:27 +0100)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/attach.c
src/lxc/file_utils.c
src/lxc/file_utils.h

index fa8c556b74a8df7ff44e4a1f72c2242dea37c5ae..8ade8db1226fcdbe0c9abc186b6125e812c3928e 100644 (file)
@@ -231,7 +231,7 @@ static int userns_setup_ids(struct attach_context *ctx,
        if (!(options->namespaces & CLONE_NEWUSER))
                return 0;
 
-       f_uidmap = fdopenat(ctx->dfd_init_pid, "uid_map", "re");
+       f_uidmap = fdopen_at(ctx->dfd_init_pid, "uid_map", "re", PROTECT_OPEN, PROTECT_LOOKUP_ABSOLUTE);
        if (!f_uidmap)
                return log_error_errno(-errno, errno, "Failed to open uid_map");
 
@@ -251,7 +251,7 @@ static int userns_setup_ids(struct attach_context *ctx,
                }
        }
 
-       f_gidmap = fdopenat(ctx->dfd_init_pid, "gid_map", "re");
+       f_gidmap = fdopen_at(ctx->dfd_init_pid, "gid_map", "re", PROTECT_OPEN, PROTECT_LOOKUP_ABSOLUTE);
        if (!f_gidmap)
                return log_error_errno(-errno, errno, "Failed to open gid_map");
 
@@ -316,7 +316,7 @@ static int parse_init_status(struct attach_context *ctx, lxc_attach_options_t *o
        bool caps_found = false;
        int ret;
 
-       f = fdopenat(ctx->dfd_init_pid, "status", "re");
+       f = fdopen_at(ctx->dfd_init_pid, "status", "re", PROTECT_OPEN, PROTECT_LOOKUP_ABSOLUTE);
        if (!f)
                return log_error_errno(-errno, errno, "Failed to open status file");
 
@@ -389,7 +389,9 @@ static int get_attach_context(struct attach_context *ctx,
        if (ctx->init_pid < 0)
                return log_error(-1, "Failed to get init pid");
 
-       ctx->dfd_self_pid = openat(-EBADF, "/proc/self", O_CLOEXEC | O_NOCTTY | O_PATH | O_DIRECTORY);
+       ctx->dfd_self_pid = open_at(-EBADF, "/proc/self",
+                                   PROTECT_OPATH_FILE & ~O_NOFOLLOW,
+                                   (PROTECT_LOOKUP_ABSOLUTE_WITH_SYMLINKS & ~RESOLVE_NO_XDEV), 0);
        if (ctx->dfd_self_pid < 0)
                return log_error_errno(-errno, errno, "Failed to open /proc/self");
 
@@ -397,7 +399,9 @@ static int get_attach_context(struct attach_context *ctx,
        if (ret < 0 || ret >= sizeof(path))
                return ret_errno(EIO);
 
-       ctx->dfd_init_pid = openat(-EBADF, path, O_CLOEXEC | O_NOCTTY | O_NOFOLLOW | O_PATH | O_DIRECTORY);
+       ctx->dfd_init_pid = open_at(-EBADF, path,
+                                   PROTECT_OPATH_DIRECTORY,
+                                   (PROTECT_LOOKUP_ABSOLUTE & ~RESOLVE_NO_XDEV), 0);
        if (ctx->dfd_init_pid < 0)
                return log_error_errno(-errno, errno, "Failed to open /proc/%d", ctx->init_pid);
 
@@ -460,24 +464,30 @@ static int get_attach_context(struct attach_context *ctx,
        return 0;
 }
 
-static int in_same_namespace(int ns_fd_pid1, int ns_fd_pid2, const char *ns_path)
+static int same_ns(int ns_fd_pid1, int ns_fd_pid2, const char *ns_path)
 {
        __do_close int ns_fd1 = -EBADF, ns_fd2 = -EBADF;
        int ret = -1;
        struct stat ns_st1, ns_st2;
 
-       ns_fd1 = openat(ns_fd_pid1, ns_path, O_CLOEXEC | O_NOCTTY | O_RDONLY);
+       ns_fd1 = open_at(ns_fd_pid1, ns_path,
+                        PROTECT_OPEN_WITH_TRAILING_SYMLINKS,
+                        (PROTECT_LOOKUP_BENEATH_WITH_MAGICLINKS & ~(RESOLVE_NO_XDEV | RESOLVE_BENEATH)),
+                        0);
        if (ns_fd1 < 0) {
                /* The kernel does not support this namespace. This is not an error. */
                if (errno == ENOENT)
                        return -EINVAL;
 
-               return -1;
+               return log_error_errno(-errno, errno, "Failed to open %d(%s)", ns_fd_pid1, ns_path);
        }
 
-       ns_fd2 = openat(ns_fd_pid2, ns_path, O_CLOEXEC | O_NOCTTY | O_RDONLY);
+       ns_fd2 = open_at(ns_fd_pid2, ns_path,
+                        PROTECT_OPEN_WITH_TRAILING_SYMLINKS,
+                        (PROTECT_LOOKUP_BENEATH_WITH_MAGICLINKS & ~(RESOLVE_NO_XDEV | RESOLVE_BENEATH)),
+                        0);
        if (ns_fd2 < 0)
-               return -1;
+               return log_error_errno(-errno, errno, "Failed to open %d(%s)", ns_fd_pid2, ns_path);
 
        ret = fstat(ns_fd1, &ns_st1);
        if (ret < 0)
@@ -503,9 +513,15 @@ static int get_attach_context_nsfds(struct attach_context *ctx,
                int j;
 
                if (options->namespaces & ns_info[i].clone_flag)
-                       ctx->ns_fd[i] = openat(ctx->dfd_init_pid, ns_info[i].proc_path, O_CLOEXEC | O_NOCTTY | O_RDONLY);
+                       ctx->ns_fd[i] = open_at(ctx->dfd_init_pid,
+                                               ns_info[i].proc_path,
+                                               PROTECT_OPEN_WITH_TRAILING_SYMLINKS,
+                                               (PROTECT_LOOKUP_BENEATH_WITH_MAGICLINKS & ~(RESOLVE_NO_XDEV | RESOLVE_BENEATH)),
+                                               0);
                else if (ctx->ns_inherited & ns_info[i].clone_flag)
-                       ctx->ns_fd[i] = in_same_namespace(ctx->dfd_self_pid, ctx->dfd_init_pid, ns_info[i].proc_path);
+                       ctx->ns_fd[i] = same_ns(ctx->dfd_self_pid,
+                                               ctx->dfd_init_pid,
+                                               ns_info[i].proc_path);
                else
                        continue;
 
index ce1c83d610098a691b827f2e9422a9489453d31d..85faff391db56029668ddff94ada297b770d4a5c 100644 (file)
@@ -553,7 +553,8 @@ static inline int dup_cloexec(int fd)
        return move_fd(fd_dup);
 }
 
-FILE *fdopenat(int dfd, const char *path, const char *mode)
+FILE *fdopen_at(int dfd, const char *path, const char *mode,
+               unsigned int o_flags, unsigned int resolve_flags)
 {
        __do_close int fd = -EBADF;
        __do_fclose FILE *f = NULL;
@@ -561,7 +562,7 @@ FILE *fdopenat(int dfd, const char *path, const char *mode)
        if (is_empty_string(path))
                fd = dup_cloexec(dfd);
        else
-               fd = openat(dfd, path, O_CLOEXEC | O_NOCTTY | O_NOFOLLOW);
+               fd = open_at(dfd, path, o_flags, resolve_flags, 0);
        if (fd < 0)
                return NULL;
 
index 7a8d322e70ecbf13ea1fc15176d34199709eef79..cc8d8d4788c571c124cdc83fb65b9cdaef43d8c8 100644 (file)
@@ -77,7 +77,9 @@ static inline int fd_to_fd(int from, int to)
 __hidden extern int fd_cloexec(int fd, bool cloexec);
 __hidden extern int lxc_open_dirfd(const char *dir);
 __hidden extern FILE *fdopen_cached(int fd, const char *mode, void **caller_freed_buffer);
-__hidden extern FILE *fdopenat(int dfd, const char *path, const char *mode);
+__hidden extern FILE *fdopen_at(int dfd, const char *path, const char *mode,
+                                unsigned int o_flags,
+                                unsigned int resolve_flags);
 __hidden extern FILE *fopen_cached(const char *path, const char *mode, void **caller_freed_buffer);
 __hidden extern int timens_offset_write(clockid_t clk_id, int64_t s_offset, int64_t ns_offset);
 __hidden extern bool exists_dir_at(int dir_fd, const char *path);