358 lines
9.7 KiB
Diff
358 lines
9.7 KiB
Diff
From c5ea37649d728630df34e1af22908b8e8124f772 Mon Sep 17 00:00:00 2001
|
|
From: wujing <wujing50@huawei.com>
|
|
Date: Mon, 13 Apr 2020 09:11:21 -0400
|
|
Subject: [PATCH 15/49] add masked paths and readonly paths
|
|
|
|
Signed-off-by: wujing <wujing50@huawei.com>
|
|
---
|
|
src/lxc/conf.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
src/lxc/conf.h | 12 +++++
|
|
src/lxc/confile.c | 106 +++++++++++++++++++++++++++++++++++++++++
|
|
3 files changed, 256 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
|
|
index a904348..fce241b 100644
|
|
--- a/src/lxc/conf.c
|
|
+++ b/src/lxc/conf.c
|
|
@@ -1275,6 +1275,96 @@ static int lxc_mount_rootfs(struct lxc_conf *conf)
|
|
return 0;
|
|
}
|
|
|
|
+#ifdef HAVE_ISULAD
|
|
+// 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, 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;
|
|
+}
|
|
+#endif
|
|
+
|
|
int lxc_chroot(const struct lxc_rootfs *rootfs)
|
|
{
|
|
__do_free char *nroot = NULL;
|
|
@@ -2666,8 +2756,9 @@ struct lxc_conf *lxc_conf_init(void)
|
|
seccomp_conf_init(new);
|
|
|
|
#ifdef HAVE_ISULAD
|
|
- /* 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;
|
|
new->umask = 0027; /*default umask 0027*/
|
|
new->console.init_fifo[0] = NULL;
|
|
@@ -3690,6 +3781,22 @@ int lxc_setup(struct lxc_handler *handler)
|
|
return log_error(-1, "Failed to setup sysctl parameters");
|
|
}
|
|
|
|
+#ifdef HAVE_ISULAD
|
|
+ // isulad: setup rootfs masked paths
|
|
+ if (!lxc_list_empty(&lxc_conf->rootfs.maskedpaths)) {
|
|
+ if (setup_rootfs_maskedpaths(&lxc_conf->rootfs.maskedpaths)) {
|
|
+ return log_error(-1, "failed to setup maskedpaths");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // isulad: setup rootfs ro paths
|
|
+ if (!lxc_list_empty(&lxc_conf->rootfs.ropaths)) {
|
|
+ if (setup_rootfs_ropaths(&lxc_conf->rootfs.ropaths)) {
|
|
+ return log_error(-1, "failed to setup readonlypaths");
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+
|
|
if (!lxc_list_empty(&lxc_conf->keepcaps)) {
|
|
if (!lxc_list_empty(&lxc_conf->caps))
|
|
return log_error(-1, "Container requests lxc.cap.drop and lxc.cap.keep: either use lxc.cap.drop or lxc.cap.keep, not both");
|
|
@@ -4103,6 +4210,8 @@ void lxc_conf_free(struct lxc_conf *conf)
|
|
}
|
|
lxc_clear_init_args(conf);
|
|
lxc_clear_populate_devices(conf);
|
|
+ lxc_clear_rootfs_masked_paths(conf);
|
|
+ lxc_clear_rootfs_ro_paths(conf);
|
|
#endif
|
|
free(conf);
|
|
}
|
|
@@ -4945,4 +5054,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 = NULL;
|
|
+ struct lxc_list *next = NULL;
|
|
+
|
|
+ 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 = NULL;
|
|
+ struct lxc_list *next = NULL;
|
|
+
|
|
+ lxc_list_for_each_safe(it, &c->rootfs.ropaths, next) {
|
|
+ lxc_list_del(it);
|
|
+ free(it->elem);
|
|
+ free(it);
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
#endif
|
|
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
|
|
index 52460a3..482fe0d 100644
|
|
--- a/src/lxc/conf.h
|
|
+++ b/src/lxc/conf.h
|
|
@@ -143,6 +143,8 @@ struct lxc_tty_info {
|
|
* @mountflags : the portion of @options that are flags
|
|
* @data : the portion of @options that are not flags
|
|
* @managed : whether it is managed by LXC
|
|
+ * @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;
|
|
@@ -152,6 +154,14 @@ struct lxc_rootfs {
|
|
unsigned long mountflags;
|
|
char *data;
|
|
bool managed;
|
|
+
|
|
+#ifdef HAVE_ISULAD
|
|
+ /* isulad: maskedpaths */
|
|
+ struct lxc_list maskedpaths;
|
|
+ /* isulad: ropaths */
|
|
+ struct lxc_list ropaths;
|
|
+#endif
|
|
+
|
|
};
|
|
|
|
/*
|
|
@@ -511,5 +521,7 @@ extern int userns_exec_minimal(const struct lxc_conf *conf,
|
|
#ifdef HAVE_ISULAD
|
|
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);
|
|
#endif
|
|
#endif /* __LXC_CONF_H */
|
|
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
|
|
index 2df269a..bf0fdf0 100644
|
|
--- a/src/lxc/confile.c
|
|
+++ b/src/lxc/confile.c
|
|
@@ -151,6 +151,8 @@ lxc_config_define(proc);
|
|
lxc_config_define(init_args);
|
|
lxc_config_define(populate_device);
|
|
lxc_config_define(umask);
|
|
+lxc_config_define(rootfs_masked_paths);
|
|
+lxc_config_define(rootfs_ro_paths);
|
|
#endif
|
|
|
|
/*
|
|
@@ -268,6 +270,8 @@ static struct lxc_config_t config_jump_table[] = {
|
|
{ "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.umask", set_config_umask, get_config_umask, clr_config_umask, },
|
|
+ { "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, },
|
|
#endif
|
|
};
|
|
|
|
@@ -6311,4 +6315,106 @@ static inline int clr_config_umask(const char *key, struct lxc_conf *c,
|
|
return 0;
|
|
}
|
|
|
|
+/* 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 == NULL)
|
|
+ goto on_error;
|
|
+
|
|
+ list_item->elem = safe_strdup(value);
|
|
+
|
|
+ lxc_list_add_tail(&lxc_conf->rootfs.maskedpaths, list_item);
|
|
+
|
|
+ return 0;
|
|
+
|
|
+on_error:
|
|
+ free(list_item);
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+// 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 = NULL;
|
|
+
|
|
+ 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: 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 == NULL)
|
|
+ goto on_error;
|
|
+
|
|
+ list_item->elem = safe_strdup(value);
|
|
+
|
|
+ lxc_list_add_tail(&lxc_conf->rootfs.ropaths, list_item);
|
|
+
|
|
+ return 0;
|
|
+
|
|
+on_error:
|
|
+ free(list_item);
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+// 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 = NULL;
|
|
+
|
|
+ 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;
|
|
+}
|
|
+
|
|
+/* 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);
|
|
+}
|
|
+
|
|
#endif
|
|
--
|
|
1.8.3.1
|
|
|