382 lines
10 KiB
Diff
382 lines
10 KiB
Diff
From 8ae551897a4ab1c56019767640d0600eaebc993d Mon Sep 17 00:00:00 2001
|
|
From: tanyifeng <tanyifeng1@huawei.com>
|
|
Date: Sat, 12 Jan 2019 15:55:52 +0800
|
|
Subject: [PATCH 016/131] add masked paths and ro paths
|
|
|
|
Signed-off-by: LiFeng <lifeng68@huawei.com>
|
|
---
|
|
src/lxc/conf.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++
|
|
src/lxc/conf.h | 8 +++
|
|
src/lxc/confile.c | 113 +++++++++++++++++++++++++++++++++++++-
|
|
3 files changed, 255 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
|
|
index 5065e697..537f956c 100644
|
|
--- a/src/lxc/conf.c
|
|
+++ b/src/lxc/conf.c
|
|
@@ -1343,6 +1343,95 @@ static int lxc_mount_rootfs(struct lxc_conf *conf)
|
|
return 0;
|
|
}
|
|
|
|
+
|
|
+// maskPath masks the top of the specified path inside a container to avoid
|
|
+// security issues from processes reading information from non-namespace aware
|
|
+// mounts ( proc/kcore ).
|
|
+static bool mask_path(const char *path)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ if (!path)
|
|
+ return true;
|
|
+
|
|
+ ret = mount("/dev/null", path, "", MS_BIND, "");
|
|
+ if (ret < 0 && errno != ENOENT) {
|
|
+ if (errno == ENOTDIR) {
|
|
+ ret = mount("tmpfs", path, "tmpfs", MS_RDONLY, "");
|
|
+ if (ret < 0)
|
|
+ goto error;
|
|
+ return true;
|
|
+ }
|
|
+ goto error;
|
|
+ }
|
|
+ return true;
|
|
+
|
|
+error:
|
|
+ SYSERROR("Failed to mask path \"%s\": %s", path, strerror(errno));
|
|
+ return false;
|
|
+}
|
|
+
|
|
+// remount_readonly will bind over the top of an existing path and ensure that it is read-only.
|
|
+static bool remount_readonly(const char *path)
|
|
+{
|
|
+ int ret, savederrno, i;
|
|
+
|
|
+ if (!path)
|
|
+ return true;
|
|
+
|
|
+ for (i = 0; i < 5; i++) {
|
|
+ ret = mount("", path, "", MS_REMOUNT | MS_RDONLY, "");
|
|
+ if (ret < 0 && errno != ENOENT) {
|
|
+ if (errno == EINVAL) {
|
|
+ // Probably not a mountpoint, use bind-mount
|
|
+ ret = mount(path, path, "", MS_BIND, "");
|
|
+ if (ret < 0)
|
|
+ goto on_error;
|
|
+ ret = mount(path, path, "", MS_BIND | MS_REMOUNT | MS_RDONLY | MS_REC | \
|
|
+ MS_NOEXEC | MS_NOSUID | MS_NODEV, "");
|
|
+ if (ret < 0)
|
|
+ goto on_error;
|
|
+ } else if (errno == EBUSY) {
|
|
+ DEBUG("Try to mount \"%s\" to readonly after 100ms.", path);
|
|
+ usleep(100 * 1000);
|
|
+ continue;
|
|
+ } else {
|
|
+ goto on_error;
|
|
+ }
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+on_error:
|
|
+ SYSERROR("Unable to mount \"%s\" to readonly", path);
|
|
+ return false;
|
|
+}
|
|
+
|
|
+// isulad: setup rootfs masked paths
|
|
+static int setup_rootfs_maskedpaths(struct lxc_list *maskedpaths)
|
|
+{
|
|
+ struct lxc_list *it;
|
|
+
|
|
+ lxc_list_for_each(it, maskedpaths) {
|
|
+ if (!mask_path((char *)it->elem))
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+// isulad: setup rootfs ro paths
|
|
+static int setup_rootfs_ropaths(struct lxc_list *ropaths)
|
|
+{
|
|
+ struct lxc_list *it;
|
|
+
|
|
+ lxc_list_for_each(it, ropaths) {
|
|
+ if (!remount_readonly((char *)it->elem))
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
int lxc_chroot(const struct lxc_rootfs *rootfs)
|
|
{
|
|
int i, ret;
|
|
@@ -2759,6 +2848,8 @@ struct lxc_conf *lxc_conf_init(void)
|
|
|
|
/* isulad add begin */
|
|
lxc_list_init(&new->populate_devs);
|
|
+ lxc_list_init(&new->rootfs.maskedpaths);
|
|
+ lxc_list_init(&new->rootfs.ropaths);
|
|
new->exit_fd = -1;
|
|
/* isulad add end */
|
|
|
|
@@ -3759,6 +3850,22 @@ int lxc_setup(struct lxc_handler *handler)
|
|
if (ret < 0)
|
|
return -1;
|
|
|
|
+ //isulad: setup rootfs masked paths
|
|
+ if (!lxc_list_empty(&lxc_conf->rootfs.maskedpaths)) {
|
|
+ if (setup_rootfs_maskedpaths(&lxc_conf->rootfs.maskedpaths)) {
|
|
+ ERROR("failed to setup maskedpaths");
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // isulad: setup rootfs ro paths
|
|
+ if (!lxc_list_empty(&lxc_conf->rootfs.ropaths)) {
|
|
+ if (setup_rootfs_ropaths(&lxc_conf->rootfs.ropaths)) {
|
|
+ ERROR("failed to setup readonlypaths");
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
ret = setup_personality(lxc_conf->personality);
|
|
if (ret < 0) {
|
|
ERROR("Failed to set personality");
|
|
@@ -4147,6 +4254,32 @@ int lxc_clear_populate_devices(struct lxc_conf *c)
|
|
return 0;
|
|
}
|
|
|
|
+/*isulad: clear rootfs masked paths*/
|
|
+int lxc_clear_rootfs_masked_paths(struct lxc_conf *c)
|
|
+{
|
|
+ struct lxc_list *it,*next;
|
|
+
|
|
+ lxc_list_for_each_safe(it, &c->rootfs.maskedpaths, next) {
|
|
+ lxc_list_del(it);
|
|
+ free(it->elem);
|
|
+ free(it);
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*isulad: clear rootfs ro paths*/
|
|
+int lxc_clear_rootfs_ro_paths(struct lxc_conf *c)
|
|
+{
|
|
+ struct lxc_list *it,*next;
|
|
+
|
|
+ lxc_list_for_each_safe(it, &c->rootfs.ropaths, next) {
|
|
+ lxc_list_del(it);
|
|
+ free(it->elem);
|
|
+ free(it);
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
void lxc_conf_free(struct lxc_conf *conf)
|
|
{
|
|
if (!conf)
|
|
@@ -4195,6 +4328,8 @@ void lxc_conf_free(struct lxc_conf *conf)
|
|
/* isulad add begin */
|
|
lxc_clear_init_args(conf);
|
|
lxc_clear_populate_devices(conf);
|
|
+ lxc_clear_rootfs_masked_paths(conf);
|
|
+ lxc_clear_rootfs_ro_paths(conf);
|
|
free(conf->container_info_file);
|
|
if (conf->exit_fd != -1)
|
|
close(conf->exit_fd);
|
|
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
|
|
index 2d939cd2..79278128 100644
|
|
--- a/src/lxc/conf.h
|
|
+++ b/src/lxc/conf.h
|
|
@@ -160,6 +160,8 @@ struct lxc_tty_info {
|
|
* @options : mount options
|
|
* @mountflags : the portion of @options that are flags
|
|
* @data : the portion of @options that are not flags
|
|
+ * @maskedpaths: A list of paths to be msked over inside the container
|
|
+ * @ropaths : A list of paths to be remounted with readonly inside the container
|
|
*/
|
|
struct lxc_rootfs {
|
|
char *path;
|
|
@@ -168,6 +170,10 @@ struct lxc_rootfs {
|
|
char *options;
|
|
unsigned long mountflags;
|
|
char *data;
|
|
+ /* isulad: maskedpaths */
|
|
+ struct lxc_list maskedpaths;
|
|
+ /* isulad: ropaths */
|
|
+ struct lxc_list ropaths;
|
|
};
|
|
|
|
/*
|
|
@@ -477,6 +483,8 @@ extern int lxc_clear_procs(struct lxc_conf *c, const char *key);
|
|
/* isulad add begin */
|
|
int lxc_clear_init_args(struct lxc_conf *lxc_conf);
|
|
int lxc_clear_populate_devices(struct lxc_conf *c);
|
|
+int lxc_clear_rootfs_masked_paths(struct lxc_conf *c);
|
|
+int lxc_clear_rootfs_ro_paths(struct lxc_conf *c);
|
|
|
|
/* isulad add end */
|
|
|
|
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
|
|
index e7822115..e1999656 100644
|
|
--- a/src/lxc/confile.c
|
|
+++ b/src/lxc/confile.c
|
|
@@ -139,6 +139,8 @@ lxc_config_define(pty_max);
|
|
lxc_config_define(rootfs_mount);
|
|
lxc_config_define(rootfs_options);
|
|
lxc_config_define(rootfs_path);
|
|
+lxc_config_define(rootfs_masked_paths);
|
|
+lxc_config_define(rootfs_ro_paths);
|
|
lxc_config_define(seccomp_profile);
|
|
lxc_config_define(selinux_context);
|
|
lxc_config_define(signal_halt);
|
|
@@ -243,6 +245,8 @@ static struct lxc_config_t config_jump_table[] = {
|
|
/*isulad add begin*/
|
|
{ "lxc.isulad.init.args", set_config_init_args, get_config_init_args, clr_config_init_args, },
|
|
{ "lxc.isulad.populate.device", set_config_populate_device, get_config_populate_device, clr_config_populate_device, },
|
|
+ { "lxc.isulad.rootfs.maskedpaths", set_config_rootfs_masked_paths, get_config_rootfs_masked_paths, clr_config_rootfs_masked_paths, },
|
|
+ { "lxc.isulad.rootfs.ropaths", set_config_rootfs_ro_paths, get_config_rootfs_ro_paths, clr_config_rootfs_ro_paths, },
|
|
/*isulad add end*/
|
|
};
|
|
|
|
@@ -2224,7 +2228,7 @@ static int set_config_init_args(const char *key, const char *value,
|
|
return 0;
|
|
}
|
|
|
|
-/* isulad: set config for init args */
|
|
+/* isulad: set config for populate device */
|
|
static int set_config_populate_device(const char *key, const char *value,
|
|
struct lxc_conf *lxc_conf, void *data)
|
|
{
|
|
@@ -2308,6 +2312,62 @@ on_error:
|
|
free(dev_elem);
|
|
}
|
|
return -1;
|
|
+}
|
|
+
|
|
+/* isulad: set config for rootfs masked paths */
|
|
+static int set_config_rootfs_masked_paths(const char *key, const char *value,
|
|
+ struct lxc_conf *lxc_conf, void *data)
|
|
+{
|
|
+ struct lxc_list *list_item = NULL;
|
|
+
|
|
+ if (lxc_config_value_empty(value))
|
|
+ return lxc_clear_rootfs_masked_paths(lxc_conf);
|
|
+
|
|
+ list_item = malloc(sizeof(*list_item));
|
|
+ if (!list_item)
|
|
+ goto on_error;
|
|
+
|
|
+ list_item->elem = strdup(value);
|
|
+
|
|
+ if (!list_item->elem)
|
|
+ goto on_error;
|
|
+
|
|
+ lxc_list_add_tail(&lxc_conf->rootfs.maskedpaths, list_item);
|
|
+
|
|
+ return 0;
|
|
+
|
|
+on_error:
|
|
+ free(list_item);
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+/* isulad: set config for rootfs ro paths */
|
|
+static int set_config_rootfs_ro_paths(const char *key, const char *value,
|
|
+ struct lxc_conf *lxc_conf, void *data)
|
|
+{
|
|
+ struct lxc_list *list_item = NULL;
|
|
+
|
|
+ if (lxc_config_value_empty(value))
|
|
+ return lxc_clear_rootfs_ro_paths(lxc_conf);
|
|
+
|
|
+ list_item = malloc(sizeof(*list_item));
|
|
+ if (!list_item)
|
|
+ goto on_error;
|
|
+
|
|
+ list_item->elem = strdup(value);
|
|
+
|
|
+ if (!list_item->elem)
|
|
+ goto on_error;
|
|
+
|
|
+ lxc_list_add_tail(&lxc_conf->rootfs.ropaths, list_item);
|
|
+
|
|
+ return 0;
|
|
+
|
|
+on_error:
|
|
+ free(list_item);
|
|
+
|
|
+ return -1;
|
|
|
|
}
|
|
|
|
@@ -3889,6 +3949,43 @@ static int get_config_populate_device(const char *key, char *retv, int inlen,
|
|
return fulllen;
|
|
}
|
|
|
|
+// isulad: get config rootfs masked paths
|
|
+static int get_config_rootfs_masked_paths(const char *key, char *retv, int inlen,
|
|
+ struct lxc_conf *c, void *data)
|
|
+{
|
|
+ int len, fulllen = 0;
|
|
+ struct lxc_list *it;
|
|
+
|
|
+ if (!retv)
|
|
+ inlen = 0;
|
|
+ else
|
|
+ memset(retv, 0, inlen);
|
|
+
|
|
+ lxc_list_for_each(it, &c->rootfs.maskedpaths) {
|
|
+ strprint(retv, inlen, "%s\n", (char *)it->elem);
|
|
+ }
|
|
+
|
|
+ return fulllen;
|
|
+}
|
|
+
|
|
+// isulad: get config rootfs ro paths
|
|
+static int get_config_rootfs_ro_paths(const char *key, char *retv, int inlen,
|
|
+ struct lxc_conf *c, void *data)
|
|
+{
|
|
+ int len, fulllen = 0;
|
|
+ struct lxc_list *it;
|
|
+
|
|
+ if (!retv)
|
|
+ inlen = 0;
|
|
+ else
|
|
+ memset(retv, 0, inlen);
|
|
+
|
|
+ lxc_list_for_each(it, &c->rootfs.ropaths) {
|
|
+ strprint(retv, inlen, "%s\n", (char *)it->elem);
|
|
+ }
|
|
+
|
|
+ return fulllen;
|
|
+}
|
|
|
|
/* Callbacks to clear config items. */
|
|
static inline int clr_config_personality(const char *key, struct lxc_conf *c,
|
|
@@ -4708,6 +4805,20 @@ static inline int clr_config_populate_device(const char *key, struct lxc_conf *c
|
|
return lxc_clear_populate_devices(c);
|
|
}
|
|
|
|
+/* isulad: clr config rootfs masked paths */
|
|
+static inline int clr_config_rootfs_masked_paths(const char *key, struct lxc_conf *c,
|
|
+ void *data)
|
|
+{
|
|
+ return lxc_clear_rootfs_masked_paths(c);
|
|
+}
|
|
+
|
|
+/* isulad: clr config rootfs ro paths */
|
|
+static inline int clr_config_rootfs_ro_paths(const char *key, struct lxc_conf *c,
|
|
+ void *data)
|
|
+{
|
|
+ return lxc_clear_rootfs_ro_paths(c);
|
|
+}
|
|
+
|
|
static int get_config_net_nic(const char *key, char *retv, int inlen,
|
|
struct lxc_conf *c, void *data)
|
|
{
|
|
--
|
|
2.23.0
|
|
|