From 0b8bc902c0c7acb54efb1fd4be5121dbf9a08598 Mon Sep 17 00:00:00 2001 From: wujing Date: Wed, 15 Jul 2020 16:09:35 +0800 Subject: [PATCH 2/9] add mount label for rootfs Signed-off-by: wujing --- src/lxc/cgroups/cgfsng.c | 59 +++++----- src/lxc/conf.c | 209 +++++++++++++++++++++++++++++++---- src/lxc/conf.h | 25 +++-- src/lxc/confile.c | 27 ++++- src/lxc/lsm/lsm.c | 20 ++++ src/lxc/lsm/lsm.h | 8 ++ src/lxc/lsm/selinux.c | 227 +++++++++++++++++++++++++++++++++++++++ src/lxc/utils.c | 70 ++++++++++++ src/lxc/utils.h | 6 ++ 9 files changed, 591 insertions(+), 60 deletions(-) diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index 4a0961f13..1ff3d9812 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -2133,7 +2133,7 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, } ret = safe_mount(NULL, tmpfspath, "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME, - "size=10240k,mode=755", root); + "size=10240k,mode=755", root, handler->conf->lsm_se_mount_context); if (ret < 0) goto on_error; @@ -2244,37 +2244,42 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops, } } - // isulad: remount /sys/fs/cgroup/systemd to readwrite for system container - if (handler->conf->systemd != NULL && strcmp(handler->conf->systemd, "true") == 0) { - // isulad: don't use the unified hierarchy for the systemd cgroup - unifiedpath = must_make_path(root, "/sys/fs/cgroup/unified", NULL); - if (dir_exists(unifiedpath)) { - ret = umount2(unifiedpath, MNT_DETACH); - if (ret < 0) { - SYSERROR("Failed to umount /sys/fs/cgroup/unified."); - goto on_error; - } - } - - systemdpath = must_make_path(root, "/sys/fs/cgroup/systemd", NULL); - ret = mount(systemdpath, systemdpath, "bind", - MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_RELATIME|MS_BIND|MS_REMOUNT, NULL); - if (ret < 0) { - SYSERROR("Failed to remount /sys/fs/cgroup/systemd."); - goto on_error; - } - } + // isulad: remount /sys/fs/cgroup/systemd to readwrite for system container + if (handler->conf->systemd != NULL && strcmp(handler->conf->systemd, "true") == 0) + { + unifiedpath = must_make_path(root, "/sys/fs/cgroup/unified", NULL); + if (dir_exists(unifiedpath)) + { + ret = umount2(unifiedpath, MNT_DETACH); + if (ret < 0) + { + SYSERROR("Failed to umount /sys/fs/cgroup/unified."); + goto on_error; + } + } + + systemdpath = must_make_path(root, "/sys/fs/cgroup/systemd", NULL); + ret = mount(systemdpath, systemdpath, "bind", + MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_RELATIME | MS_BIND | MS_REMOUNT, NULL); + if (ret < 0) + { + SYSERROR("Failed to remount /sys/fs/cgroup/systemd."); + goto on_error; + } + } retval = true; on_error: free(tmpfspath); - if (systemdpath != NULL) { - free(systemdpath); - } - if (unifiedpath != NULL) { - free(unifiedpath); - } + if (systemdpath != NULL) + { + free(systemdpath); + } + if (unifiedpath != NULL) + { + free(unifiedpath); + } lxc_free_array((void **)merged, free); return retval; } diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 0744c19b3..7e4af0a95 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -699,9 +699,15 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha mflags = add_required_remount_flags(source, destination, default_mounts[i].flags); +#ifdef HAVE_ISULAD + r = safe_mount(source, destination, default_mounts[i].fstype, + mflags, default_mounts[i].options, + conf->rootfs.path ? conf->rootfs.mount : NULL, NULL); +#else r = safe_mount(source, destination, default_mounts[i].fstype, mflags, default_mounts[i].options, conf->rootfs.path ? conf->rootfs.mount : NULL); +#endif saved_errno = errno; if (r < 0 && errno == ENOENT) { INFO("Mount source or target for \"%s\" on \"%s\" does not exist. Skipping", source, destination); @@ -1076,7 +1082,7 @@ on_error: */ #ifdef HAVE_ISULAD static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs, - int autodevtmpfssize, const char *lxcpath, char *systemd) + int autodevtmpfssize, const char *lxcpath, char *systemd, const char *mount_label) #else static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs, int autodevtmpfssize, const char *lxcpath) @@ -1118,7 +1124,7 @@ static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs, } } else { ret = safe_mount("none", path, "tmpfs", 0, mount_options, - rootfs->path ? rootfs->mount : NULL); + rootfs->path ? rootfs->mount : NULL, mount_label); if (ret < 0) { SYSERROR("Failed to mount tmpfs on \"%s\"", path); goto reset_umask; @@ -1127,7 +1133,7 @@ static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs, } #else ret = safe_mount("none", path, "tmpfs", 0, mount_options, - rootfs->path ? rootfs->mount : NULL ); + rootfs->path ? rootfs->mount : NULL); if (ret < 0) { SYSERROR("Failed to mount tmpfs on \"%s\"", path); goto reset_umask; @@ -1183,8 +1189,11 @@ enum { LXC_DEVNODE_PARTIAL, LXC_DEVNODE_OPEN, }; - +#ifdef HAVE_ISULAD +static int lxc_fill_autodev(const struct lxc_rootfs *rootfs, const char *mount_label) +#else static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) +#endif { int i, ret; char path[PATH_MAX]; @@ -1260,9 +1269,13 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) ret = snprintf(hostpath, PATH_MAX, "/dev/%s", device->name); if (ret < 0 || ret >= PATH_MAX) return -1; - +#ifdef HAVE_ISULAD + ret = safe_mount(hostpath, path, 0, MS_BIND, NULL, + rootfs->path ? rootfs->mount : NULL, mount_label); +#else ret = safe_mount(hostpath, path, 0, MS_BIND, NULL, rootfs->path ? rootfs->mount : NULL); +#endif if (ret < 0) return log_error_errno(-1, errno, "Failed to bind mount host device node \"%s\" onto \"%s\"", hostpath, path); @@ -1818,17 +1831,34 @@ static int lxc_setup_devpts(struct lxc_conf *conf) { int ret; char **opts; +#ifdef HAVE_ISULAD + __do_free char *devpts_mntopts = NULL; +#else char devpts_mntopts[256]; +#endif char *mntopt_sets[5]; char default_devpts_mntopts[256] = "gid=5,newinstance,ptmxmode=0666,mode=0620"; if (conf->pty_max <= 0) return log_debug(0, "No new devpts instance will be mounted since no pts devices are requested"); +#ifdef HAVE_ISULAD + if (conf->lsm_se_mount_context != NULL) { + if (asprintf(&devpts_mntopts, "%s,max=%zu,context=\"%s\"", + default_devpts_mntopts, conf->pty_max, conf->lsm_se_mount_context) < 0) { + return -1; + } + } else { + if (asprintf(&devpts_mntopts, "%s,max=%zu", default_devpts_mntopts, conf->pty_max) < 0) { + return -1; + } + } +#else ret = snprintf(devpts_mntopts, sizeof(devpts_mntopts), "%s,max=%zu", default_devpts_mntopts, conf->pty_max); if (ret < 0 || (size_t)ret >= sizeof(devpts_mntopts)) return -1; +#endif (void)umount2("/dev/pts", MNT_DETACH); @@ -1917,9 +1947,13 @@ static int setup_personality(int persona) return 0; } - +#ifdef HAVE_ISULAD +static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, + const struct lxc_terminal *console, const char *mount_label) +#else static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, const struct lxc_terminal *console) +#endif { int ret; char path[PATH_MAX]; @@ -1956,8 +1990,12 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, ret = fchmod(console->slave, S_IXUSR | S_IXGRP); if (ret < 0) return log_error_errno(-errno, errno, "Failed to set mode \"0%o\" to \"%s\"", S_IXUSR | S_IXGRP, console->name); - +#ifdef HAVE_ISULAD + // ret = safe_mount(console->name, path, "none", MS_BIND, 0, rootfs_path, mount_label); + ret = safe_mount(console->name, path, "bind", MS_BIND, 0, rootfs_path, mount_label); +#else ret = safe_mount(console->name, path, "none", MS_BIND, 0, rootfs_path); +#endif if (ret < 0) return log_error_errno(-1, errno, "Failed to mount \"%s\" on \"%s\"", console->name, path); #ifdef HAVE_ISULAD @@ -1967,9 +2005,15 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, return 0; } +#ifdef HAVE_ISULAD +static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, + const struct lxc_terminal *console, + char *ttydir, const char *mount_label) +#else static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, const struct lxc_terminal *console, char *ttydir) +#endif { int ret; char path[PATH_MAX], lxcpath[PATH_MAX]; @@ -2020,7 +2064,11 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, return log_error_errno(-errno, errno, "Failed to set mode \"0%o\" to \"%s\"", S_IXUSR | S_IXGRP, console->name); /* bind mount console->name to '/dev//console' */ +#ifdef HAVE_ISULAD + ret = safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs_path, mount_label); +#else ret = safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs_path); +#endif if (ret < 0) return log_error_errno(-1, errno, "Failed to mount \"%s\" on \"%s\"", console->name, lxcpath); DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath); @@ -2029,7 +2077,11 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, #endif /* bind mount '/dev//console' to '/dev/console' */ +#ifdef HAVE_ISULAD + ret = safe_mount(lxcpath, path, "none", MS_BIND, 0, rootfs_path, mount_label); +#else ret = safe_mount(lxcpath, path, "none", MS_BIND, 0, rootfs_path); +#endif if (ret < 0) return log_error_errno(-1, errno, "Failed to mount \"%s\" on \"%s\"", console->name, lxcpath); DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath); @@ -2038,15 +2090,26 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, return 0; } +#ifdef HAVE_ISULAD static int lxc_setup_console(const struct lxc_rootfs *rootfs, - const struct lxc_terminal *console, char *ttydir) + const struct lxc_terminal *console, char *ttydir, const char *mount_label) { + if (!ttydir) + return lxc_setup_dev_console(rootfs, console, mount_label); + return lxc_setup_ttydir_console(rootfs, console, ttydir, mount_label); +} +#else +static int lxc_setup_console(const struct lxc_rootfs *rootfs, + const struct lxc_terminal *console, char *ttydir) +{ if (!ttydir) return lxc_setup_dev_console(rootfs, console); return lxc_setup_ttydir_console(rootfs, console, ttydir); } +#endif + #ifdef HAVE_ISULAD static void parse_mntopt(char *opt, unsigned long *mflags, unsigned long *pflags, char **data, size_t size) { @@ -2226,10 +2289,17 @@ int parse_propagationopts(const char *mntopts, unsigned long *pflags) return 0; } +#ifdef HAVE_ISULAD +static int mount_entry(const char *fsname, const char *target, + const char *fstype, unsigned long mountflags, + unsigned long pflags, const char *data, bool optional, + bool dev, bool relative, const char *rootfs, const char *mount_label) +#else static int mount_entry(const char *fsname, const char *target, const char *fstype, unsigned long mountflags, unsigned long pflags, const char *data, bool optional, bool dev, bool relative, const char *rootfs) +#endif { int ret; char srcbuf[PATH_MAX]; @@ -2245,8 +2315,13 @@ static int mount_entry(const char *fsname, const char *target, srcpath = srcbuf; } +#ifdef HAVE_ISULAD + ret = safe_mount(srcpath, target, fstype, mountflags & ~MS_REMOUNT, data, + rootfs, mount_label); +#else ret = safe_mount(srcpath, target, fstype, mountflags & ~MS_REMOUNT, data, rootfs); +#endif if (ret < 0) { if (optional) return log_info_errno(0, errno, "Failed to mount \"%s\" on \"%s\" (optional)", @@ -2579,11 +2654,20 @@ static int check_mount_destination(const char *rootfs, const char *dest) /* rootfs, lxc_name, and lxc_path can be NULL when the container is created * without a rootfs. */ +#ifdef HAVE_ISULAD +static inline int mount_entry_on_generic(struct mntent *mntent, + const char *path, + const struct lxc_rootfs *rootfs, + const char *lxc_name, + const char *lxc_path, + const char *mount_label) +#else static inline int mount_entry_on_generic(struct mntent *mntent, const char *path, const struct lxc_rootfs *rootfs, const char *lxc_name, const char *lxc_path) +#endif { __do_free char *mntdata = NULL; unsigned long mntflags = 0, pflags = 0; @@ -2655,7 +2739,7 @@ static inline int mount_entry_on_generic(struct mntent *mntent, mntent->mnt_opts, rootfs_path); } else { ret = mount_entry(mntent->mnt_fsname, dest, mntent->mnt_type, mntflags, - pflags, mntdata, optional, dev, relative, rootfs_path); + pflags, mntdata, optional, dev, relative, rootfs_path, mount_label); } if (ret < 0) { @@ -2695,13 +2779,25 @@ static inline int mount_entry_on_systemfs(struct mntent *mntent) if (ret < 0 || ret >= sizeof(path)) return -1; +#ifdef HAVE_ISULAD + return mount_entry_on_generic(mntent, path, NULL, NULL, NULL, NULL); +#else return mount_entry_on_generic(mntent, path, NULL, NULL, NULL); +#endif } +#ifdef HAVE_ISULAD +static int mount_entry_on_absolute_rootfs(struct mntent *mntent, + const struct lxc_rootfs *rootfs, + const char *lxc_name, + const char *lxc_path, + const char *mount_label) +#else static int mount_entry_on_absolute_rootfs(struct mntent *mntent, const struct lxc_rootfs *rootfs, const char *lxc_name, const char *lxc_path) +#endif { int offset; char *aux; @@ -2736,14 +2832,25 @@ skipabs: ret = snprintf(path, PATH_MAX, "%s/%s", rootfs->mount, aux + offset); if (ret < 0 || ret >= PATH_MAX) return -1; - +#ifdef HAVE_ISULAD + return mount_entry_on_generic(mntent, path, rootfs, lxc_name, lxc_path, mount_label); +#else return mount_entry_on_generic(mntent, path, rootfs, lxc_name, lxc_path); +#endif } +#ifdef HAVE_ISULAD +static int mount_entry_on_relative_rootfs(struct mntent *mntent, + const struct lxc_rootfs *rootfs, + const char *lxc_name, + const char *lxc_path, + const char *mount_label) +#else static int mount_entry_on_relative_rootfs(struct mntent *mntent, const struct lxc_rootfs *rootfs, const char *lxc_name, const char *lxc_path) +#endif { int ret; char path[PATH_MAX]; @@ -2753,12 +2860,22 @@ static int mount_entry_on_relative_rootfs(struct mntent *mntent, if (ret < 0 || (size_t)ret >= sizeof(path)) return -1; +#ifdef HAVE_ISULAD + return mount_entry_on_generic(mntent, path, rootfs, lxc_name, lxc_path, mount_label); +#else return mount_entry_on_generic(mntent, path, rootfs, lxc_name, lxc_path); +#endif } +#ifdef HAVE_ISULAD +static int mount_file_entries(const struct lxc_conf *conf, + const struct lxc_rootfs *rootfs, FILE *file, + const char *lxc_name, const char *lxc_path, const char *mount_label) +#else static int mount_file_entries(const struct lxc_conf *conf, const struct lxc_rootfs *rootfs, FILE *file, const char *lxc_name, const char *lxc_path) +#endif { char buf[PATH_MAX]; struct mntent mntent; @@ -2786,22 +2903,30 @@ static int mount_file_entries(const struct lxc_conf *conf, free(mntent.mnt_fsname); return -1; } -#endif if (!rootfs->path) ret = mount_entry_on_systemfs(&mntent); else if (mntent.mnt_dir[0] != '/') ret = mount_entry_on_relative_rootfs(&mntent, rootfs, - lxc_name, lxc_path); + lxc_name, lxc_path, mount_label); else ret = mount_entry_on_absolute_rootfs(&mntent, rootfs, - lxc_name, lxc_path); + lxc_name, lxc_path, mount_label); -#ifdef HAVE_ISULAD free(mntent.mnt_fsname); mntent.mnt_fsname = NULL; free(mntent.mnt_dir); mntent.mnt_dir = NULL; +#else + + if (!rootfs->path) + ret = mount_entry_on_systemfs(&mntent); + else if (mntent.mnt_dir[0] != '/') + ret = mount_entry_on_relative_rootfs(&mntent, rootfs, + lxc_name, lxc_path); + else + ret = mount_entry_on_absolute_rootfs(&mntent, rootfs, + lxc_name, lxc_path); #endif if (ret < 0) @@ -2822,9 +2947,15 @@ static inline void __auto_endmntent__(FILE **f) #define __do_endmntent __attribute__((__cleanup__(__auto_endmntent__))) +#ifdef HAVE_ISULAD +static int setup_mount(const struct lxc_conf *conf, + const struct lxc_rootfs *rootfs, const char *fstab, + const char *lxc_name, const char *lxc_path, const char *mount_label) +#else static int setup_mount(const struct lxc_conf *conf, const struct lxc_rootfs *rootfs, const char *fstab, const char *lxc_name, const char *lxc_path) +#endif { __do_endmntent FILE *f = NULL; int ret; @@ -2836,7 +2967,11 @@ static int setup_mount(const struct lxc_conf *conf, if (!f) return log_error_errno(-1, errno, "Failed to open \"%s\"", fstab); +#ifdef HAVE_ISULAD + ret = mount_file_entries(conf, rootfs, f, lxc_name, lxc_path, mount_label); +#else ret = mount_file_entries(conf, rootfs, f, lxc_name, lxc_path); +#endif if (ret < 0) ERROR("Failed to set up mount entries"); @@ -2912,10 +3047,17 @@ FILE *make_anonymous_mount_file(struct lxc_list *mount, return f; } +#ifdef HAVE_ISULAD +static int setup_mount_entries(const struct lxc_conf *conf, + const struct lxc_rootfs *rootfs, + struct lxc_list *mount, const char *lxc_name, + const char *lxc_path, const char *mount_label) +#else static int setup_mount_entries(const struct lxc_conf *conf, const struct lxc_rootfs *rootfs, struct lxc_list *mount, const char *lxc_name, const char *lxc_path) +#endif { __do_fclose FILE *f = NULL; @@ -2923,7 +3065,11 @@ static int setup_mount_entries(const struct lxc_conf *conf, if (!f) return -1; +#ifdef HAVE_ISULAD + return mount_file_entries(conf, rootfs, f, lxc_name, lxc_path, mount_label); +#else return mount_file_entries(conf, rootfs, f, lxc_name, lxc_path); +#endif } #ifdef HAVE_ISULAD @@ -3892,8 +4038,11 @@ static int lxc_execute_bind_init(struct lxc_handler *handler) if (ret < 0 && errno != EEXIST) return log_error_errno(-1, errno, "Failed to create dummy \"%s\" file as bind mount target", destpath); } - +#ifdef HAVE_ISULAD + ret = safe_mount(path, destpath, "none", MS_BIND, NULL, conf->rootfs.mount, conf->lsm_se_mount_context); +#else ret = safe_mount(path, destpath, "none", MS_BIND, NULL, conf->rootfs.mount); +#endif if (ret < 0) return log_error_errno(-1, errno, "Failed to bind mount lxc.init.static into container"); @@ -4035,7 +4184,7 @@ static int lxc_setup_boot_id(void) #ifdef HAVE_ISULAD /* isulad: setup devices which will be populated in the container.*/ -static int setup_populate_devs(const struct lxc_rootfs *rootfs, struct lxc_list *devs) +static int setup_populate_devs(const struct lxc_rootfs *rootfs, struct lxc_list *devs, const char *mount_label) { int ret = 0; char *pathdirname = NULL; @@ -4104,7 +4253,7 @@ static int setup_populate_devs(const struct lxc_rootfs *rootfs, struct lxc_list } fclose(pathfile); if (safe_mount(hostpath, path, 0, MS_BIND, NULL, - rootfs->path ? rootfs->mount : NULL) != 0) { + rootfs->path ? rootfs->mount : NULL, mount_label) != 0) { SYSERROR("Failed bind mounting device %s from host into container", dev_elem->name); ret = -1; @@ -4761,7 +4910,8 @@ int lxc_setup(struct lxc_handler *handler) if (lxc_conf->autodev > 0) { #ifdef HAVE_ISULAD - ret = mount_autodev(name, &lxc_conf->rootfs, lxc_conf->autodevtmpfssize, lxcpath, lxc_conf->systemd); + ret = mount_autodev(name, &lxc_conf->rootfs, lxc_conf->autodevtmpfssize, lxcpath, + lxc_conf->systemd, lxc_conf->lsm_se_mount_context); #else ret = mount_autodev(name, &lxc_conf->rootfs, lxc_conf->autodevtmpfssize, lxcpath); #endif @@ -4775,14 +4925,22 @@ int lxc_setup(struct lxc_handler *handler) ret = lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & ~LXC_AUTO_CGROUP_MASK, handler); if (ret < 0) return log_error(-1, "Failed to setup first automatic mounts"); - +#ifdef HAVE_ISULAD + ret = setup_mount(lxc_conf, &lxc_conf->rootfs, lxc_conf->fstab, name, lxcpath, lxc_conf->lsm_se_mount_context); +#else ret = setup_mount(lxc_conf, &lxc_conf->rootfs, lxc_conf->fstab, name, lxcpath); +#endif if (ret < 0) return log_error(-1, "Failed to setup mounts"); if (!lxc_list_empty(&lxc_conf->mount_list)) { +#ifdef HAVE_ISULAD + ret = setup_mount_entries(lxc_conf, &lxc_conf->rootfs, + &lxc_conf->mount_list, name, lxcpath, lxc_conf->lsm_se_mount_context); +#else ret = setup_mount_entries(lxc_conf, &lxc_conf->rootfs, &lxc_conf->mount_list, name, lxcpath); +#endif if (ret < 0) return log_error(-1, "Failed to setup mount entries"); #ifdef HAVE_ISULAD @@ -4828,8 +4986,11 @@ int lxc_setup(struct lxc_handler *handler) ret = run_lxc_hooks(name, "autodev", lxc_conf, NULL); if (ret < 0) return log_error(-1, "Failed to run autodev hooks"); - +#ifdef HAVE_ISULAD + ret = lxc_fill_autodev(&lxc_conf->rootfs, lxc_conf->lsm_se_mount_context); +#else ret = lxc_fill_autodev(&lxc_conf->rootfs); +#endif if (ret < 0) return log_error(-1, "Failed to populate \"/dev\""); } @@ -4837,7 +4998,7 @@ int lxc_setup(struct lxc_handler *handler) #ifdef HAVE_ISULAD /* isulad: setup devices which will be populated in the container. */ if (!lxc_list_empty(&lxc_conf->populate_devs) && setup_dev) { - if (setup_populate_devs(&lxc_conf->rootfs, &lxc_conf->populate_devs) != 0) { + if (setup_populate_devs(&lxc_conf->rootfs, &lxc_conf->populate_devs, lxc_conf->lsm_se_mount_context) != 0) { return log_error(-1, "Failed to setup devices in the container"); } } @@ -4846,9 +5007,13 @@ int lxc_setup(struct lxc_handler *handler) /* Make sure any start hooks are in the container */ if (!verify_start_hooks(lxc_conf)) return log_error(-1, "Failed to verify start hooks"); - +#ifdef HAVE_ISULAD + ret = lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console, + lxc_conf->ttys.dir, lxc_conf->lsm_se_mount_context); +#else ret = lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console, lxc_conf->ttys.dir); +#endif if (ret < 0) return log_error(-1, "Failed to setup console"); diff --git a/src/lxc/conf.h b/src/lxc/conf.h index 4b6409e3e..c9265b65e 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -442,31 +442,36 @@ struct lxc_conf { } shmount; #ifdef HAVE_ISULAD - /* - * isulad: support oci hook - * */ + /* support oci hook */ oci_runtime_spec_hooks *ocihooks; - /* isulad add: init args used to repalce init_cmd*/ + /* init args used to repalce init_cmd */ char **init_argv; size_t init_argc; gid_t *init_groups; size_t init_groups_len; - /* populate devices*/ + /* populate devices */ struct lxc_list populate_devs; - mode_t umask; //umask value + mode_t umask; // umask value char *container_info_file; - int exit_fd; /* exit fifo fd*/ + /* exit fifo fd*/ + int exit_fd; + + /* record error messages */ + char *errmsg; - char *errmsg; /* record error messages */ + /* pipdfd for get error message of child or grandchild process */ + int errpipe[2]; - int errpipe[2];//pipdfd for get error message of child or grandchild process. + /* systemd value */ + char *systemd; - char *systemd; //systemd value + /* Linux Security Modules SELinux context for device mount */ + char *lsm_se_mount_context; #endif }; diff --git a/src/lxc/confile.c b/src/lxc/confile.c index b1d101a9d..f108b37b4 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -158,6 +158,7 @@ lxc_config_define(systemd); lxc_config_define(console_log_driver); lxc_config_define(console_syslog_tag); lxc_config_define(console_syslog_facility); +lxc_config_define(selinux_mount_context); #endif /* @@ -247,7 +248,7 @@ static struct lxc_config_t config_jump_table[] = { { "lxc.net.veth.ipv6.route", set_config_net_veth_ipv6_route, get_config_net_veth_ipv6_route, clr_config_net_veth_ipv6_route, }, { "lxc.net.", set_config_net_nic, get_config_net_nic, clr_config_net_nic, }, { "lxc.net", set_config_net, get_config_net, clr_config_net, }, - { "lxc.no_new_privs", set_config_no_new_privs, get_config_no_new_privs, clr_config_no_new_privs, }, + { "lxc.no_new_privs", set_config_no_new_privs, get_config_no_new_privs, clr_config_no_new_privs, }, { "lxc.prlimit", set_config_prlimit, get_config_prlimit, clr_config_prlimit, }, { "lxc.pty.max", set_config_pty_max, get_config_pty_max, clr_config_pty_max, }, { "lxc.rootfs.managed", set_config_rootfs_managed, get_config_rootfs_managed, clr_config_rootfs_managed, }, @@ -282,6 +283,7 @@ static struct lxc_config_t config_jump_table[] = { { "lxc.console.logdriver", set_config_console_log_driver, get_config_console_log_driver, clr_config_console_log_driver, }, { "lxc.console.syslog_tag", set_config_console_syslog_tag, get_config_console_syslog_tag, clr_config_console_syslog_tag, }, { "lxc.console.syslog_facility", set_config_console_syslog_facility, get_config_console_syslog_facility, clr_config_console_syslog_facility, }, + { "lxc.selinux.mount_context", set_config_selinux_mount_context, get_config_selinux_mount_context, clr_config_selinux_mount_context, }, #endif }; @@ -6685,6 +6687,16 @@ static int set_config_console_syslog_facility(const char *key, const char *value return 0; } +static int set_config_selinux_mount_context(const char *key, const char *value, + struct lxc_conf *lxc_conf, void *data) +{ + if (value != NULL && strcmp(value, "unconfined_t") == 0) { + return set_config_string_item(&lxc_conf->lsm_se_mount_context, NULL); + } + + return set_config_string_item(&lxc_conf->lsm_se_mount_context, value); +} + static int get_config_console_log_driver(const char *key, char *retv, int inlen, struct lxc_conf *c, void *data) { @@ -6703,6 +6715,12 @@ static int get_config_console_syslog_facility(const char *key, char *retv, int i return lxc_get_conf_int(c, retv, inlen, c->console.log_syslog_facility); } +static int get_config_selinux_mount_context(const char *key, char *retv, int inlen, + struct lxc_conf *c, void *data) +{ + return lxc_get_conf_str(retv, inlen, c->lsm_se_mount_context); +} + static inline int clr_config_console_log_driver(const char *key, struct lxc_conf *c, void *data) { @@ -6726,4 +6744,11 @@ static inline int clr_config_console_syslog_facility(const char *key, return 0; } +static inline int clr_config_selinux_mount_context(const char *key, + struct lxc_conf *c, void *data) +{ + free(c->lsm_se_mount_context); + c->lsm_se_mount_context = NULL; + return 0; +} #endif diff --git a/src/lxc/lsm/lsm.c b/src/lxc/lsm/lsm.c index 553e0c99a..2f87dd68d 100644 --- a/src/lxc/lsm/lsm.c +++ b/src/lxc/lsm/lsm.c @@ -168,6 +168,26 @@ int lsm_process_label_set(const char *label, struct lxc_conf *conf, return drv->process_label_set(label, conf, on_exec); } +#ifdef HAVE_ISULAD +int lsm_file_label_set(const char *path, const char *label) +{ + if (!drv) { + ERROR("LSM driver not inited"); + return -1; + } + return drv->file_label_set(path, label); +} + +int lsm_relabel(const char *path, const char *label, bool share) +{ + if (!drv) { + ERROR("LSM driver not inited"); + return -1; + } + return drv->relabel(path, label, share); +} +#endif + int lsm_process_prepare(struct lxc_conf *conf, const char *lxcpath) { if (!drv) { diff --git a/src/lxc/lsm/lsm.h b/src/lxc/lsm/lsm.h index ee578bb03..4872f5598 100644 --- a/src/lxc/lsm/lsm.h +++ b/src/lxc/lsm/lsm.h @@ -17,6 +17,10 @@ struct lsm_drv { char *(*process_label_get)(pid_t pid); int (*process_label_set)(const char *label, struct lxc_conf *conf, bool on_exec); +#ifdef HAVE_ISULAD + int (*file_label_set)(const char *path, const char *label); + int (*relabel)(const char *path, const char *label, bool share); +#endif int (*keyring_label_set)(char* label); int (*prepare)(struct lxc_conf *conf, const char *lxcpath); void (*cleanup)(struct lxc_conf *conf, const char *lxcpath); @@ -32,6 +36,10 @@ extern int lsm_process_label_set(const char *label, struct lxc_conf *conf, extern int lsm_process_label_fd_get(pid_t pid, bool on_exec); extern int lsm_process_label_set_at(int label_fd, const char *label, bool on_exec); +#ifdef HAVE_ISULAD +extern int lsm_file_label_set(const char *path, const char *label); +extern int lsm_relabel(const char *path, const char *label, bool share); +#endif extern void lsm_process_cleanup(struct lxc_conf *conf, const char *lxcpath); extern int lsm_keyring_label_set(char *label); diff --git a/src/lxc/lsm/selinux.c b/src/lxc/lsm/selinux.c index dba0ab584..5bc9843e4 100644 --- a/src/lxc/lsm/selinux.c +++ b/src/lxc/lsm/selinux.c @@ -16,6 +16,10 @@ #include "log.h" #include "lsm.h" +#ifdef HAVE_ISULAD +#include +#endif + #define DEFAULT_LABEL "unconfined_t" lxc_log_define(selinux, lsm); @@ -85,6 +89,225 @@ static int selinux_process_label_set(const char *inlabel, struct lxc_conf *conf, return 0; } +#ifdef HAVE_ISULAD +/* + * selinux_file_label_set: Set SELinux context of a file + * + * @path : a file + * @label : label string + * + * Returns 0 on success, < 0 on failure + */ +static int selinux_file_label_set(const char *path, const char *label) +{ + int ret; + + if (path == NULL || label == NULL || strcmp(label, "unconfined_t") == 0) { + return 0; + } + + ret = lsetfilecon(path, label); + if (ret != 0) { + SYSERROR("Failed to setSELinux context to \"%s\": %s", label, path); + return -1; + } + + INFO("Changed SELinux context to \"%s\": %s", label, path); + return 0; +} + +/* + * is_exclude_relabel_path: Determine whether it is a excluded path to label + * + * @path : a file or directory + * + * Returns 0 on success, < 0 on failure + */ +static bool is_exclude_relabel_path(const char *path) +{ + const char *exclude_path[] = { "/", "/usr", "/etc", "/tmp", "/home", "/run", "/var", "/root" }; + size_t i; + + for (i = 0; i < sizeof(exclude_path) / sizeof(char *); i++) { + if (strcmp(path, exclude_path[i]) == 0) { + return true; + } + } + + return false; +} + +/* + * bad_prefix: Prevent users from relabing system files + * + * @path : a file or directory + * + * Returns 0 on success, < 0 on failure + */ +static int bad_prefix(const char *fpath) +{ + const char *bad_prefixes = "/usr"; + + if (fpath == NULL) { + ERROR("Empty file path"); + return -1; + } + + if (strncmp(fpath, bad_prefixes, strlen(bad_prefixes)) == 0) { + ERROR("relabeling content in %s is not allowed", bad_prefixes); + return -1; + } + + return 0; +} + +/* + * recurse_set_file_label: Recursively label files or folders + * + * @path : a file or directory + * @label : label string + * + * Returns 0 on success, < 0 on failure + */ +static int recurse_set_file_label(const char *basePath, const char *label) +{ + int ret = 0; + DIR *dir = NULL; + struct dirent *ptr = NULL; + char base[PATH_MAX] = { 0 }; + + if ((dir = opendir(basePath)) == NULL) { + ERROR("Failed to Open dir: %s", basePath); + return -1; + } + + ret = lsetfilecon(basePath, label); + if (ret != 0) { + ERROR("Failed to set file label"); + goto out; + } + + while ((ptr = readdir(dir)) != NULL) { + if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) { + continue; + } else { + int nret = snprintf(base, sizeof(base), "%s/%s", basePath, ptr->d_name); + if (nret < 0 || nret >= sizeof(base)) { + ERROR("Failed to get path"); + ret = -1; + goto out; + } + if (ptr->d_type == DT_DIR) { + ret = recurse_set_file_label(base, label); + if (ret != 0) { + ERROR("Failed to set dir label"); + goto out; + } + } else { + ret = lsetfilecon(base, label); + if (ret != 0) { + ERROR("Failed to set file label"); + goto out; + } + } + } + } + +out: + closedir(dir); + return ret; +} + +/* + * selinux_chcon: Chcon changes the `fpath` file object to the SELinux label `label`. + * If `fpath` is a directory and `recurse`` is true, Chcon will walk the + * directory tree setting the label. + * + * @fpath : a file or directory + * @label : label string + * @recurse : whether to recurse + * + * Returns 0 on success, < 0 on failure + */ +static int selinux_chcon(const char *fpath, const char *label, bool recurse) +{ + struct stat s_buf; + + if (fpath == NULL) { + ERROR("Empty file path"); + return -1; + } + + if (label == NULL) { + return 0; + } + + if (bad_prefix(fpath) != 0) { + return -1; + } + if (stat(fpath, &s_buf) != 0) { + return -1; + } + if (recurse && S_ISDIR(s_buf.st_mode)) { + return recurse_set_file_label(fpath, label); + } + + if (lsetfilecon(fpath, label) != 0) { + ERROR("Failed to set file label"); + return -1; + } + + return 0; +} + +/* + * selinux_relabel: Relabel changes the label of path to the filelabel string. + * It changes the MCS label to s0 if shared is true. + * This will allow all containers to share the content. + * + * @path : a file or directory + * @label : label string + * @shared : whether to use share mode + * + * Returns 0 on success, < 0 on failure + */ +static int selinux_relabel(const char *path, const char *label, bool shared) +{ + int ret = 0; + char *tmp_file_label = NULL; + + if (label == NULL) { + return 0; + } + + tmp_file_label = strdup(label); + if (is_exclude_relabel_path(path)) { + ERROR("SELinux relabeling of %s is not allowed", path); + ret = -1; + goto out; + } + + if (shared) { + context_t c = context_new(label); + context_range_set(c, "s0"); + free(tmp_file_label); + tmp_file_label = strdup(context_str(c)); + context_free(c); + } + + if (selinux_chcon(path, tmp_file_label, true) != 0) { + ERROR("Failed to modify %s's selinux context: %s", path, tmp_file_label); + ret = -1; + goto out; + } + +out: + free(tmp_file_label); + return ret; +} + +#endif + /* * selinux_keyring_label_set: Set SELinux context that will be assigned to the keyring * @@ -103,6 +326,10 @@ static struct lsm_drv selinux_drv = { .process_label_get = selinux_process_label_get, .process_label_set = selinux_process_label_set, .keyring_label_set = selinux_keyring_label_set, +#ifdef HAVE_ISULAD + .file_label_set = selinux_file_label_set, + .relabel = selinux_relabel, +#endif }; struct lsm_drv *lsm_selinux_drv_init(void) diff --git a/src/lxc/utils.c b/src/lxc/utils.c index 4e418fbb9..032176b1b 100644 --- a/src/lxc/utils.c +++ b/src/lxc/utils.c @@ -1097,6 +1097,37 @@ out: return dirfd; } +#ifdef HAVE_ISULAD +static int format_mount_label(const char *data, const char *mount_label, char **mnt_opts) +{ + int ret = 0; + + if (mount_label != NULL) { + if (data != NULL) { + ret = asprintf(mnt_opts, "%s,context=\"%s\"", data, mount_label); + } else { + ret = asprintf(mnt_opts, "context=\"%s\"", mount_label); + } + + return ret < 0 ? -1 : 0; + } + + *mnt_opts = data != NULL ? strdup(data) : NULL; + return 0; +} + +static int receive_mount_options(const char *data, const char *mount_label, + const char *fstype, char **mnt_opts) +{ + // SELinux kernels don't support labeling of /proc or /sys + if (fstype != NULL && (strcmp(fstype, "proc") == 0 || strcmp(fstype, "sysfs") == 0)) { + return format_mount_label(data, NULL, mnt_opts); + } + + return format_mount_label(data, mount_label, mnt_opts); +} +#endif + /* * Safely mount a path into a container, ensuring that the mount target * is under the container's @rootfs. (If @rootfs is NULL, then the container @@ -1105,14 +1136,22 @@ out: * CAVEAT: This function must not be used for other purposes than container * setup before executing the container's init */ +#ifdef HAVE_ISULAD +int safe_mount(const char *src, const char *dest, const char *fstype, + unsigned long flags, const void *data, const char *rootfs, const char *mount_label) +#else int safe_mount(const char *src, const char *dest, const char *fstype, unsigned long flags, const void *data, const char *rootfs) +#endif { int destfd, ret, saved_errno; /* Only needs enough for /proc/self/fd/. */ char srcbuf[50], destbuf[50]; int srcfd = -1; const char *mntsrc = src; +#ifdef HAVE_ISULAD + __do_free char *mnt_opts = NULL; +#endif if (!rootfs) rootfs = ""; @@ -1155,8 +1194,23 @@ int safe_mount(const char *src, const char *dest, const char *fstype, return -EINVAL; } +#ifdef HAVE_ISULAD + if (receive_mount_options(data, mount_label, fstype, &mnt_opts) != 0) { + ERROR("Failed to receive mount options"); + return -EINVAL; + } + + ret = mount(mntsrc, destbuf, fstype, flags, mnt_opts); + saved_errno = errno; + if (ret < 0 && strcmp(fstype, "mqueue") == 0) { + INFO("older kernels don't support labeling of /dev/mqueue, retry without selinux context"); + ret = mount(mntsrc, destbuf, fstype, flags, data); + saved_errno = errno; + } +#else ret = mount(mntsrc, destbuf, fstype, flags, data); saved_errno = errno; +#endif if (srcfd != -1) close(srcfd); @@ -1167,6 +1221,18 @@ int safe_mount(const char *src, const char *dest, const char *fstype, return ret; } +#ifdef HAVE_ISULAD + if (strcmp(fstype, "mqueue") == 0 && lsm_file_label_set(dest, mount_label) != 0) { + ERROR("Failed to set file label on %s", dest); + return -EINVAL; + } + + if (strcmp(fstype, "bind") == 0 && lsm_relabel(src, mount_label, false) != 0) { + ERROR("Failed to reabel %s with %s", src, mount_label); + return -EINVAL; + } +#endif + return 0; } @@ -1233,7 +1299,11 @@ domount: if (!strcmp(rootfs, "")) ret = mount("proc", path, "proc", 0, NULL); else +#ifdef HAVE_ISULAD + ret = safe_mount("proc", path, "proc", 0, NULL, rootfs, NULL); +#else ret = safe_mount("proc", path, "proc", 0, NULL, rootfs); +#endif if (ret < 0) return -1; diff --git a/src/lxc/utils.h b/src/lxc/utils.h index 39ef5792f..4d1c49bab 100644 --- a/src/lxc/utils.h +++ b/src/lxc/utils.h @@ -220,9 +220,15 @@ extern char *choose_init(const char *rootfs); extern bool switch_to_ns(pid_t pid, const char *ns); extern char *get_template_path(const char *t); extern int open_without_symlink(const char *target, const char *prefix_skip); +#ifdef HAVE_ISULAD +extern int safe_mount(const char *src, const char *dest, const char *fstype, + unsigned long flags, const void *data, + const char *rootfs, const char *mount_label); +#else extern int safe_mount(const char *src, const char *dest, const char *fstype, unsigned long flags, const void *data, const char *rootfs); +#endif extern int lxc_mount_proc_if_needed(const char *rootfs); extern int open_devnull(void); extern int set_stdfds(int fd); -- 2.25.1