lxc/0036-drop_caps-add-drop-caps-of-current-process.patch
2019-09-30 11:03:07 -04:00

257 lines
7.3 KiB
Diff

From 191cff886b75864a9304eb5e56fa29662978ffec Mon Sep 17 00:00:00 2001
From: LiFeng <lifeng68@huawei.com>
Date: Tue, 15 Jan 2019 22:55:06 -0500
Subject: [PATCH 036/122] drop_caps: add drop caps of current process
Signed-off-by: LiFeng <lifeng68@huawei.com>
---
src/lxc/attach.c | 26 +++++++++++++---
src/lxc/cgroups/cgfsng.c | 35 ++++++++++-----------
src/lxc/conf.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++
src/lxc/conf.h | 1 +
src/lxc/start.c | 16 ++++++++++
5 files changed, 135 insertions(+), 22 deletions(-)
diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index 8cbbf96..3f60fe1 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -936,11 +936,6 @@ static int attach_child_main(struct attach_clone_payload *payload)
TRACE("Loaded seccomp profile");
}
- close(payload->ipc_socket);
- payload->ipc_socket = -EBADF;
- lxc_proc_put_context_info(init_ctx);
- payload->init_ctx = NULL;
-
/* The following is done after the communication socket is shut down.
* That way, all errors that might (though unlikely) occur up until this
* point will have their messages printed to the original stderr (if
@@ -997,9 +992,30 @@ static int attach_child_main(struct attach_clone_payload *payload)
if (new_gid == ns_root_gid)
new_gid = LXC_INVALID_GID;
+ if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+ SYSERROR("Failed to keep permitted capabilities");
+ goto on_error;
+ }
+
if (!lxc_switch_uid_gid(new_uid, new_gid))
goto on_error;
+ if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
+ SYSERROR("Failed to clear permitted capabilities");
+ goto on_error;
+ }
+
+ if (init_ctx->container && init_ctx->container->lxc_conf &&
+ lxc_drop_caps(init_ctx->container->lxc_conf) != 0) {
+ ERROR("Failed to drop caps.");
+ goto on_error;
+ }
+
+ close(payload->ipc_socket);
+ payload->ipc_socket = -EBADF;
+ lxc_proc_put_context_info(init_ctx);
+ payload->init_ctx = NULL;
+
/* We're done, so we can now do whatever the user intended us to do. */
_exit(payload->exec_function(payload->exec_payload, msg_fd));
diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 8b913a6..bc1481d 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -2664,11 +2664,11 @@ __cgfsng_ops static bool cgfsng_data_init(struct cgroup_ops *ops, struct lxc_han
{
const char *cgroup_pattern;
char *container_cgroup, *tmp;
- struct lxc_conf *conf = handler->conf;
+ struct lxc_conf *conf = NULL;
size_t len;
- if (!conf)
- return false;
+ if (handler)
+ conf = handler->conf;
/* copy system-wide cgroup information */
cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
@@ -2680,21 +2680,22 @@ __cgfsng_ops static bool cgfsng_data_init(struct cgroup_ops *ops, struct lxc_han
ops->cgroup_pattern = must_copy_string(cgroup_pattern);
/* isulad: init ops->container_cgroup here instead of in cgfsng_payload_create*/
- if (conf->cgroup_meta.dir)
- tmp = lxc_string_join("/", (const char *[]){conf->cgroup_meta.dir, handler->name, NULL}, false);
- else
- tmp = lxc_string_replace("%n", handler->name, ops->cgroup_pattern);
- if (!tmp) {
- ERROR("Failed expanding cgroup name pattern");
- return false;
- }
-
- len = strlen(tmp) + 1;
- container_cgroup = must_realloc(NULL, len);
- (void)strlcpy(container_cgroup, tmp, len);
- free(tmp);
- ops->container_cgroup = container_cgroup;
+ if (conf) {
+ if (conf->cgroup_meta.dir)
+ tmp = lxc_string_join("/", (const char *[]){conf->cgroup_meta.dir, handler->name, NULL}, false);
+ else
+ tmp = lxc_string_replace("%n", handler->name, ops->cgroup_pattern);
+ if (!tmp) {
+ ERROR("Failed expanding cgroup name pattern");
+ return false;
+ }
+ len = strlen(tmp) + 1;
+ container_cgroup = must_realloc(NULL, len);
+ (void)strlcpy(container_cgroup, tmp, len);
+ free(tmp);
+ ops->container_cgroup = container_cgroup;
+ }
return true;
}
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index fea0f59..6134ed3 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -4220,6 +4220,85 @@ int lxc_setup(struct lxc_handler *handler)
return 0;
}
+/* isulad drop caps for container*/
+int lxc_drop_caps(struct lxc_conf *conf)
+{
+#define __DEF_CAP_TO_MASK(x) (1U << ((x) & 31))
+#if HAVE_LIBCAP
+ struct lxc_list *iterator;
+ char *keep_entry;
+ int i, capid;
+ int numcaps = lxc_caps_last_cap() + 1;
+ struct lxc_list *caps = NULL;
+
+ if (lxc_list_empty(&conf->keepcaps))
+ return 0;
+
+ caps = &conf->keepcaps;
+
+ if (numcaps <= 0 || numcaps > 200)
+ return -1;
+
+ // caplist[i] is 1 if we keep capability i
+ int *caplist = alloca(numcaps * sizeof(int));
+ memset(caplist, 0, numcaps * sizeof(int));
+
+ lxc_list_for_each(iterator, caps) {
+
+ keep_entry = iterator->elem;
+ /* isulad: Do not keep any cap*/
+ if (strcmp(keep_entry, "ISULAD_KEEP_NONE") == 0) {
+ DEBUG("Do not keep any capability");
+ for(i = 0; i < numcaps; i++) {
+ caplist[i] = 0;
+ }
+ break;
+ }
+
+ capid = parse_cap(keep_entry);
+
+ if (capid == -2)
+ continue;
+
+ if (capid < 0) {
+ ERROR("unknown capability %s", keep_entry);
+ return -1;
+ }
+
+ DEBUG("keep capability '%s' (%d)", keep_entry, capid);
+
+ caplist[capid] = 1;
+ }
+
+ struct __user_cap_header_struct cap_header_data;
+ struct __user_cap_data_struct cap_data_data[2];
+
+ cap_user_header_t cap_header = &cap_header_data;
+ cap_user_data_t cap_data = &cap_data_data[0];
+
+ memset(cap_header, 0 ,sizeof(struct __user_cap_header_struct));
+ memset(cap_data, 0, sizeof(struct __user_cap_data_struct) * 2);
+
+ cap_header->pid = 0;
+ cap_header->version = _LINUX_CAPABILITY_VERSION;
+
+ for (i = 0; i < numcaps; i++) {
+ if (caplist[i]) {
+ cap_data[CAP_TO_INDEX(i)].effective = cap_data[CAP_TO_INDEX(i)].effective | __DEF_CAP_TO_MASK(i);
+ cap_data[CAP_TO_INDEX(i)].permitted = cap_data[CAP_TO_INDEX(i)].permitted | __DEF_CAP_TO_MASK(i);
+ cap_data[CAP_TO_INDEX(i)].inheritable = cap_data[CAP_TO_INDEX(i)].inheritable | __DEF_CAP_TO_MASK(i);
+ }
+ }
+
+ if (capset(cap_header, cap_data)) {
+ SYSERROR("Failed to set capabilitys");
+ return -1;
+ }
+
+#endif
+ return 0;
+}
+
struct oci_hook_conf {
defs_hook *ocihook;
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index 44feb98..b92c48e 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -498,6 +498,7 @@ 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);
+int lxc_drop_caps(struct lxc_conf *conf);
/* isulad add end */
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 040909c..357e81d 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1411,6 +1411,11 @@ static int do_start(void *data)
}
}
+ if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+ SYSERROR("Failed to keep permitted capabilities");
+ goto out_warn_father;
+ }
+
/* The container has been setup. We can now switch to an unprivileged
* uid/gid.
*/
@@ -1448,6 +1453,17 @@ static int do_start(void *data)
goto out_warn_father;
}
+ /* isulad: drop the cap of current process */
+ if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
+ SYSERROR("Failed to clear permitted capabilities");
+ goto out_warn_father;
+ }
+
+ if (lxc_drop_caps(handler->conf)) {
+ SYSERROR("Failed to drop caps");
+ goto out_warn_father;
+ }
+
/* After this call, we are in error because this ops should not return
* as it execs.
*/
--
1.8.3.1