lxc/0027-Capabilites-security-feature-enhanced.patch
lifeng 8966f1fe72 lxc: update lxc to 4.0.1
Signed-off-by: lifeng <lifeng68@huawei.com>
2020-04-23 19:30:12 +08:00

241 lines
6.6 KiB
Diff

From e71dabf21ddd2a093ebdfcc6f6c79200415d12b1 Mon Sep 17 00:00:00 2001
From: wujing <wujing50@huawei.com>
Date: Tue, 14 Apr 2020 23:30:46 -0400
Subject: [PATCH 27/49] Capabilites security feature enhanced
Signed-off-by: wujing <wujing50@huawei.com>
---
src/lxc/attach.c | 24 +++++++++++++
src/lxc/conf.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/lxc/conf.h | 1 +
src/lxc/start.c | 20 +++++++++++
4 files changed, 148 insertions(+)
diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index c77b929..231fa5f 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -832,10 +832,12 @@ static int attach_child_main(struct attach_clone_payload *payload)
goto on_error;
}
+#ifndef HAVE_ISULAD
close(payload->ipc_socket);
payload->ipc_socket = -EBADF;
lxc_proc_put_context_info(init_ctx);
payload->init_ctx = NULL;
+#endif
/* The following is done after the communication socket is shut down.
* That way, all errors that might (though unlikely) occur up until this
@@ -895,6 +897,11 @@ static int attach_child_main(struct attach_clone_payload *payload)
new_gid = LXC_INVALID_GID;
#ifdef HAVE_ISULAD
+ if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+ SYSERROR("Failed to keep permitted capabilities");
+ goto on_error;
+ }
+
if (!lxc_setgroups(init_ctx->container->lxc_conf->init_groups_len,
init_ctx->container->lxc_conf->init_groups))
goto on_error;
@@ -908,6 +915,23 @@ static int attach_child_main(struct attach_clone_payload *payload)
if (!lxc_switch_uid_gid(new_uid, new_gid))
goto on_error;
+#ifdef HAVE_ISULAD
+ if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
+ SYSERROR("Failed to clear permitted capabilities");
+ goto on_error;
+ }
+
+ if (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;
+#endif
+
/* We're done, so we can now do whatever the user intended us to do. */
_exit(payload->exec_function(payload->exec_payload));
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 43ef067..325e0c2 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2902,6 +2902,16 @@ static int dropcaps_except(struct lxc_list *caps)
lxc_list_for_each (iterator, caps) {
keep_entry = iterator->elem;
+#ifdef HAVE_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;
+ }
+#endif
capid = parse_cap(keep_entry);
if (capid == -2)
continue;
@@ -4703,6 +4713,99 @@ int lxc_setup(struct lxc_handler *handler)
return 0;
}
+#ifdef HAVE_ISULAD
+/* 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
+ int ret = 0;
+ struct lxc_list *iterator = NULL;
+ char *keep_entry = NULL;
+ size_t i = 0;
+ int capid;
+ size_t numcaps = (size_t)lxc_caps_last_cap() + 1;
+ struct lxc_list *caps = NULL;
+ int *caplist = 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
+ caplist = malloc(numcaps * sizeof(int));
+ if (caplist == NULL) {
+ ERROR("Out of memory");
+ return -1;
+ }
+ (void)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);
+ ret = -1;
+ goto out;
+ }
+
+ 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_3;
+
+ for (i = 0; i < numcaps; i++) {
+ if (caplist[i]) {
+ cap_data[CAP_TO_INDEX(i)].effective = cap_data[CAP_TO_INDEX(i)].effective | (i > 31 ? __DEF_CAP_TO_MASK(i % 32) : __DEF_CAP_TO_MASK(i));
+ cap_data[CAP_TO_INDEX(i)].permitted = cap_data[CAP_TO_INDEX(i)].permitted | (i > 31 ? __DEF_CAP_TO_MASK(i % 32) : __DEF_CAP_TO_MASK(i));
+ cap_data[CAP_TO_INDEX(i)].inheritable = cap_data[CAP_TO_INDEX(i)].inheritable | (i > 31 ? __DEF_CAP_TO_MASK(i % 32) : __DEF_CAP_TO_MASK(i));
+ }
+ }
+
+ if (capset(cap_header, cap_data)) {
+ SYSERROR("Failed to set capabilitys");
+ ret = -1;
+ goto out;
+ }
+
+#endif
+
+out:
+ free(caplist);
+ return ret;
+}
+#endif
+
int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf,
char *argv[])
{
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index 879e427..7b6fd3b 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -555,6 +555,7 @@ int lxc_clear_init_groups(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);
int run_oci_hooks(const char *name, const char *hookname, struct lxc_conf *conf, const char *lxcpath);
#endif
#endif /* __LXC_CONF_H */
diff --git a/src/lxc/start.c b/src/lxc/start.c
index e2311ec..bb2e74a 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1652,6 +1652,13 @@ static int do_start(void *data)
}
}
+#ifdef HAVE_ISULAD
+ if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+ SYSERROR("Failed to keep permitted capabilities");
+ goto out_warn_father;
+ }
+#endif
+
/* The container has been setup. We can now switch to an unprivileged
* uid/gid.
*/
@@ -1705,6 +1712,19 @@ static int do_start(void *data)
goto out_warn_father;
}
+#ifdef HAVE_ISULAD
+ /* 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;
+ }
+#endif
+
if (handler->conf->monitor_signal_pdeath != SIGKILL) {
ret = lxc_set_death_signal(handler->conf->monitor_signal_pdeath,
handler->monitor_pid, status_fd);
--
1.8.3.1