#include <fcntl.h>
#include <grp.h>
#include <poll.h>
+#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include "terminal.h"
#include "utils.h"
+#ifndef HAVE_STRLCPY
+#include "include/strlcpy.h"
+#endif
+
lxc_log_define(lxc_start, lxc);
extern void mod_all_rdeps(struct lxc_container *c, bool inc);
return -EBADF;
}
- ret = sigprocmask(SIG_BLOCK, &mask, oldmask);
+ ret = pthread_sigmask(SIG_BLOCK, &mask, oldmask);
if (ret < 0) {
SYSERROR("Failed to set signal mask");
return -EBADF;
int lxc_serve_state_clients(const char *name, struct lxc_handler *handler,
lxc_state_t state)
{
+ size_t retlen;
ssize_t ret;
struct lxc_list *cur, *next;
struct lxc_state_client *client;
return 0;
}
- strncpy(msg.name, name, sizeof(msg.name));
- msg.name[sizeof(msg.name) - 1] = 0;
+ retlen = strlcpy(msg.name, name, sizeof(msg.name));
+ if (retlen >= sizeof(msg.name))
+ return -E2BIG;
lxc_list_for_each_safe(cur, &handler->conf->state_clients, next) {
client = cur->elem;
}
TRACE("Chowned console");
+ handler->cgroup_ops = cgroup_init(handler);
+ if (!handler->cgroup_ops) {
+ ERROR("Failed to initialize cgroup driver");
+ goto out_restore_sigmask;
+ }
+ TRACE("Initialized cgroup driver");
+
INFO("Container \"%s\" is initialized", name);
return 0;
out_restore_sigmask:
- sigprocmask(SIG_SETMASK, &handler->oldmask, NULL);
+ pthread_sigmask(SIG_SETMASK, &handler->oldmask, NULL);
out_delete_tty:
lxc_delete_tty(&conf->ttys);
out_aborting:
struct lxc_list *cur, *next;
char *namespaces[LXC_NS_MAX + 1];
size_t namespace_count = 0;
+ struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
/* The STOPPING state is there for future cleanup code which can take
* awhile.
while (namespace_count--)
free(namespaces[namespace_count]);
- cgroup_destroy(handler);
+ cgroup_ops->destroy(cgroup_ops, handler);
+ cgroup_exit(cgroup_ops);
if (handler->conf->reboot == 0) {
/* For all new state clients simply close the command socket.
}
/* Reset mask set by setup_signal_fd. */
- ret = sigprocmask(SIG_SETMASK, &handler->oldmask, NULL);
+ ret = pthread_sigmask(SIG_SETMASK, &handler->oldmask, NULL);
if (ret < 0)
WARN("%s - Failed to restore signal mask", strerror(errno));
goto out_warn_father;
}
- ret = sigprocmask(SIG_SETMASK, &handler->oldmask, NULL);
+ ret = lxc_ambient_caps_up();
+ if (ret < 0) {
+ SYSERROR("Failed to raise ambient capabilities");
+ goto out_warn_father;
+ }
+
+ ret = pthread_sigmask(SIG_SETMASK, &handler->oldmask, NULL);
if (ret < 0) {
SYSERROR("Failed to set signal mask");
goto out_warn_father;
*/
ret = lxc_sync_barrier_parent(handler, LXC_SYNC_CONFIGURE);
if (ret < 0)
- return -1;
+ goto out_error;
ret = lxc_network_recv_veth_names_from_parent(handler);
if (ret < 0) {
if (ret < 0)
goto out_warn_father;
+ ret = lxc_ambient_caps_down();
+ if (ret < 0) {
+ SYSERROR("Failed to clear ambient capabilities");
+ goto out_warn_father;
+ }
+
/* After this call, we are in error because this ops should not return
* as it execs.
*/
continue;
ret = setns(handler->nsfd[i], 0);
- if (ret < 0)
+ if (ret < 0) {
+ /*
+ * Note that joining a user and/or mount namespace
+ * requires the process is not multithreaded otherwise
+ * setns() will fail here.
+ */
+ SYSERROR("Failed to inherit %s namespace",
+ ns_info[i].proc_name);
return -1;
+ }
DEBUG("Inherited %s namespace", ns_info[i].proc_name);
}
struct lxc_list *id_map;
const char *name = handler->name;
const char *lxcpath = handler->lxcpath;
- bool cgroups_connected = false, share_ns = false;
+ bool share_ns = false;
struct lxc_conf *conf = handler->conf;
+ struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
id_map = &conf->id_map;
wants_to_map_ids = !lxc_list_empty(id_map);
}
}
- if (!cgroup_init(handler)) {
- ERROR("Failed initializing cgroup support");
- goto out_delete_net;
- }
-
- cgroups_connected = true;
-
- if (!cgroup_create(handler)) {
+ if (!cgroup_ops->create(cgroup_ops, handler)) {
ERROR("Failed creating cgroups");
goto out_delete_net;
}
if (ret < 0)
goto out_delete_net;
- if (!cgroup_setup_limits(handler, false)) {
+ if (!cgroup_ops->setup_limits(cgroup_ops, handler->conf, false)) {
ERROR("Failed to setup cgroup limits for container \"%s\"", name);
goto out_delete_net;
}
- if (!cgroup_enter(handler))
+ if (!cgroup_ops->enter(cgroup_ops, handler->pid))
goto out_delete_net;
- if (!cgroup_chown(handler))
+ if (!cgroup_ops->chown(cgroup_ops, handler->conf))
goto out_delete_net;
/* Now we're ready to preserve the network namespace */
if (ret < 0)
goto out_delete_net;
- if (!cgroup_setup_limits(handler, true)) {
+ if (!cgroup_ops->setup_limits(cgroup_ops, handler->conf, true)) {
ERROR("Failed to setup legacy device cgroup controller limits");
goto out_delete_net;
}
TRACE("Set up legacy device cgroup controller limits");
- cgroup_disconnect();
- cgroups_connected = false;
-
if (handler->ns_clone_flags & CLONE_NEWCGROUP) {
/* Now we're ready to preserve the cgroup namespace */
ret = lxc_try_preserve_ns(handler->pid, "cgroup");
return 0;
out_delete_net:
- if (cgroups_connected)
- cgroup_disconnect();
-
if (handler->ns_clone_flags & CLONE_NEWNET)
lxc_delete_network(handler);