Unverified Commit f8dcf07f by Stéphane Graber Committed by GitHub

Merge pull request #3648 from brauner/2021-02-03/fixes

conf: open hardening & fd-only operations
parents b5e75029 a26822c5
...@@ -644,7 +644,7 @@ AC_CHECK_HEADER([ifaddrs.h], ...@@ -644,7 +644,7 @@ AC_CHECK_HEADER([ifaddrs.h],
AC_HEADER_MAJOR AC_HEADER_MAJOR
# Check for some syscalls functions # Check for some syscalls functions
AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr faccessat gettid memfd_create move_mount open_tree execveat clone3 fsopen fspick fsconfig fsmount, openat2]) AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr faccessat gettid memfd_create move_mount open_tree execveat clone3 fsopen fspick fsconfig fsmount, openat2, close_range])
AC_CHECK_TYPES([struct open_how], [], [], [[#include <linux/openat2.h>]]) AC_CHECK_TYPES([struct open_how], [], [], [[#include <linux/openat2.h>]])
AC_CHECK_TYPES([struct clone_args], [], [], [[#include <linux/sched.h>]]) AC_CHECK_TYPES([struct clone_args], [], [], [[#include <linux/sched.h>]])
AC_CHECK_MEMBERS([struct clone_args.set_tid],[],[],[[#include <linux/sched.h>]]) AC_CHECK_MEMBERS([struct clone_args.set_tid],[],[],[[#include <linux/sched.h>]])
......
...@@ -781,31 +781,30 @@ static const struct dev_symlinks dev_symlinks[] = { ...@@ -781,31 +781,30 @@ static const struct dev_symlinks dev_symlinks[] = {
static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs) static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs)
{ {
int i, ret; for (int i = 0; i < sizeof(dev_symlinks) / sizeof(dev_symlinks[0]); i++) {
char path[PATH_MAX]; int ret;
struct stat s; struct stat s;
for (i = 0; i < sizeof(dev_symlinks) / sizeof(dev_symlinks[0]); i++) {
const struct dev_symlinks *d = &dev_symlinks[i]; const struct dev_symlinks *d = &dev_symlinks[i];
ret = snprintf(path, sizeof(path), "%s/dev/%s", /*
rootfs->path ? rootfs->mount : "", d->name); * Stat the path first. If we don't get an error accept it as
if (ret < 0 || (size_t)ret >= sizeof(path))
return -1;
/* Stat the path first. If we don't get an error accept it as
* is and don't try to create it * is and don't try to create it
*/ */
ret = stat(path, &s); ret = fstatat(rootfs->dev_mntpt_fd, d->name, &s, 0);
if (ret == 0) if (ret == 0)
continue; continue;
ret = symlink(d->oldpath, path); ret = symlinkat(d->oldpath, rootfs->dev_mntpt_fd, d->name);
if (ret && errno != EEXIST) { if (ret) {
if (errno == EROFS) switch (errno) {
WARN("Failed to create \"%s\". Read-only filesystem", path); case EROFS:
else WARN("Failed to create \"%s\" on read-only filesystem", d->name);
return log_error_errno(-1, errno, "Failed to create \"%s\"", path); __fallthrough;
case EEXIST:
break;
default:
return log_error_errno(-errno, errno, "Failed to create \"%s\"", d->name);
}
} }
} }
...@@ -1149,18 +1148,12 @@ enum { ...@@ -1149,18 +1148,12 @@ enum {
static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
{ {
__do_close int dev_dir_fd = -EBADF;
int i, ret; int i, ret;
mode_t cmask; mode_t cmask;
int use_mknod = LXC_DEVNODE_MKNOD; int use_mknod = LXC_DEVNODE_MKNOD;
/* ignore, just don't try to fill in */ if (rootfs->dev_mntpt_fd < 0)
if (!exists_dir_at(rootfs->mntpt_fd, "dev")) return log_info(0, "No /dev directory found, skipping setup");
return 0;
dev_dir_fd = openat(rootfs->mntpt_fd, "dev/", O_RDONLY | O_CLOEXEC | O_DIRECTORY | O_PATH | O_NOFOLLOW);
if (dev_dir_fd < 0)
return -errno;
INFO("Populating \"/dev\""); INFO("Populating \"/dev\"");
...@@ -1170,7 +1163,7 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) ...@@ -1170,7 +1163,7 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
const struct lxc_device_node *device = &lxc_devices[i]; const struct lxc_device_node *device = &lxc_devices[i];
if (use_mknod >= LXC_DEVNODE_MKNOD) { if (use_mknod >= LXC_DEVNODE_MKNOD) {
ret = mknodat(dev_dir_fd, device->name, device->mode, makedev(device->maj, device->min)); ret = mknodat(rootfs->dev_mntpt_fd, device->name, device->mode, makedev(device->maj, device->min));
if (ret == 0 || (ret < 0 && errno == EEXIST)) { if (ret == 0 || (ret < 0 && errno == EEXIST)) {
DEBUG("Created device node \"%s\"", device->name); DEBUG("Created device node \"%s\"", device->name);
} else if (ret < 0) { } else if (ret < 0) {
...@@ -1190,7 +1183,7 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) ...@@ -1190,7 +1183,7 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
* - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=55956b59df336f6738da916dbb520b6e37df9fbd * - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=55956b59df336f6738da916dbb520b6e37df9fbd
* - https://lists.linuxfoundation.org/pipermail/containers/2018-June/039176.html * - https://lists.linuxfoundation.org/pipermail/containers/2018-June/039176.html
*/ */
fd = openat(dev_dir_fd, device->name, O_RDONLY | O_CLOEXEC); fd = open_at(rootfs->dev_mntpt_fd, device->name, PROTECT_OPEN, PROTECT_LOOKUP_BENEATH, 0);
if (fd >= 0) { if (fd >= 0) {
/* Device nodes are fully useable. */ /* Device nodes are fully useable. */
use_mknod = LXC_DEVNODE_OPEN; use_mknod = LXC_DEVNODE_OPEN;
...@@ -1208,7 +1201,7 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) ...@@ -1208,7 +1201,7 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
* nodes the prio mknod() call will have created the * nodes the prio mknod() call will have created the
* device node so we can use it as a bind-mount target. * device node so we can use it as a bind-mount target.
*/ */
ret = mknodat(dev_dir_fd, device->name, S_IFREG | 0000, 0); ret = mknodat(rootfs->dev_mntpt_fd, device->name, S_IFREG | 0000, 0);
if (ret < 0 && errno != EEXIST) if (ret < 0 && errno != EEXIST)
return log_error_errno(-1, errno, "Failed to create file \"%s\"", device->name); return log_error_errno(-1, errno, "Failed to create file \"%s\"", device->name);
} }
...@@ -1218,7 +1211,7 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) ...@@ -1218,7 +1211,7 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
if (ret < 0 || (size_t)ret >= sizeof(hostpath)) if (ret < 0 || (size_t)ret >= sizeof(hostpath))
return ret_errno(EIO); return ret_errno(EIO);
ret = safe_mount_beneath_at(dev_dir_fd, hostpath, device->name, NULL, MS_BIND, NULL); ret = safe_mount_beneath_at(rootfs->dev_mntpt_fd, hostpath, device->name, NULL, MS_BIND, NULL);
if (ret < 0) { if (ret < 0) {
const char *mntpt = rootfs->path ? rootfs->mount : NULL; const char *mntpt = rootfs->path ? rootfs->mount : NULL;
if (errno == ENOSYS) { if (errno == ENOSYS) {
...@@ -1278,7 +1271,7 @@ static int lxc_mount_rootfs(struct lxc_conf *conf) ...@@ -1278,7 +1271,7 @@ static int lxc_mount_rootfs(struct lxc_conf *conf)
rootfs->path, rootfs->mount, rootfs->path, rootfs->mount,
rootfs->options ? rootfs->options : "(null)"); rootfs->options ? rootfs->options : "(null)");
rootfs->mntpt_fd = openat(-1, rootfs->mount, O_RDONLY | O_CLOEXEC | O_DIRECTORY | O_PATH); rootfs->mntpt_fd = open_at(-EBADF, rootfs->mount, PROTECT_OPATH_DIRECTORY, PROTECT_LOOKUP_ABSOLUTE_XDEV, 0);
if (rootfs->mntpt_fd < 0) if (rootfs->mntpt_fd < 0)
return -errno; return -errno;
...@@ -1401,54 +1394,50 @@ static int lxc_chroot(const struct lxc_rootfs *rootfs) ...@@ -1401,54 +1394,50 @@ static int lxc_chroot(const struct lxc_rootfs *rootfs)
* though, so you may need to say mount --bind /nfs/my_root /nfs/my_root * though, so you may need to say mount --bind /nfs/my_root /nfs/my_root
* first. * first.
*/ */
static int lxc_pivot_root(const char *rootfs) static int lxc_pivot_root(const struct lxc_rootfs *rootfs)
{ {
__do_close int oldroot = -EBADF, newroot = -EBADF; __do_close int fd_oldroot = -EBADF;
int ret; int ret;
oldroot = open("/", O_DIRECTORY | O_RDONLY | O_CLOEXEC); fd_oldroot = open_at(-EBADF, "/", PROTECT_OPATH_DIRECTORY, PROTECT_LOOKUP_ABSOLUTE, 0);
if (oldroot < 0) if (fd_oldroot < 0)
return log_error_errno(-1, errno, "Failed to open old root directory"); return log_error_errno(-1, errno, "Failed to open old root directory");
newroot = open(rootfs, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
if (newroot < 0)
return log_error_errno(-1, errno, "Failed to open new root directory");
/* change into new root fs */ /* change into new root fs */
ret = fchdir(newroot); ret = fchdir(rootfs->mntpt_fd);
if (ret < 0) if (ret < 0)
return log_error_errno(-1, errno, "Failed to change to new rootfs \"%s\"", rootfs); return log_error_errno(-errno, errno, "Failed to change into new root directory \"%s\"", rootfs->mount);
/* pivot_root into our new root fs */ /* pivot_root into our new root fs */
ret = pivot_root(".", "."); ret = pivot_root(".", ".");
if (ret < 0) if (ret < 0)
return log_error_errno(-1, errno, "Failed to pivot_root()"); return log_error_errno(-errno, errno, "Failed to pivot into new root directory \"%s\"", rootfs->mount);
/* At this point the old-root is mounted on top of our new-root. To /* At this point the old-root is mounted on top of our new-root. To
* unmounted it we must not be chdir'd into it, so escape back to * unmounted it we must not be chdir'd into it, so escape back to
* old-root. * old-root.
*/ */
ret = fchdir(oldroot); ret = fchdir(fd_oldroot);
if (ret < 0) if (ret < 0)
return log_error_errno(-1, errno, "Failed to enter old root directory"); return log_error_errno(-errno, errno, "Failed to enter old root directory");
/* Make oldroot a depedent mount to make sure our umounts don't propagate to the /*
* host. * Make fd_oldroot a depedent mount to make sure our umounts don't
* propagate to the host.
*/ */
ret = mount("", ".", "", MS_SLAVE | MS_REC, NULL); ret = mount("", ".", "", MS_SLAVE | MS_REC, NULL);
if (ret < 0) if (ret < 0)
return log_error_errno(-1, errno, "Failed to recursively turn old root mount tree into dependent mount"); return log_error_errno(-errno, errno, "Failed to recursively turn old root mount tree into dependent mount");
ret = umount2(".", MNT_DETACH); ret = umount2(".", MNT_DETACH);
if (ret < 0) if (ret < 0)
return log_error_errno(-1, errno, "Failed to detach old root directory"); return log_error_errno(-errno, errno, "Failed to detach old root directory");
ret = fchdir(newroot); ret = fchdir(rootfs->mntpt_fd);
if (ret < 0) if (ret < 0)
return log_error_errno(-1, errno, "Failed to re-enter new root directory"); return log_error_errno(-errno, errno, "Failed to re-enter new root directory \"%s\"", rootfs->mount);
TRACE("pivot_root(\"%s\") successful", rootfs);
TRACE("Changed into new rootfs \"%s\"", rootfs->mount);
return 0; return 0;
} }
...@@ -1460,7 +1449,7 @@ static int lxc_setup_rootfs_switch_root(const struct lxc_rootfs *rootfs) ...@@ -1460,7 +1449,7 @@ static int lxc_setup_rootfs_switch_root(const struct lxc_rootfs *rootfs)
if (detect_ramfs_rootfs()) if (detect_ramfs_rootfs())
return lxc_chroot(rootfs); return lxc_chroot(rootfs);
return lxc_pivot_root(rootfs->mount); return lxc_pivot_root(rootfs);
} }
static const struct id_map *find_mapped_nsid_entry(const struct lxc_conf *conf, static const struct id_map *find_mapped_nsid_entry(const struct lxc_conf *conf,
...@@ -1519,6 +1508,7 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler) ...@@ -1519,6 +1508,7 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler)
char *mntopt_sets[5]; char *mntopt_sets[5];
char default_devpts_mntopts[256] = "gid=5,newinstance,ptmxmode=0666,mode=0620"; char default_devpts_mntopts[256] = "gid=5,newinstance,ptmxmode=0666,mode=0620";
struct lxc_conf *conf = handler->conf; struct lxc_conf *conf = handler->conf;
struct lxc_rootfs *rootfs = &conf->rootfs;
int sock = handler->data_sock[0]; int sock = handler->data_sock[0];
if (conf->pty_max <= 0) if (conf->pty_max <= 0)
...@@ -1532,7 +1522,7 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler) ...@@ -1532,7 +1522,7 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler)
(void)umount2("/dev/pts", MNT_DETACH); (void)umount2("/dev/pts", MNT_DETACH);
/* Create mountpoint for devpts instance. */ /* Create mountpoint for devpts instance. */
ret = mkdir("/dev/pts", 0755); ret = mkdirat(rootfs->dev_mntpt_fd, "pts", 0755);
if (ret < 0 && errno != EEXIST) if (ret < 0 && errno != EEXIST)
return log_error_errno(-1, errno, "Failed to create \"/dev/pts\" directory"); return log_error_errno(-1, errno, "Failed to create \"/dev/pts\" directory");
...@@ -1562,7 +1552,7 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler) ...@@ -1562,7 +1552,7 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler)
return log_error_errno(-1, errno, "Failed to mount new devpts instance"); return log_error_errno(-1, errno, "Failed to mount new devpts instance");
DEBUG("Mount new devpts instance with options \"%s\"", *opts); DEBUG("Mount new devpts instance with options \"%s\"", *opts);
devpts_fd = openat(-EBADF, "/dev/pts", O_CLOEXEC | O_DIRECTORY | O_PATH | O_NOFOLLOW); devpts_fd = open_at(rootfs->dev_mntpt_fd, "pts", PROTECT_OPATH_DIRECTORY, PROTECT_LOOKUP_BENEATH_XDEV, 0);
if (devpts_fd < 0) { if (devpts_fd < 0) {
devpts_fd = -EBADF; devpts_fd = -EBADF;
TRACE("Failed to create detached devpts mount"); TRACE("Failed to create detached devpts mount");
...@@ -1576,7 +1566,7 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler) ...@@ -1576,7 +1566,7 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler)
TRACE("Sent devpts file descriptor %d to parent", devpts_fd); TRACE("Sent devpts file descriptor %d to parent", devpts_fd);
/* Remove any pre-existing /dev/ptmx file. */ /* Remove any pre-existing /dev/ptmx file. */
ret = remove("/dev/ptmx"); ret = unlinkat(rootfs->dev_mntpt_fd, "ptmx", 0);
if (ret < 0) { if (ret < 0) {
if (errno != ENOENT) if (errno != ENOENT)
return log_error_errno(-1, errno, "Failed to remove existing \"/dev/ptmx\" file"); return log_error_errno(-1, errno, "Failed to remove existing \"/dev/ptmx\" file");
...@@ -1585,7 +1575,7 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler) ...@@ -1585,7 +1575,7 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler)
} }
/* Create dummy /dev/ptmx file as bind mountpoint for /dev/pts/ptmx. */ /* Create dummy /dev/ptmx file as bind mountpoint for /dev/pts/ptmx. */
ret = mknod("/dev/ptmx", S_IFREG | 0000, 0); ret = mknodat(rootfs->dev_mntpt_fd, "ptmx", S_IFREG | 0000, 0);
if (ret < 0 && errno != EEXIST) if (ret < 0 && errno != EEXIST)
return log_error_errno(-1, errno, "Failed to create dummy \"/dev/ptmx\" file as bind mount target"); return log_error_errno(-1, errno, "Failed to create dummy \"/dev/ptmx\" file as bind mount target");
DEBUG("Created dummy \"/dev/ptmx\" file as bind mount target"); DEBUG("Created dummy \"/dev/ptmx\" file as bind mount target");
...@@ -1599,12 +1589,12 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler) ...@@ -1599,12 +1589,12 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler)
ERROR("Failed to bind mount \"/dev/pts/ptmx\" to \"/dev/ptmx\""); ERROR("Failed to bind mount \"/dev/pts/ptmx\" to \"/dev/ptmx\"");
/* Remove the dummy /dev/ptmx file we created above. */ /* Remove the dummy /dev/ptmx file we created above. */
ret = remove("/dev/ptmx"); ret = unlinkat(rootfs->dev_mntpt_fd, "ptmx", 0);
if (ret < 0) if (ret < 0)
return log_error_errno(-1, errno, "Failed to remove existing \"/dev/ptmx\""); return log_error_errno(-1, errno, "Failed to remove existing \"/dev/ptmx\"");
/* Fallback option: Create symlink /dev/ptmx -> /dev/pts/ptmx. */ /* Fallback option: Create symlink /dev/ptmx -> /dev/pts/ptmx. */
ret = symlink("/dev/pts/ptmx", "/dev/ptmx"); ret = symlinkat("/dev/pts/ptmx", rootfs->dev_mntpt_fd, "/dev/ptmx");
if (ret < 0) if (ret < 0)
return log_error_errno(-1, errno, "Failed to create symlink from \"/dev/ptmx\" to \"/dev/pts/ptmx\""); return log_error_errno(-1, errno, "Failed to create symlink from \"/dev/ptmx\" to \"/dev/pts/ptmx\"");
...@@ -3334,8 +3324,8 @@ int lxc_setup(struct lxc_handler *handler) ...@@ -3334,8 +3324,8 @@ int lxc_setup(struct lxc_handler *handler)
return log_error(-1, "Failed to mount \"/dev\""); return log_error(-1, "Failed to mount \"/dev\"");
} }
lxc_conf->rootfs.dev_mntpt_fd = openat(lxc_conf->rootfs.mntpt_fd, "dev", lxc_conf->rootfs.dev_mntpt_fd = open_at(lxc_conf->rootfs.mntpt_fd, "dev",
O_RDONLY | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW); PROTECT_OPATH_DIRECTORY, PROTECT_LOOKUP_BENEATH_XDEV, 0);
if (lxc_conf->rootfs.dev_mntpt_fd < 0 && errno != ENOENT) if (lxc_conf->rootfs.dev_mntpt_fd < 0 && errno != ENOENT)
return log_error_errno(-errno, errno, "Failed to open \"/dev\""); return log_error_errno(-errno, errno, "Failed to open \"/dev\"");
......
...@@ -672,4 +672,6 @@ enum { ...@@ -672,4 +672,6 @@ enum {
#define ENOCGROUP2 ENOMEDIUM #define ENOCGROUP2 ENOMEDIUM
#define MAX_FILENO ~0U
#endif /* __LXC_MACRO_H */ #endif /* __LXC_MACRO_H */
...@@ -127,10 +127,13 @@ static void lxc_rexec_as_memfd(char **argv, char **envp, const char *memfd_name) ...@@ -127,10 +127,13 @@ static void lxc_rexec_as_memfd(char **argv, char **envp, const char *memfd_name)
sent = lxc_sendfile_nointr(memfd >= 0 ? memfd : tmpfd, fd, NULL, sent = lxc_sendfile_nointr(memfd >= 0 ? memfd : tmpfd, fd, NULL,
st.st_size - bytes_sent); st.st_size - bytes_sent);
if (sent < 0) { if (sent < 0) {
/* Fallback to shoveling data between kernel- and /*
* Fallback to shoveling data between kernel- and
* userspace. * userspace.
*/ */
lseek(fd, 0, SEEK_SET); if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
fprintf(stderr, "Failed to seek to beginning of file");
if (fd_to_fd(fd, memfd >= 0 ? memfd : tmpfd)) if (fd_to_fd(fd, memfd >= 0 ? memfd : tmpfd))
break; break;
...@@ -159,6 +162,9 @@ static void lxc_rexec_as_memfd(char **argv, char **envp, const char *memfd_name) ...@@ -159,6 +162,9 @@ static void lxc_rexec_as_memfd(char **argv, char **envp, const char *memfd_name)
if (execfd < 0) if (execfd < 0)
return; return;
ret = close_range(STDERR_FILENO, MAX_FILENO, CLOSE_RANGE_CLOEXEC);
if (ret && (errno != ENOSYS && errno != EINVAL))
fprintf(stderr, "%m - Failed to mark all file descriptors as close-on-exec\n");
fexecve(execfd, argv, envp); fexecve(execfd, argv, envp);
} }
......
...@@ -660,4 +660,24 @@ ...@@ -660,4 +660,24 @@
#endif #endif
#endif #endif
#ifndef __NR_close_range
#if defined __alpha__
#define __NR_close_range 546
#elif defined _MIPS_SIM
#if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */
#define __NR_close_range (436 + 4000)
#endif
#if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */
#define __NR_close_range (436 + 6000)
#endif
#if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */
#define __NR_close_range (436 + 5000)
#endif
#elif defined __ia64__
#define __NR_close_range (436 + 1024)
#else
#define __NR_close_range 436
#endif
#endif
#endif /* __LXC_SYSCALL_NUMBERS_H */ #endif /* __LXC_SYSCALL_NUMBERS_H */
...@@ -257,10 +257,12 @@ struct lxc_open_how { ...@@ -257,10 +257,12 @@ struct lxc_open_how {
#define PROTECT_LOOKUP_BENEATH (RESOLVE_BENEATH | RESOLVE_NO_XDEV | RESOLVE_NO_MAGICLINKS | RESOLVE_NO_SYMLINKS) #define PROTECT_LOOKUP_BENEATH (RESOLVE_BENEATH | RESOLVE_NO_XDEV | RESOLVE_NO_MAGICLINKS | RESOLVE_NO_SYMLINKS)
#define PROTECT_LOOKUP_BENEATH_WITH_SYMLINKS (PROTECT_LOOKUP_BENEATH & ~RESOLVE_NO_SYMLINKS) #define PROTECT_LOOKUP_BENEATH_WITH_SYMLINKS (PROTECT_LOOKUP_BENEATH & ~RESOLVE_NO_SYMLINKS)
#define PROTECT_LOOKUP_BENEATH_WITH_MAGICLINKS (PROTECT_LOOKUP_BENEATH & ~(RESOLVE_NO_SYMLINKS | RESOLVE_NO_MAGICLINKS)) #define PROTECT_LOOKUP_BENEATH_WITH_MAGICLINKS (PROTECT_LOOKUP_BENEATH & ~(RESOLVE_NO_SYMLINKS | RESOLVE_NO_MAGICLINKS))
#define PROTECT_LOOKUP_BENEATH_XDEV (PROTECT_LOOKUP_BENEATH & ~RESOLVE_NO_XDEV)
#define PROTECT_LOOKUP_ABSOLUTE (PROTECT_LOOKUP_BENEATH & ~RESOLVE_BENEATH) #define PROTECT_LOOKUP_ABSOLUTE (PROTECT_LOOKUP_BENEATH & ~RESOLVE_BENEATH)
#define PROTECT_LOOKUP_ABSOLUTE_WITH_SYMLINKS (PROTECT_LOOKUP_ABSOLUTE & ~RESOLVE_NO_SYMLINKS) #define PROTECT_LOOKUP_ABSOLUTE_WITH_SYMLINKS (PROTECT_LOOKUP_ABSOLUTE & ~RESOLVE_NO_SYMLINKS)
#define PROTECT_LOOKUP_ABSOLUTE_WITH_MAGICLINKS (PROTECT_LOOKUP_ABSOLUTE & ~(RESOLVE_NO_SYMLINKS | RESOLVE_NO_MAGICLINKS)) #define PROTECT_LOOKUP_ABSOLUTE_WITH_MAGICLINKS (PROTECT_LOOKUP_ABSOLUTE & ~(RESOLVE_NO_SYMLINKS | RESOLVE_NO_MAGICLINKS))
#define PROTECT_LOOKUP_ABSOLUTE_XDEV (PROTECT_LOOKUP_ABSOLUTE & ~RESOLVE_NO_XDEV)
#define PROTECT_OPATH_FILE (O_NOFOLLOW | O_PATH | O_CLOEXEC) #define PROTECT_OPATH_FILE (O_NOFOLLOW | O_PATH | O_CLOEXEC)
#define PROTECT_OPATH_DIRECTORY (PROTECT_OPATH_FILE | O_DIRECTORY) #define PROTECT_OPATH_DIRECTORY (PROTECT_OPATH_FILE | O_DIRECTORY)
...@@ -282,4 +284,19 @@ static inline int openat2(int dfd, const char *filename, struct lxc_open_how *ho ...@@ -282,4 +284,19 @@ static inline int openat2(int dfd, const char *filename, struct lxc_open_how *ho
} }
#endif /* HAVE_OPENAT2 */ #endif /* HAVE_OPENAT2 */
#ifndef CLOSE_RANGE_UNSHARE
#define CLOSE_RANGE_UNSHARE (1U << 1)
#endif
#ifndef CLOSE_RANGE_CLOEXEC
#define CLOSE_RANGE_CLOEXEC (1U << 2)
#endif
#ifndef HAVE_CLOSE_RANGE
static inline int close_range(unsigned int fd, unsigned int max_fd, unsigned int flags)
{
return syscall(__NR_close_range, fd, max_fd, flags);
}
#endif
#endif /* __LXC_SYSCALL_WRAPPER_H */ #endif /* __LXC_SYSCALL_WRAPPER_H */
...@@ -36,8 +36,8 @@ int main(int argc, char *argv[]) ...@@ -36,8 +36,8 @@ int main(int argc, char *argv[])
__do_close int fd_log = -EBADF; __do_close int fd_log = -EBADF;
int ret = 1; int ret = 1;
struct lxc_log log = {}; struct lxc_log log = {};
struct lxc_container *c = NULL;
char template[sizeof(P_tmpdir"/attach_XXXXXX")]; char template[sizeof(P_tmpdir"/attach_XXXXXX")];
struct lxc_container *c;
(void)strlcpy(template, P_tmpdir"/attach_XXXXXX", sizeof(template)); (void)strlcpy(template, P_tmpdir"/attach_XXXXXX", sizeof(template));
...@@ -107,6 +107,7 @@ out: ...@@ -107,6 +107,7 @@ out:
} }
(void)unlink(template); (void)unlink(template);
if (c)
lxc_container_put(c); lxc_container_put(c);
return ret; return ret;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment