代码拉取完成,页面将自动刷新
同步操作将从 src-openEuler/lxc 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
From 44dd71a4d76eb464b81890ea3cfa2ac9c6c3d990 Mon Sep 17 00:00:00 2001
From: haozi007 <[email protected]>
Date: Tue, 19 Jul 2022 14:40:59 +0800
Subject: [PATCH] refactor patch code of isulad for selinux/attach
Signed-off-by: haozi007 <[email protected]>
---
src/lxc/exec_commands.c | 471 +++++++++++++++++++++++++++++++++++++
src/lxc/lsm/selinux.c | 258 ++++++++++++++++++++
src/lxc/tools/lxc_attach.c | 413 +++++++++++++++++++++++++++++++-
3 files changed, 1141 insertions(+), 1 deletion(-)
create mode 100644 src/lxc/exec_commands.c
diff --git a/src/lxc/exec_commands.c b/src/lxc/exec_commands.c
new file mode 100644
index 0000000..50246fa
--- /dev/null
+++ b/src/lxc/exec_commands.c
@@ -0,0 +1,471 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved.
+ * Author: lifeng
+ * Create: 2019-12-08
+ * Description: provide container definition
+ * lxc: linux Container library
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ ******************************************************************************/
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+#include <caps.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "af_unix.h"
+#include "cgroup.h"
+#include "exec_commands.h"
+#include "commands_utils.h"
+#include "conf.h"
+#include "config.h"
+#include "confile.h"
+#include "log.h"
+#include "lxc.h"
+#include "lxclock.h"
+#include "mainloop.h"
+#include "monitor.h"
+#include "terminal.h"
+#include "utils.h"
+
+lxc_log_define(commands_exec, lxc);
+
+static const char *lxc_exec_cmd_str(lxc_exec_cmd_t cmd)
+{
+ static const char *const cmdname[LXC_EXEC_CMD_MAX] = {
+ [LXC_EXEC_CMD_SET_TERMINAL_WINCH] = "set_exec_terminal_winch",
+ };
+
+ if (cmd >= LXC_EXEC_CMD_MAX)
+ return "Invalid request";
+
+ return cmdname[cmd];
+}
+
+static int lxc_exec_cmd_rsp_recv(int sock, struct lxc_exec_cmd_rr *cmd)
+{
+ int ret, rspfd;
+ struct lxc_exec_cmd_rsp *rsp = &cmd->rsp;
+
+ ret = lxc_abstract_unix_recv_fds_timeout(sock, &rspfd, 1, rsp, sizeof(*rsp), 1000 * 1000);
+ if (ret < 0) {
+ SYSERROR("Failed to receive response for command \"%s\"",
+ lxc_exec_cmd_str(cmd->req.cmd));
+
+ if (errno == ECONNRESET || errno == EAGAIN || errno == EWOULDBLOCK) {
+ errno = ECONNRESET; /*isulad set errno ECONNRESET when timeout */
+ return -1;
+ }
+
+ return -1;
+ }
+ TRACE("Command \"%s\" received response", lxc_exec_cmd_str(cmd->req.cmd));
+
+ if (rsp->datalen == 0) {
+ DEBUG("Response data length for command \"%s\" is 0",
+ lxc_exec_cmd_str(cmd->req.cmd));
+ return ret;
+ }
+
+ if (rsp->datalen > LXC_CMD_DATA_MAX) {
+ ERROR("Response data for command \"%s\" is too long: %d bytes > %d",
+ lxc_exec_cmd_str(cmd->req.cmd), rsp->datalen, LXC_CMD_DATA_MAX);
+ return -1;
+ }
+
+ rsp->data = malloc(rsp->datalen);
+ if (!rsp->data) {
+ errno = ENOMEM;
+ ERROR("Failed to allocate response buffer for command \"%s\"",
+ lxc_exec_cmd_str(cmd->req.cmd));
+ return -1;
+ }
+
+ ret = lxc_recv_nointr(sock, rsp->data, rsp->datalen, 0);
+ if (ret != rsp->datalen) {
+ SYSERROR("Failed to receive response data for command \"%s\"",
+ lxc_exec_cmd_str(cmd->req.cmd));
+ return -1;
+ }
+
+ return ret;
+}
+
+static int lxc_exec_cmd_rsp_send(int fd, struct lxc_exec_cmd_rsp *rsp)
+{
+ ssize_t ret;
+
+ errno = EMSGSIZE;
+ ret = lxc_send_nointr(fd, rsp, sizeof(*rsp), MSG_NOSIGNAL);
+ if (ret < 0 || (size_t)ret != sizeof(*rsp)) {
+ SYSERROR("Failed to send command response %zd", ret);
+ return -1;
+ }
+
+ if (!rsp->data || rsp->datalen <= 0)
+ return 0;
+
+ errno = EMSGSIZE;
+ ret = lxc_send_nointr(fd, rsp->data, rsp->datalen, MSG_NOSIGNAL);
+ if (ret < 0 || ret != (ssize_t)rsp->datalen) {
+ SYSWARN("Failed to send command response data %zd", ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int lxc_exec_cmd_send(const char *name, struct lxc_exec_cmd_rr *cmd,
+ const char *lxcpath, const char *hashed_sock_name, const char *suffix)
+{
+ int client_fd, saved_errno;
+ ssize_t ret = -1;
+
+ client_fd = lxc_cmd_connect(name, lxcpath, hashed_sock_name, suffix);
+ if (client_fd < 0)
+ return -1;
+
+ ret = lxc_abstract_unix_send_credential(client_fd, &cmd->req,
+ sizeof(cmd->req));
+ if (ret < 0 || (size_t)ret != sizeof(cmd->req))
+ goto on_error;
+
+ if (cmd->req.datalen <= 0)
+ return client_fd;
+
+ errno = EMSGSIZE;
+ ret = lxc_send_nointr(client_fd, (void *)cmd->req.data,
+ cmd->req.datalen, MSG_NOSIGNAL);
+ if (ret < 0 || ret != (ssize_t)cmd->req.datalen)
+ goto on_error;
+
+ return client_fd;
+
+on_error:
+ saved_errno = errno;
+ close(client_fd);
+ errno = saved_errno;
+
+ return -1;
+}
+
+static int lxc_exec_cmd(const char *name, struct lxc_exec_cmd_rr *cmd, const char *lxcpath, const char *hashed_sock_name, const char *suffix)
+{
+ int client_fd = -1;
+ int saved_errno;
+ int ret = -1;
+
+ client_fd = lxc_exec_cmd_send(name, cmd, lxcpath, hashed_sock_name, suffix);
+ if (client_fd < 0) {
+ SYSTRACE("Command \"%s\" failed to connect command socket",
+ lxc_exec_cmd_str(cmd->req.cmd));
+ return -1;
+ }
+
+ ret = lxc_exec_cmd_rsp_recv(client_fd, cmd);
+
+ saved_errno = errno;
+ close(client_fd);
+ errno = saved_errno;
+ return ret;
+}
+
+int lxc_exec_cmd_set_terminal_winch(const char *name, const char *lxcpath, const char *suffix, unsigned int height, unsigned int width)
+{
+ int ret = 0;
+ struct lxc_exec_cmd_set_terminal_winch_request data = { 0 };
+
+ data.height = height;
+ data.width = width;
+
+ struct lxc_exec_cmd_rr cmd = {
+ .req = {
+ .cmd = LXC_EXEC_CMD_SET_TERMINAL_WINCH,
+ .datalen = sizeof(struct lxc_exec_cmd_set_terminal_winch_request),
+ .data = &data,
+ },
+ };
+
+ ret = lxc_exec_cmd(name, &cmd, lxcpath, NULL, suffix);
+ if (ret < 0) {
+ ERROR("Failed to send command to container");
+ return -1;
+ }
+
+ if (cmd.rsp.ret != 0) {
+ ERROR("Command response error:%d", cmd.rsp.ret);
+ return -1;
+ }
+ return 0;
+}
+
+static int lxc_exec_cmd_set_terminal_winch_callback(int fd, struct lxc_exec_cmd_req *req,
+ struct lxc_exec_command_handler *handler)
+{
+ struct lxc_exec_cmd_rsp rsp;
+ struct lxc_exec_cmd_set_terminal_winch_request *data = (struct lxc_exec_cmd_set_terminal_winch_request *)(req->data);
+ memset(&rsp, 0, sizeof(rsp));
+
+ rsp.ret = lxc_set_terminal_winsz(handler->terminal, data->height, data->width);;
+
+ return lxc_exec_cmd_rsp_send(fd, &rsp);
+
+}
+
+static int lxc_exec_cmd_process(int fd, struct lxc_exec_cmd_req *req,
+ struct lxc_exec_command_handler *handler)
+{
+ typedef int (*callback)(int, struct lxc_exec_cmd_req *, struct lxc_exec_command_handler *);
+
+ callback cb[LXC_EXEC_CMD_MAX] = {
+ [LXC_EXEC_CMD_SET_TERMINAL_WINCH] = lxc_exec_cmd_set_terminal_winch_callback,
+ };
+
+ if (req->cmd >= LXC_EXEC_CMD_MAX) {
+ ERROR("Undefined command id %d", req->cmd);
+ return -1;
+ }
+ return cb[req->cmd](fd, req, handler);
+}
+
+static void lxc_exec_cmd_fd_cleanup(int fd, struct lxc_epoll_descr *descr)
+{
+ lxc_mainloop_del_handler(descr, fd);
+ close(fd);
+ return;
+}
+
+static int lxc_exec_cmd_handler(int fd, uint32_t events, void *data,
+ struct lxc_epoll_descr *descr)
+{
+ int ret;
+ struct lxc_exec_cmd_req req;
+ void *reqdata = NULL;
+ struct lxc_exec_command_handler *handler = data;
+
+ ret = lxc_abstract_unix_rcv_credential(fd, &req, sizeof(req));
+ if (ret < 0) {
+ SYSERROR("Failed to receive data on command socket for command "
+ "\"%s\"", lxc_exec_cmd_str(req.cmd));
+
+ if (errno == EACCES) {
+ /* We don't care for the peer, just send and close. */
+ struct lxc_exec_cmd_rsp rsp = {.ret = ret};
+
+ lxc_exec_cmd_rsp_send(fd, &rsp);
+ }
+
+ goto out_close;
+ }
+
+ if (ret == 0)
+ goto out_close;
+
+ if (ret != sizeof(req)) {
+ WARN("Failed to receive full command request. Ignoring request "
+ "for \"%s\"", lxc_exec_cmd_str(req.cmd));
+ ret = -1;
+ goto out_close;
+ }
+
+ if (req.datalen > LXC_CMD_DATA_MAX) {
+ ERROR("Received command data length %d is too large for "
+ "command \"%s\"", req.datalen, lxc_exec_cmd_str(req.cmd));
+ errno = EFBIG;
+ ret = -EFBIG;
+ goto out_close;
+ }
+
+ if (req.datalen > 0) {
+ reqdata = alloca(req.datalen);
+ if (!reqdata) {
+ ERROR("Failed to allocate memory for \"%s\" command",
+ lxc_exec_cmd_str(req.cmd));
+ errno = ENOMEM;
+ ret = -ENOMEM;
+ goto out_close;
+ }
+
+ ret = lxc_recv_nointr(fd, reqdata, req.datalen, 0);
+ if (ret != req.datalen) {
+ WARN("Failed to receive full command request. Ignoring "
+ "request for \"%s\"", lxc_exec_cmd_str(req.cmd));
+ ret = LXC_MAINLOOP_ERROR;
+ goto out_close;
+ }
+
+ req.data = reqdata;
+ }
+
+ ret = lxc_exec_cmd_process(fd, &req, handler);
+ if (ret) {
+ /* This is not an error, but only a request to close fd. */
+ ret = LXC_MAINLOOP_CONTINUE;
+ goto out_close;
+ }
+
+out:
+ return ret;
+
+out_close:
+ lxc_exec_cmd_fd_cleanup(fd, descr);
+ goto out;
+}
+
+static int lxc_exec_cmd_accept(int fd, uint32_t events, void *data,
+ struct lxc_epoll_descr *descr)
+{
+ int connection = -1;
+ int opt = 1, ret = -1;
+
+ connection = accept(fd, NULL, 0);
+ if (connection < 0) {
+ SYSERROR("Failed to accept connection to run command");
+ return LXC_MAINLOOP_ERROR;
+ }
+
+ ret = fcntl(connection, F_SETFD, FD_CLOEXEC);
+ if (ret < 0) {
+ SYSERROR("Failed to set close-on-exec on incoming command connection");
+ goto out_close;
+ }
+
+ ret = setsockopt(connection, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt));
+ if (ret < 0) {
+ SYSERROR("Failed to enable necessary credentials on command socket");
+ goto out_close;
+ }
+
+ ret = lxc_mainloop_add_handler(descr, connection, lxc_exec_cmd_handler, data);
+ if (ret) {
+ ERROR("Failed to add command handler");
+ goto out_close;
+ }
+
+out:
+ return ret;
+
+out_close:
+ close(connection);
+ goto out;
+}
+#ifdef HAVE_ISULAD
+int lxc_exec_unix_sock_delete(const char *name, const char *suffix)
+{
+ char path[LXC_AUDS_ADDR_LEN] = {0};
+
+ if (name == NULL || suffix == NULL)
+ return -1;
+
+ if (generate_named_unix_sock_path(name, suffix, path, sizeof(path)) != 0)
+ return -1;
+
+ (void)unlink(path);
+
+ return 0;
+}
+
+int lxc_exec_cmd_init(const char *name, const char *lxcpath, const char *suffix)
+{
+ __do_close int fd = -EBADF;
+ int ret;
+ char path[LXC_AUDS_ADDR_LEN] = {0};
+ __do_free char *exec_sock_dir = NULL;
+
+ exec_sock_dir = generate_named_unix_sock_dir(name);
+ if (exec_sock_dir == NULL)
+ return -1;
+
+ if (mkdir_p(exec_sock_dir, 0600) < 0)
+ return log_error_errno(-1, errno, "Failed to create exec sock directory %s", path);
+
+ if (generate_named_unix_sock_path(name, suffix, path, sizeof(path)) != 0)
+ return -1;
+
+ TRACE("Creating unix socket \"%s\"", path);
+
+ fd = lxc_named_unix_open(path, SOCK_STREAM, 0);
+ if (fd < 0) {
+ if (errno == EADDRINUSE) {
+ WARN("Container \"%s\" exec unix sock is occupied", name);
+ (void)unlink(path);
+ fd = lxc_named_unix_open(path, SOCK_STREAM, 0);
+ if (fd < 0)
+ return log_error_errno(-1, errno, "Failed to create command socket %s", path);
+ } else {
+ return log_error_errno(-1, errno, "Failed to create command socket %s", path);
+ }
+ }
+
+ ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
+ if (ret < 0)
+ return log_error_errno(-1, errno, "Failed to set FD_CLOEXEC on command socket file descriptor");
+
+ return log_trace(move_fd(fd), "Created unix socket \"%s\"", path);
+}
+#else
+int lxc_exec_cmd_init(const char *name, const char *lxcpath, const char *suffix)
+{
+ int fd, ret;
+ char path[LXC_AUDS_ADDR_LEN] = {0};
+
+ ret = lxc_make_abstract_socket_name(path, sizeof(path), name, lxcpath, NULL, suffix);
+ if (ret < 0)
+ return -1;
+ TRACE("Creating abstract unix socket \"%s\"", &path[1]);
+
+ fd = lxc_abstract_unix_open(path, SOCK_STREAM, 0);
+ if (fd < 0) {
+ SYSERROR("Failed to create command socket %s", &path[1]);
+ if (errno == EADDRINUSE)
+ ERROR("Container \"%s\" appears to be already running", name);
+
+ return -1;
+ }
+
+ ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
+ if (ret < 0) {
+ SYSERROR("Failed to set FD_CLOEXEC on command socket file descriptor");
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+#endif
+
+int lxc_exec_cmd_mainloop_add(struct lxc_epoll_descr *descr, struct lxc_exec_command_handler *handler)
+{
+ int ret;
+ int fd = handler->maincmd_fd;
+
+ ret = lxc_mainloop_add_handler(descr, fd, lxc_exec_cmd_accept, handler);
+ if (ret < 0) {
+ ERROR("Failed to add handler for command socket");
+ close(fd);
+ }
+
+ return ret;
+}
diff --git a/src/lxc/lsm/selinux.c b/src/lxc/lsm/selinux.c
index dba0ab5..bd4f449 100644
--- a/src/lxc/lsm/selinux.c
+++ b/src/lxc/lsm/selinux.c
@@ -16,6 +16,10 @@
#include "log.h"
#include "lsm.h"
+#ifdef HAVE_ISULAD
+#include <selinux/context.h>
+#endif
+
#define DEFAULT_LABEL "unconfined_t"
lxc_log_define(selinux, lsm);
@@ -85,6 +89,256 @@ static int selinux_process_label_set(const char *inlabel, struct lxc_conf *conf,
return 0;
}
+#ifdef HAVE_ISULAD
+/*
+ * selinux_file_label_set: Set SELinux context of a file
+ *
+ * @path : a file
+ * @label : label string
+ *
+ * Returns 0 on success, < 0 on failure
+ */
+static int selinux_file_label_set(const char *path, const char *label)
+{
+ if (path == NULL || label == NULL || strcmp(label, "unconfined_t") == 0) {
+ return 0;
+ }
+
+ if (!is_selinux_enabled()) {
+ return 0;
+ }
+
+ if (lsetfilecon(path, label) != 0) {
+ SYSERROR("Failed to setSELinux context to \"%s\": %s", label, path);
+ return -1;
+ }
+
+ INFO("Changed SELinux context to \"%s\": %s", label, path);
+ return 0;
+}
+
+/*
+ * is_exclude_relabel_path: Determine whether it is a excluded path to label
+ *
+ * @path : a file or directory
+ *
+ * Returns 0 on success, < 0 on failure
+ */
+static bool is_exclude_relabel_path(const char *path)
+{
+ const char *exclude_path[] = { "/", "/usr", "/etc", "/tmp", "/home", "/run", "/var", "/root" };
+ size_t i;
+
+ for (i = 0; i < sizeof(exclude_path) / sizeof(char *); i++) {
+ if (strcmp(path, exclude_path[i]) == 0) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * bad_prefix: Prevent users from relabing system files
+ *
+ * @path : a file or directory
+ *
+ * Returns 0 on success, < 0 on failure
+ */
+static int bad_prefix(const char *fpath)
+{
+ const char *bad_prefixes = "/usr";
+
+ if (fpath == NULL) {
+ ERROR("Empty file path");
+ return -1;
+ }
+
+ if (strncmp(fpath, bad_prefixes, strlen(bad_prefixes)) == 0) {
+ ERROR("relabeling content in %s is not allowed", bad_prefixes);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * recurse_set_file_label: Recursively label files or folders
+ *
+ * @path : a file or directory
+ * @label : label string
+ *
+ * Returns 0 on success, < 0 on failure
+ */
+static int recurse_set_file_label(const char *basePath, const char *label)
+{
+ int ret = 0;
+ __do_closedir DIR *dir = NULL;
+ struct dirent *ptr = NULL;
+ char base[PATH_MAX] = { 0 };
+
+ if ((dir = opendir(basePath)) == NULL) {
+ ERROR("Failed to Open dir: %s", basePath);
+ return -1;
+ }
+
+ ret = lsetfilecon(basePath, label);
+ if (ret != 0) {
+ ERROR("Failed to set file label");
+ return ret;
+ }
+
+ while ((ptr = readdir(dir)) != NULL) {
+ if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
+ continue;
+ } else {
+ int nret = snprintf(base, sizeof(base), "%s/%s", basePath, ptr->d_name);
+ if (nret < 0 || nret >= sizeof(base)) {
+ ERROR("Failed to get path");
+ return -1;
+ }
+ if (ptr->d_type == DT_DIR) {
+ ret = recurse_set_file_label(base, label);
+ if (ret != 0) {
+ ERROR("Failed to set dir label");
+ return ret;
+ }
+ } else {
+ ret = lsetfilecon(base, label);
+ if (ret != 0) {
+ ERROR("Failed to set file label");
+ return ret;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * selinux_chcon: Chcon changes the `fpath` file object to the SELinux label `label`.
+ * If `fpath` is a directory and `recurse`` is true, Chcon will walk the
+ * directory tree setting the label.
+ *
+ * @fpath : a file or directory
+ * @label : label string
+ * @recurse : whether to recurse
+ *
+ * Returns 0 on success, < 0 on failure
+ */
+static int selinux_chcon(const char *fpath, const char *label, bool recurse)
+{
+ struct stat s_buf;
+
+ if (fpath == NULL || label == NULL) {
+ ERROR("Invalid parameters!");
+ return -1;
+ }
+
+ if (bad_prefix(fpath) != 0) {
+ return -1;
+ }
+ if (stat(fpath, &s_buf) != 0) {
+ return -1;
+ }
+ if (recurse && S_ISDIR(s_buf.st_mode)) {
+ return recurse_set_file_label(fpath, label);
+ }
+
+ if (lsetfilecon(fpath, label) != 0) {
+ ERROR("Failed to set file label");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * convert_context_to_share_mode: set sensitivity to s0 and remove categories
+ * user:role:type:sensitivity[:categories] => user:role:type:s0
+ *
+ * @label : label string
+ *
+ * Returns label with share mode on success, NULL on failure
+ */
+static char *convert_context_to_share_mode(const char *label) {
+ __do_free char *converted_label = strdup(label);
+ char *s = converted_label;
+ const char *shared_level = "s0";
+ int cnt = 0;
+
+ // selinux label format: user:role:type:sensitivity[:categories]
+ // locates the ":" position in front of the sensitivity
+ while (cnt++ < 3 && (s = strchr(s, ':')) != NULL) {
+ s++;
+ }
+
+ // make sure sensitivity can set s0 value
+ if (s == NULL || strlen(s) < strlen(shared_level)) {
+ ERROR("Invalid selinux file context: %s", label);
+ return NULL;
+ }
+
+ if (strcmp(s, shared_level) == 0) {
+ return move_ptr(converted_label);
+ }
+
+ *s = '\0';
+ strcat(converted_label, shared_level);
+
+ return move_ptr(converted_label);
+}
+
+/*
+ * selinux_relabel: Relabel changes the label of path to the filelabel string.
+ * It changes the MCS label to s0 if shared is true.
+ * This will allow all containers to share the content.
+ *
+ * @path : a file or directory
+ * @label : label string
+ * @shared : whether to use share mode
+ *
+ * Returns 0 on success, < 0 on failure
+ */
+static int selinux_relabel(const char *path, const char *label, bool shared)
+{
+ __do_free char *tmp_file_label = NULL;
+
+ if (path == NULL || label == NULL) {
+ return 0;
+ }
+
+ if (!is_selinux_enabled()) {
+ return 0;
+ }
+
+ if (is_exclude_relabel_path(path)) {
+ ERROR("SELinux relabeling of %s is not allowed", path);
+ return -1;
+ }
+
+ if (shared) {
+ tmp_file_label = convert_context_to_share_mode(label);
+ if (tmp_file_label == NULL) {
+ ERROR("Failed to convert context to share mode: %s", label);
+ return -1;
+ }
+ } else {
+ tmp_file_label = strdup(label);
+ }
+
+
+ if (selinux_chcon(path, tmp_file_label, true) != 0) {
+ ERROR("Failed to modify %s's selinux context: %s", path, tmp_file_label);
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif
+
/*
* selinux_keyring_label_set: Set SELinux context that will be assigned to the keyring
*
@@ -103,6 +357,10 @@ static struct lsm_drv selinux_drv = {
.process_label_get = selinux_process_label_get,
.process_label_set = selinux_process_label_set,
.keyring_label_set = selinux_keyring_label_set,
+#ifdef HAVE_ISULAD
+ .file_label_set = selinux_file_label_set,
+ .relabel = selinux_relabel,
+#endif
};
struct lsm_drv *lsm_selinux_drv_init(void)
diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c
index a8f493a..1a5a241 100644
--- a/src/lxc/tools/lxc_attach.c
+++ b/src/lxc/tools/lxc_attach.c
@@ -72,8 +72,20 @@ static const struct option my_longopts[] = {
{"set-var", required_argument, 0, 'v'},
{"pty-log", required_argument, 0, 'L'},
{"rcfile", required_argument, 0, 'f'},
+#ifndef HAVE_ISULAD
{"uid", required_argument, 0, 'u'},
{"gid", required_argument, 0, 'g'},
+#else
+ {"workdir", required_argument, 0, 'w'},
+ {"user", required_argument, 0, 'u'},
+ {"in-fifo", required_argument, 0, OPT_INPUT_FIFO}, /* isulad add terminal fifos*/
+ {"out-fifo", required_argument, 0, OPT_OUTPUT_FIFO},
+ {"err-fifo", required_argument, 0, OPT_STDERR_FIFO},
+ {"suffix", required_argument, 0, OPT_ATTACH_SUFFIX},
+ {"timeout", required_argument, 0, OPT_ATTACH_TIMEOUT},
+ {"disable-pty", no_argument, 0, OPT_DISABLE_PTY},
+ {"open-stdin", no_argument, 0, OPT_OPEN_STDIN},
+#endif
LXC_COMMON_OPTIONS
};
@@ -124,9 +136,26 @@ Options :\n\
multiple times.\n\
-f, --rcfile=FILE\n\
Load configuration file FILE\n\
+"
+#ifndef HAVE_ISULAD
+"\
-u, --uid=UID Execute COMMAND with UID inside the container\n\
-g, --gid=GID Execute COMMAND with GID inside the container\n\
-",
+"
+#else
+"\
+ -w, --workdir Working directory inside the container.\n\
+ -u, --user User ID (format: UID[:GID])\n\
+ --in-fifo Stdin fifo path\n\
+ --out-fifo Stdout fifo path\n\
+ --err-fifo Stderr fifo path\n\
+ --suffi ID for mutli-attach on one container\n\
+ --timeout Timeout in seconds (default: 0)\n\
+ --disable-pty Disable pty for attach\n\
+ --open-stdin Open stdin for attach\n\
+"
+#endif
+,
.options = my_longopts,
.parser = my_parser,
.checker = NULL,
@@ -136,6 +165,71 @@ Options :\n\
.gid = LXC_INVALID_GID,
};
+#ifdef HAVE_ISULAD
+static int parse_user_id(const char *username, char **uid, char **gid, char **tmp_dup)
+{
+ char *tmp = NULL;
+ char *pdot = NULL;
+
+ if (uid == NULL || gid == NULL || tmp_dup == NULL) {
+ return -1;
+ }
+
+ if (username != NULL) {
+ tmp = strdup(username);
+ if (tmp == NULL) {
+ ERROR("Failed to duplicate user name");
+ return -1;
+ }
+
+ // for free tmp in caller
+ *tmp_dup = tmp;
+ pdot = strstr(tmp, ":");
+ if (pdot != NULL) {
+ *pdot = '\0';
+ if (pdot != tmp) {
+ // uid found
+ *uid = tmp;
+ }
+
+ if (*(pdot + 1) != '\0') {
+ // gid found
+ *gid = pdot + 1;
+ }
+ } else {
+ // No : found
+ if (*tmp != '\0') {
+ *uid = tmp;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int get_attach_uid_gid(const char *username, uid_t *user_id, gid_t *group_id)
+{
+ char *tmp = NULL;
+ char *uid = NULL;
+ char *gid = NULL;
+
+ // parse uid and gid by username
+ if (parse_user_id(username, &uid, &gid, &tmp) != 0) {
+ return -1;
+ }
+
+ if (uid != NULL) {
+ *user_id = (unsigned int)atoll(uid);
+ }
+ if (gid != NULL) {
+ *group_id = (unsigned int)atoll(gid);
+ }
+
+ free(tmp);
+ return 0;
+}
+#endif
+
static int my_parser(struct lxc_arguments *args, int c, char *arg)
{
int ret;
@@ -193,6 +287,7 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
case 'f':
args->rcfile = arg;
break;
+#ifndef HAVE_ISULAD
case 'u':
if (lxc_safe_uint(arg, &args->uid) < 0)
return -1;
@@ -201,6 +296,42 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
if (lxc_safe_uint(arg, &args->gid) < 0)
return -1;
break;
+#else
+ case 'u':
+ if (get_attach_uid_gid(arg, &args->uid, &args->gid) != 0) {
+ ERROR("Failed to get attach user U/GID");
+ return -1;
+ }
+ break;
+ case 'w':
+ args->workdir=arg;
+ break;
+ case OPT_INPUT_FIFO:
+ args->terminal_fifos[0] = arg;
+ break;
+ case OPT_OUTPUT_FIFO:
+ args->terminal_fifos[1] = arg;
+ break;
+ case OPT_STDERR_FIFO:
+ args->terminal_fifos[2] = arg;
+ break;
+ case OPT_ATTACH_SUFFIX:
+ args->suffix = arg;
+ break;
+ case OPT_ATTACH_TIMEOUT:
+ if(!is_non_negative_num(arg)) {
+ ERROR("Error attach timeout parameter:%s.\n", arg);
+ return -1;
+ }
+ args->attach_timeout = (unsigned int)atoll(arg);
+ break;
+ case OPT_DISABLE_PTY:
+ args->disable_pty = 1;
+ break;
+ case OPT_OPEN_STDIN:
+ args->open_stdin = 1;
+ break;
+#endif
}
return 0;
@@ -264,6 +395,285 @@ static int lxc_attach_create_log_file(const char *log_file)
return fd;
}
+#ifdef HAVE_ISULAD
+// isulad: send '128 + signal' if container is killed by signal.
+#define EXIT_SIGNAL_OFFSET 128
+
+/*isulad: attach with terminal*/
+static int do_attach_foreground(struct lxc_container *c, lxc_attach_command_t *command,
+ lxc_attach_options_t *attach_options,
+ char **errmsg)
+{
+ int ret = 0;
+ pid_t pid;
+ int wexit = -1;
+ int signal;
+
+ if (command->program)
+ ret = c->attach(c, lxc_attach_run_command, command, attach_options, &pid);
+ else
+ ret = c->attach(c, lxc_attach_run_shell, NULL, attach_options, &pid);
+ if (ret < 0) {
+ *errmsg = safe_strdup("Internal error, failed to call attach");
+ goto out;
+ }
+
+ ret = lxc_wait_for_pid_status(pid);
+ if (ret < 0) {
+ free(*errmsg);
+ *errmsg = safe_strdup("Internal error, failed to wait attached process");
+ goto out;
+ }
+
+ if (WIFEXITED(ret))
+ wexit = WEXITSTATUS(ret);
+ else
+ wexit = -1;
+
+ if (WIFSIGNALED(ret)) {
+ signal = WTERMSIG(ret);
+ wexit = EXIT_SIGNAL_OFFSET + signal;
+ }
+
+ WARN("Execd pid %d exit with %d", pid, wexit);
+
+out:
+ if (c->lxc_conf->errmsg) {
+ free(*errmsg);
+ *errmsg = safe_strdup(c->lxc_conf->errmsg);
+ }
+ return wexit;
+}
+
+static void close_msg_pipe(int *errpipe)
+{
+ if (errpipe[0] >= 0) {
+ close(errpipe[0]);
+ errpipe[0] = -1;
+ }
+ if (errpipe[1] >= 0) {
+ close(errpipe[1]);
+ errpipe[1] = -1;
+ }
+}
+
+/*isulad: attach without terminal in background */
+static int do_attach_background(struct lxc_container *c, lxc_attach_command_t *command,
+ lxc_attach_options_t *attach_options,
+ char **errmsg)
+{
+ int ret = 0;
+ int msgpipe[2];
+ pid_t pid = 0;
+ ssize_t size_read;
+ char msgbuf[BUFSIZ + 1] = {0};
+
+ //pipdfd for get error message of child or grandchild process.
+ if (pipe2(msgpipe, O_CLOEXEC) != 0) {
+ SYSERROR("Failed to init msgpipe");
+ return -1;
+ }
+
+ pid = fork();
+ if (pid < 0) {
+ close_msg_pipe(msgpipe);
+ return -1;
+ }
+
+ if (pid != 0) {
+ close(msgpipe[1]);
+ msgpipe[1] = -1;
+ size_read = read(msgpipe[0], msgbuf, BUFSIZ);
+ if (size_read > 0) {
+ *errmsg = safe_strdup(msgbuf);
+ ret = -1;
+ }
+
+ close(msgpipe[0]);
+ msgpipe[0] = -1;
+
+ return ret;
+ }
+
+ /* second fork to be reparented by init */
+ pid = fork();
+ if (pid < 0) {
+ SYSERROR("Error doing dual-fork");
+ close_msg_pipe(msgpipe);
+ exit(1);
+ }
+ if (pid != 0) {
+ close_msg_pipe(msgpipe);
+ exit(0);
+ }
+
+ close(msgpipe[0]);
+ msgpipe[0] = -1;
+
+ if (null_stdfds() < 0) {
+ ERROR("failed to close fds");
+ exit(1);
+ }
+ setsid();
+
+ if (command->program)
+ ret = c->attach(c, lxc_attach_run_command, command, attach_options, &pid);
+ else
+ ret = c->attach(c, lxc_attach_run_shell, NULL, attach_options, &pid);
+ if (ret < 0) {
+ if (c->lxc_conf->errmsg)
+ lxc_write_error_message(msgpipe[1], "%s", c->lxc_conf->errmsg);
+ else
+ lxc_write_error_message(msgpipe[1], "Failed to attach container");
+ close(msgpipe[1]);
+ msgpipe[1] = -1;
+ ret = -1;
+ goto out;
+ }
+
+ close(msgpipe[1]);
+ msgpipe[1] = -1;
+
+ ret = wait_for_pid(pid);
+out:
+ lxc_container_put(c);
+ if (ret)
+ exit(EXIT_FAILURE);
+ else
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ int wexit = 0;
+ struct lxc_log log;
+ char *errmsg = NULL;
+ lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT;
+ lxc_attach_command_t command = (lxc_attach_command_t){.program = NULL};
+
+ if (lxc_caps_init())
+ exit(EXIT_FAILURE);
+
+ if (lxc_arguments_parse(&my_args, argc, argv))
+ exit(EXIT_FAILURE);
+
+ log.name = my_args.name;
+ log.file = my_args.log_file;
+ log.level = my_args.log_priority;
+ log.prefix = my_args.progname;
+ log.quiet = my_args.quiet;
+ log.lxcpath = my_args.lxcpath[0];
+
+ if (lxc_log_init(&log))
+ exit(EXIT_FAILURE);
+
+ if (geteuid())
+ if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
+ ERROR("You lack access to %s", my_args.lxcpath[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ struct lxc_container *c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
+ if (!c)
+ exit(EXIT_FAILURE);
+
+ if (my_args.rcfile) {
+ c->clear_config(c);
+ if (!c->load_config(c, my_args.rcfile)) {
+ ERROR("Failed to load rcfile");
+ lxc_container_put(c);
+ exit(EXIT_FAILURE);
+ }
+
+ c->configfile = strdup(my_args.rcfile);
+ if (!c->configfile) {
+ ERROR("Out of memory setting new config filename");
+ lxc_container_put(c);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (!c->may_control(c)) {
+ ERROR("Insufficent privileges to control %s", c->name);
+ lxc_container_put(c);
+ exit(EXIT_FAILURE);
+ }
+
+ if (remount_sys_proc)
+ attach_options.attach_flags |= LXC_ATTACH_REMOUNT_PROC_SYS;
+
+ if (elevated_privileges)
+ attach_options.attach_flags &= ~(elevated_privileges);
+
+ if (my_args.terminal_fifos[0] || my_args.terminal_fifos[1] || my_args.terminal_fifos[2]) {
+ attach_options.init_fifo[0] = my_args.terminal_fifos[0];
+ attach_options.init_fifo[1] = my_args.terminal_fifos[1];
+ attach_options.init_fifo[2] = my_args.terminal_fifos[2];
+ attach_options.attach_flags |= LXC_ATTACH_TERMINAL;
+ } else if (stdfd_is_pty()) {
+ attach_options.attach_flags |= LXC_ATTACH_TERMINAL;
+ }
+
+ attach_options.namespaces = namespace_flags;
+ attach_options.personality = new_personality;
+ attach_options.env_policy = env_policy;
+ attach_options.extra_env_vars = extra_env;
+ attach_options.extra_keep_env = extra_keep;
+ attach_options.timeout = my_args.attach_timeout;
+
+ if (my_args.argc > 0) {
+ command.program = my_args.argv[0];
+ command.argv = (char**)my_args.argv;
+ }
+
+ if (my_args.console_log) {
+ attach_options.log_fd = lxc_attach_create_log_file(my_args.console_log);
+ if (attach_options.log_fd < 0) {
+ ERROR("Failed to create log file for %s", c->name);
+ lxc_container_put(c);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (my_args.uid != LXC_INVALID_UID)
+ attach_options.uid = my_args.uid;
+
+ if (my_args.gid != LXC_INVALID_GID)
+ attach_options.gid = my_args.gid;
+
+ attach_options.suffix = my_args.suffix;
+
+ if (my_args.disable_pty) {
+ attach_options.disable_pty = true;
+ }
+
+ if (my_args.open_stdin) {
+ attach_options.open_stdin = true;
+ }
+
+ if (my_args.workdir) {
+ attach_options.initial_cwd = my_args.workdir;
+ }
+
+ /* isulad: add do attach background */
+ if (attach_options.attach_flags & LXC_ATTACH_TERMINAL)
+ wexit = do_attach_foreground(c, &command, &attach_options, &errmsg);
+ else
+ wexit = do_attach_background(c, &command, &attach_options, &errmsg);
+
+ if (errmsg) {
+ fprintf(stderr, "%s:%s:%s:%d starting container process caused \"%s\"", c->name,
+ __FILE__, __func__, __LINE__, errmsg);
+ free(errmsg);
+ }
+
+ lxc_container_put(c);
+ if (wexit >= 0)
+ exit(wexit);
+
+ exit(EXIT_FAILURE);
+}
+#else
int main(int argc, char *argv[])
{
int ret = -1;
@@ -377,3 +787,4 @@ out:
exit(EXIT_FAILURE);
}
+#endif
--
2.25.1
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。