attach: non-functional changes

parent ea0eb48b
......@@ -22,22 +22,24 @@
*/
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/unistd.h>
#include <sys/mount.h>
#include <sys/param.h>
#include <sys/prctl.h>
#include <sys/mount.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include <linux/unistd.h>
#include <pwd.h>
#include <lxc/lxccontainer.h>
#ifndef HAVE_DECL_PR_CAPBSET_DROP
#define PR_CAPBSET_DROP 24
......@@ -51,28 +53,27 @@
#define PR_GET_NO_NEW_PRIVS 39
#endif
#include "namespace.h"
#include "log.h"
#include "af_unix.h"
#include "attach.h"
#include "caps.h"
#include "config.h"
#include "utils.h"
#include "commands.h"
#include "cgroup.h"
#include "lxclock.h"
#include "commands.h"
#include "conf.h"
#include "lxcseccomp.h"
#include <lxc/lxccontainer.h>
#include "lsm/lsm.h"
#include "config.h"
#include "confile.h"
#include "log.h"
#include "lsm/lsm.h"
#include "lxclock.h"
#include "lxcseccomp.h"
#include "namespace.h"
#include "utils.h"
#if HAVE_SYS_PERSONALITY_H
#include <sys/personality.h>
#endif
#ifndef SOCK_CLOEXEC
# define SOCK_CLOEXEC 02000000
#define SOCK_CLOEXEC 02000000
#endif
#ifndef MS_REC
......@@ -80,7 +81,7 @@
#endif
#ifndef MS_SLAVE
#define MS_SLAVE (1<<19)
#define MS_SLAVE (1 << 19)
#endif
lxc_log_define(lxc_attach, lxc);
......@@ -125,7 +126,7 @@ static int lsm_openat(int procfd, pid_t pid, int on_exec)
static int lsm_set_label_at(int lsm_labelfd, int on_exec, char *lsm_label)
{
int fret = -1;
const char* name;
const char *name;
char *command = NULL;
name = lsm_name();
......@@ -143,7 +144,8 @@ static int lsm_set_label_at(int lsm_labelfd, int on_exec, char *lsm_label)
if (strcmp(name, "AppArmor") == 0) {
int size;
command = malloc(strlen(lsm_label) + strlen("changeprofile ") + 1);
command =
malloc(strlen(lsm_label) + strlen("changeprofile ") + 1);
if (!command) {
SYSERROR("Failed to write apparmor profile.");
goto out;
......@@ -185,12 +187,12 @@ out:
#define __PROC_STATUS_LEN (5 + (LXC_NUMSTRLEN64) + 7 + 1)
static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
{
int ret;
bool found;
FILE *proc_file;
char proc_fn[__PROC_STATUS_LEN];
bool found;
int ret;
char *line = NULL;
size_t line_bufsz = 0;
char *line = NULL;
struct lxc_proc_context_info *info = NULL;
/* Read capabilities. */
......@@ -224,7 +226,8 @@ static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
fclose(proc_file);
if (!found) {
SYSERROR("Could not read capability bounding set from %s.", proc_fn);
SYSERROR("Could not read capability bounding set from %s.",
proc_fn);
errno = ENOENT;
goto on_error;
}
......@@ -251,7 +254,6 @@ static int lxc_attach_to_ns(pid_t pid, int which)
int fd[LXC_NS_MAX];
int i, j, saved_errno;
if (access("/proc/self/ns", X_OK)) {
ERROR("Does this kernel version support namespaces?");
return -1;
......@@ -275,7 +277,8 @@ static int lxc_attach_to_ns(pid_t pid, int which)
close(fd[j]);
errno = saved_errno;
SYSERROR("Failed to open namespace: \"%s\".", ns_info[i].proc_name);
SYSERROR("Failed to open namespace: \"%s\".",
ns_info[i].proc_name);
return -1;
}
}
......@@ -291,7 +294,8 @@ static int lxc_attach_to_ns(pid_t pid, int which)
close(fd[j]);
errno = saved_errno;
SYSERROR("Failed to attach to namespace \"%s\".", ns_info[i].proc_name);
SYSERROR("Failed to attach to namespace \"%s\".",
ns_info[i].proc_name);
return -1;
}
......@@ -314,7 +318,7 @@ static int lxc_attach_remount_sys_proc(void)
}
if (detect_shared_rootfs()) {
if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL)) {
SYSERROR("Failed to make / rslave.");
ERROR("Continuing...");
}
......@@ -354,9 +358,9 @@ static int lxc_attach_remount_sys_proc(void)
static int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx)
{
int last_cap = lxc_caps_last_cap();
int cap;
int cap, last_cap;
last_cap = lxc_caps_last_cap();
for (cap = 0; cap <= last_cap; cap++) {
if (ctx->capability_mask & (1LL << cap))
continue;
......@@ -370,11 +374,12 @@ static int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx)
return 0;
}
static int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char** extra_env, char** extra_keep)
static int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy,
char **extra_env, char **extra_keep)
{
if (policy == LXC_ATTACH_CLEAR_ENV) {
char **extra_keep_store = NULL;
int path_kept = 0;
char **extra_keep_store = NULL;
if (extra_keep) {
size_t count, i;
......@@ -410,6 +415,7 @@ static int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char*
if (clearenv()) {
char **p;
SYSERROR("Failed to clear environment.");
if (extra_keep_store) {
for (p = extra_keep_store; *p; p++)
......@@ -421,6 +427,7 @@ static int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char*
if (extra_keep_store) {
size_t i;
for (i = 0; extra_keep[i]; i++) {
if (extra_keep_store[i]) {
if (setenv(extra_keep[i], extra_keep_store[i], 1) < 0)
......@@ -469,10 +476,9 @@ static int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char*
static char *lxc_attach_getpwshell(uid_t uid)
{
int fd, ret;
pid_t pid;
int pipes[2];
int ret;
int fd;
char *result = NULL;
/* We need to fork off a process that runs the getent program, and we
......@@ -490,21 +496,20 @@ static char *lxc_attach_getpwshell(uid_t uid)
}
if (pid) {
int status;
FILE *pipe_f;
char *line = NULL;
size_t line_bufsz = 0;
int found = 0;
int status;
size_t line_bufsz = 0;
char *line = NULL;
close(pipes[1]);
pipe_f = fdopen(pipes[0], "r");
while (getline(&line, &line_bufsz, pipe_f) != -1) {
char *token;
char *saveptr = NULL;
long value;
char *endptr = NULL;
int i;
long value;
char *token;
char *endptr = NULL, *saveptr = NULL;
/* If we already found something, just continue to read
* until the pipe doesn't deliver any more data, but
......@@ -615,7 +620,7 @@ static char *lxc_attach_getpwshell(uid_t uid)
}
}
static void lxc_attach_get_init_uidgid(uid_t* init_uid, gid_t* init_gid)
static void lxc_attach_get_init_uidgid(uid_t *init_uid, gid_t *init_gid)
{
FILE *proc_file;
char proc_fn[__PROC_STATUS_LEN];
......@@ -639,11 +644,11 @@ static void lxc_attach_get_init_uidgid(uid_t* init_uid, gid_t* init_gid)
*/
ret = sscanf(line, "Uid: %ld", &value);
if (ret != EOF && ret == 1) {
uid = (uid_t) value;
uid = (uid_t)value;
} else {
ret = sscanf(line, "Gid: %ld", &value);
if (ret != EOF && ret == 1)
gid = (gid_t) value;
gid = (gid_t)value;
}
if (uid != (uid_t)-1 && gid != (gid_t)-1)
break;
......@@ -665,16 +670,21 @@ static void lxc_attach_get_init_uidgid(uid_t* init_uid, gid_t* init_gid)
struct attach_clone_payload {
int ipc_socket;
lxc_attach_options_t* options;
struct lxc_proc_context_info* init_ctx;
lxc_attach_options_t *options;
struct lxc_proc_context_info *init_ctx;
lxc_attach_exec_t exec_function;
void* exec_payload;
void *exec_payload;
};
static int attach_child_main(void* data);
/* Help the optimizer along if it doesn't know that exit always exits. */
#define rexit(c) do { int __c = (c); _exit(__c); return __c; } while(0)
#define rexit(c) \
do { \
int __c = (c); \
_exit(__c); \
return __c; \
} while (0)
/* Define default options if no options are supplied by the user. */
static lxc_attach_options_t attach_static_default_options = LXC_ATTACH_OPTIONS_DEFAULT;
......@@ -684,7 +694,8 @@ static bool fetch_seccomp(struct lxc_container *c,
{
char *path;
if (!(options->namespaces & CLONE_NEWNS) || !(options->attach_flags & LXC_ATTACH_LSM)) {
if (!(options->namespaces & CLONE_NEWNS) ||
!(options->attach_flags & LXC_ATTACH_LSM)) {
free(c->lxc_conf->seccomp);
c->lxc_conf->seccomp = NULL;
return true;
......@@ -724,15 +735,13 @@ static bool fetch_seccomp(struct lxc_container *c,
return true;
}
static bool no_new_privs(struct lxc_container *c,
lxc_attach_options_t *options)
static bool no_new_privs(struct lxc_container *c, lxc_attach_options_t *options)
{
char *val;
/* Remove current setting. */
if (!c->set_config_item(c, "lxc.no_new_privs", "")) {
if (!c->set_config_item(c, "lxc.no_new_privs", ""))
return false;
}
/* Retrieve currently active setting. */
val = c->get_running_config_item(c, "lxc.no_new_privs");
......@@ -753,25 +762,29 @@ static bool no_new_privs(struct lxc_container *c,
static signed long get_personality(const char *name, const char *lxcpath)
{
char *p = lxc_cmd_get_config_item(name, "lxc.arch", lxcpath);
char *p;
signed long ret;
p = lxc_cmd_get_config_item(name, "lxc.arch", lxcpath);
if (!p)
return -1;
ret = lxc_config_parse_arch(p);
free(p);
return ret;
}
int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_function, void* exec_payload, lxc_attach_options_t* options, pid_t* attached_process)
int lxc_attach(const char *name, const char *lxcpath,
lxc_attach_exec_t exec_function, void *exec_payload,
lxc_attach_options_t *options, pid_t *attached_process)
{
int ret, status;
pid_t init_pid, pid, attached_pid, expected;
struct lxc_proc_context_info *init_ctx;
char* cwd;
char* new_cwd;
int ipc_sockets[2];
char *cwd, *new_cwd;
signed long personality;
pid_t attached_pid, expected, init_pid, pid;
struct lxc_proc_context_info *init_ctx;
if (!options)
options = &attach_static_default_options;
......@@ -784,14 +797,13 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
init_ctx = lxc_proc_get_context_info(init_pid);
if (!init_ctx) {
ERROR("Failed to get context of init process: %ld.",
(long)init_pid);
ERROR("Failed to get context of init process: %ld", (long)init_pid);
return -1;
}
personality = get_personality(name, lxcpath);
if (init_ctx->personality < 0) {
ERROR("Failed to get personality of the container.");
ERROR("Failed to get personality of the container");
lxc_proc_put_context_info(init_ctx);
return -1;
}
......@@ -876,7 +888,6 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
* setns() (otherwise, user namespaces will hate us).
*/
pid = fork();
if (pid < 0) {
SYSERROR("Failed to create first subprocess.");
free(cwd);
......@@ -901,9 +912,9 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
}
/* Setup resource limits */
if (!lxc_list_empty(&init_ctx->container->lxc_conf->limits) && setup_resource_limits(&init_ctx->container->lxc_conf->limits, pid)) {
goto on_error;
}
if (!lxc_list_empty(&init_ctx->container->lxc_conf->limits))
if (setup_resource_limits(&init_ctx->container->lxc_conf->limits, pid) < 0)
goto on_error;
/* Open /proc before setns() to the containers namespace so we
* don't rely on any information from inside the container.
......@@ -924,7 +935,8 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
}
/* Get pid of attached process from intermediate process. */
ret = lxc_read_nointr_expect(ipc_sockets[0], &attached_pid, sizeof(attached_pid), NULL);
ret = lxc_read_nointr_expect(ipc_sockets[0], &attached_pid,
sizeof(attached_pid), NULL);
if (ret <= 0) {
if (ret != 0)
ERROR("Expected to receive pid: %s.", strerror(errno));
......@@ -955,7 +967,8 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
/* Wait for the attached process to finish initializing. */
expected = 1;
ret = lxc_read_nointr_expect(ipc_sockets[0], &status, sizeof(status), &expected);
ret = lxc_read_nointr_expect(ipc_sockets[0], &status,
sizeof(status), &expected);
if (ret <= 0) {
if (ret != 0)
ERROR("Expected to receive sequence number 1: %s.", strerror(errno));
......@@ -974,7 +987,8 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
* up its LSM labels.
*/
expected = 3;
ret = lxc_read_nointr_expect(ipc_sockets[0], &status, sizeof(status), &expected);
ret = lxc_read_nointr_expect(ipc_sockets[0], &status,
sizeof(status), &expected);
if (ret <= 0) {
ERROR("Expected to receive sequence number 3: %s.",
strerror(errno));
......@@ -982,9 +996,12 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
}
/* Open LSM fd and send it to child. */
if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) {
if ((options->namespaces & CLONE_NEWNS) &&
(options->attach_flags & LXC_ATTACH_LSM) &&
init_ctx->lsm_label) {
int on_exec, saved_errno;
int labelfd = -1;
on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? 1 : 0;
/* Open fd for the LSM security module. */
labelfd = lsm_openat(procfd, attached_pid, on_exec);
......@@ -1025,7 +1042,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
shutdown(ipc_sockets[0], SHUT_RDWR);
close(ipc_sockets[0]);
if (to_cleanup_pid)
(void) wait_for_pid(to_cleanup_pid);
(void)wait_for_pid(to_cleanup_pid);
lxc_proc_put_context_info(init_ctx);
return -1;
}
......@@ -1038,7 +1055,8 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
/* Wait for the parent to have setup cgroups. */
expected = 0;
status = -1;
ret = lxc_read_nointr_expect(ipc_sockets[1], &status, sizeof(status), &expected);
ret = lxc_read_nointr_expect(ipc_sockets[1], &status, sizeof(status),
&expected);
if (ret <= 0) {
ERROR("Expected to receive sequence number 0: %s.", strerror(errno));
shutdown(ipc_sockets[1], SHUT_RDWR);
......@@ -1112,21 +1130,17 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
static int attach_child_main(void* data)
{
struct attach_clone_payload* payload = (struct attach_clone_payload*)data;
int ipc_socket = payload->ipc_socket;
lxc_attach_options_t* options = payload->options;
struct lxc_proc_context_info* init_ctx = payload->init_ctx;
int expected, fd, lsm_labelfd, ret, status;
long flags;
#if HAVE_SYS_PERSONALITY_H
long new_personality;
#endif
int ret;
int status;
int expected;
long flags;
int fd;
int lsm_labelfd;
uid_t new_uid;
gid_t new_gid;
struct attach_clone_payload* payload = (struct attach_clone_payload*)data;
int ipc_socket = payload->ipc_socket;
lxc_attach_options_t* options = payload->options;
struct lxc_proc_context_info* init_ctx = payload->init_ctx;
/* Wait for the initial thread to signal us that it's ready for us to
* start initializing.
......@@ -1145,7 +1159,8 @@ static int attach_child_main(void* data)
* parent process, otherwise /proc may not properly reflect the new pid
* namespace.
*/
if (!(options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_REMOUNT_PROC_SYS)) {
if (!(options->namespaces & CLONE_NEWNS) &&
(options->attach_flags & LXC_ATTACH_REMOUNT_PROC_SYS)) {
ret = lxc_attach_remount_sys_proc();
if (ret < 0) {
shutdown(ipc_socket, SHUT_RDWR);
......@@ -1182,7 +1197,9 @@ static int attach_child_main(void* data)
/* Always set the environment (specify (LXC_ATTACH_KEEP_ENV, NULL, NULL)
* if you want this to be a no-op).
*/
ret = lxc_attach_set_environment(options->env_policy, options->extra_env_vars, options->extra_keep_env);
ret = lxc_attach_set_environment(options->env_policy,
options->extra_env_vars,
options->extra_keep_env);
if (ret < 0) {
ERROR("Could not set initial environment for attached process.");
shutdown(ipc_socket, SHUT_RDWR);
......@@ -1226,7 +1243,8 @@ static int attach_child_main(void* data)
rexit(-1);
}
}
if ((new_uid != 0 || options->namespaces & CLONE_NEWUSER) && setuid(new_uid)) {
if ((new_uid != 0 || options->namespaces & CLONE_NEWUSER) &&
setuid(new_uid)) {
SYSERROR("Switching to container uid.");
shutdown(ipc_socket, SHUT_RDWR);
rexit(-1);
......@@ -1276,7 +1294,8 @@ static int attach_child_main(void* data)
rexit(-1);
}
if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) {
if ((options->namespaces & CLONE_NEWNS) &&
(options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) {
int on_exec;
/* Receive fd for LSM security module. */
ret = lxc_abstract_unix_recv_fds(ipc_socket, &lsm_labelfd, 1, NULL, 0);
......
......@@ -24,8 +24,8 @@
#ifndef __LXC_ATTACH_H
#define __LXC_ATTACH_H
#include <sys/types.h>
#include <lxc/attach_options.h>
#include <sys/types.h>
struct lxc_conf;
......@@ -36,6 +36,8 @@ struct lxc_proc_context_info {
unsigned long long capability_mask;
};
extern int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_function, void* exec_payload, lxc_attach_options_t* options, pid_t* attached_process);
extern int lxc_attach(const char *name, const char *lxcpath,
lxc_attach_exec_t exec_function, void *exec_payload,
lxc_attach_options_t *options, pid_t *attached_process);
#endif
#endif /* __LXC_ATTACH_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment