241 lines
6.6 KiB
Diff
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
|
|
|