1244 lines
31 KiB
Diff
1244 lines
31 KiB
Diff
From 44dd71a4d76eb464b81890ea3cfa2ac9c6c3d990 Mon Sep 17 00:00:00 2001
|
|
From: haozi007 <liuhao27@huawei.com>
|
|
Date: Tue, 19 Jul 2022 14:40:59 +0800
|
|
Subject: [PATCH] refactor patch code of isulad for selinux/attach
|
|
|
|
Signed-off-by: haozi007 <liuhao27@huawei.com>
|
|
---
|
|
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
|
|
|