From: Christian Brauner Date: Mon, 1 Feb 2021 19:03:29 +0000 (+0100) Subject: attach: harden open calls X-Git-Tag: lxc-5.0.0~308^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5129b2d3edcaef2feebdb80ae478f3268cfba454;p=thirdparty%2Flxc.git attach: harden open calls Signed-off-by: Christian Brauner --- diff --git a/src/lxc/attach.c b/src/lxc/attach.c index fa8c556b7..8ade8db12 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -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; diff --git a/src/lxc/file_utils.c b/src/lxc/file_utils.c index ce1c83d61..85faff391 100644 --- a/src/lxc/file_utils.c +++ b/src/lxc/file_utils.c @@ -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; diff --git a/src/lxc/file_utils.h b/src/lxc/file_utils.h index 7a8d322e7..cc8d8d478 100644 --- a/src/lxc/file_utils.h +++ b/src/lxc/file_utils.h @@ -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);