*/
#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
#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
#endif
#ifndef MS_SLAVE
-#define MS_SLAVE (1<<19)
+#define MS_SLAVE (1 << 19)
#endif
lxc_log_define(lxc_attach, lxc);
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();
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;
#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. */
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;
}
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;
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;
}
}
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;
}
}
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...");
}
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;
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;
if (clearenv()) {
char **p;
+
SYSERROR("Failed to clear environment.");
if (extra_keep_store) {
for (p = extra_keep_store; *p; p++)
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)
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
}
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
}
}
-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];
*/
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;
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;
{
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;
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");
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;
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;
}
* setns() (otherwise, user namespaces will hate us).
*/
pid = fork();
-
if (pid < 0) {
SYSERROR("Failed to create first subprocess.");
free(cwd);
}
/* 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.
}
/* 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));
/* 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));
* 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));
}
/* 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);
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;
}
/* 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);
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.
* 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);
/* 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);
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);
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);