Unverified Commit 208b3ee0 by Stéphane Graber Committed by GitHub

Merge pull request #3281 from brauner/2020-03-10/fixes

tree-wide: cleanup
parents 32a0f033 bbba37f7
...@@ -54,19 +54,6 @@ ...@@ -54,19 +54,6 @@
lxc_log_define(cgfsng, cgroup); lxc_log_define(cgfsng, cgroup);
static void free_string_list(char **clist)
{
int i;
if (!clist)
return;
for (i = 0; clist[i]; i++)
free(clist[i]);
free(clist);
}
/* Given a pointer to a null-terminated array of pointers, realloc to add one /* Given a pointer to a null-terminated array of pointers, realloc to add one
* entry, and point the new entry to NULL. Do not fail. Return the index to the * entry, and point the new entry to NULL. Do not fail. Return the index to the
* second-to-last entry - that is, the one which is now available for use * second-to-last entry - that is, the one which is now available for use
...@@ -2940,12 +2927,11 @@ static void cg_unified_delegate(char ***delegate) ...@@ -2940,12 +2927,11 @@ static void cg_unified_delegate(char ***delegate)
*/ */
static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileged) static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileged)
{ {
__do_free char *basecginfo = NULL; __do_free char *basecginfo = NULL, *line = NULL;
__do_free char *line = NULL; __do_free_string_list char **klist = NULL, **nlist = NULL;
__do_fclose FILE *f = NULL; __do_fclose FILE *f = NULL;
int ret; int ret;
size_t len = 0; size_t len = 0;
char **klist = NULL, **nlist = NULL;
/* Root spawned containers escape the current cgroup, so use init's /* Root spawned containers escape the current cgroup, so use init's
* cgroups as our base in that case. * cgroups as our base in that case.
...@@ -2968,11 +2954,11 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg ...@@ -2968,11 +2954,11 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg
lxc_cgfsng_print_basecg_debuginfo(basecginfo, klist, nlist); lxc_cgfsng_print_basecg_debuginfo(basecginfo, klist, nlist);
while (getline(&line, &len, f) != -1) { while (getline(&line, &len, f) != -1) {
__do_free char *base_cgroup = NULL, *mountpoint = NULL;
__do_free_string_list char **controller_list = NULL;
int type; int type;
bool writeable; bool writeable;
struct hierarchy *new; struct hierarchy *new;
char *base_cgroup = NULL, *mountpoint = NULL;
char **controller_list = NULL;
type = get_cgroup_version(line); type = get_cgroup_version(line);
if (type == 0) if (type == 0)
...@@ -3000,18 +2986,18 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg ...@@ -3000,18 +2986,18 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg
if (type == CGROUP_SUPER_MAGIC) if (type == CGROUP_SUPER_MAGIC)
if (controller_list_is_dup(ops->hierarchies, controller_list)) if (controller_list_is_dup(ops->hierarchies, controller_list))
log_trace_errno(goto next, EEXIST, "Skipping duplicating controller"); log_trace_errno(continue, EEXIST, "Skipping duplicating controller");
mountpoint = cg_hybrid_get_mountpoint(line); mountpoint = cg_hybrid_get_mountpoint(line);
if (!mountpoint) if (!mountpoint)
log_error_errno(goto next, EINVAL, "Failed parsing mountpoint from \"%s\"", line); log_error_errno(continue, EINVAL, "Failed parsing mountpoint from \"%s\"", line);
if (type == CGROUP_SUPER_MAGIC) if (type == CGROUP_SUPER_MAGIC)
base_cgroup = cg_hybrid_get_current_cgroup(basecginfo, controller_list[0], CGROUP_SUPER_MAGIC); base_cgroup = cg_hybrid_get_current_cgroup(basecginfo, controller_list[0], CGROUP_SUPER_MAGIC);
else else
base_cgroup = cg_hybrid_get_current_cgroup(basecginfo, NULL, CGROUP2_SUPER_MAGIC); base_cgroup = cg_hybrid_get_current_cgroup(basecginfo, NULL, CGROUP2_SUPER_MAGIC);
if (!base_cgroup) if (!base_cgroup)
log_error_errno(goto next, EINVAL, "Failed to find current cgroup"); log_error_errno(continue, EINVAL, "Failed to find current cgroup");
trim(base_cgroup); trim(base_cgroup);
prune_init_scope(base_cgroup); prune_init_scope(base_cgroup);
...@@ -3020,7 +3006,7 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg ...@@ -3020,7 +3006,7 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg
else else
writeable = test_writeable_v1(mountpoint, base_cgroup); writeable = test_writeable_v1(mountpoint, base_cgroup);
if (!writeable) if (!writeable)
log_trace_errno(goto next, EROFS, "The %s group is not writeable", base_cgroup); log_trace_errno(continue, EROFS, "The %s group is not writeable", base_cgroup);
if (type == CGROUP2_SUPER_MAGIC) { if (type == CGROUP2_SUPER_MAGIC) {
char *cgv2_ctrl_path; char *cgv2_ctrl_path;
...@@ -3040,26 +3026,16 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg ...@@ -3040,26 +3026,16 @@ static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileg
/* Exclude all controllers that cgroup use does not want. */ /* Exclude all controllers that cgroup use does not want. */
if (!cgroup_use_wants_controllers(ops, controller_list)) if (!cgroup_use_wants_controllers(ops, controller_list))
log_trace_errno(goto next, EINVAL, "Skipping controller"); log_trace_errno(continue, EINVAL, "Skipping controller");
new = add_hierarchy(&ops->hierarchies, controller_list, mountpoint, base_cgroup, type); new = add_hierarchy(&ops->hierarchies, move_ptr(controller_list), move_ptr(mountpoint), move_ptr(base_cgroup), type);
if (type == CGROUP2_SUPER_MAGIC && !ops->unified) { if (type == CGROUP2_SUPER_MAGIC && !ops->unified) {
if (unprivileged) if (unprivileged)
cg_unified_delegate(&new->cgroup2_chown); cg_unified_delegate(&new->cgroup2_chown);
ops->unified = new; ops->unified = new;
} }
continue;
next:
free_string_list(controller_list);
free(mountpoint);
free(base_cgroup);
} }
free_string_list(klist);
free_string_list(nlist);
TRACE("Writable cgroup hierarchies:"); TRACE("Writable cgroup hierarchies:");
lxc_cgfsng_print_hierarchies(ops); lxc_cgfsng_print_hierarchies(ops);
......
...@@ -191,20 +191,16 @@ static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp) ...@@ -191,20 +191,16 @@ static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
errno = EMSGSIZE; errno = EMSGSIZE;
ret = lxc_send_nointr(fd, rsp, sizeof(*rsp), MSG_NOSIGNAL); ret = lxc_send_nointr(fd, rsp, sizeof(*rsp), MSG_NOSIGNAL);
if (ret < 0 || (size_t)ret != sizeof(*rsp)) { if (ret < 0 || (size_t)ret != sizeof(*rsp))
SYSERROR("Failed to send command response %zd", ret); return log_error_errno(-1, errno, "Failed to send command response %zd", ret);
return -1;
}
if (!rsp->data || rsp->datalen <= 0) if (!rsp->data || rsp->datalen <= 0)
return 0; return 0;
errno = EMSGSIZE; errno = EMSGSIZE;
ret = lxc_send_nointr(fd, rsp->data, rsp->datalen, MSG_NOSIGNAL); ret = lxc_send_nointr(fd, rsp->data, rsp->datalen, MSG_NOSIGNAL);
if (ret < 0 || ret != (ssize_t)rsp->datalen) { if (ret < 0 || ret != (ssize_t)rsp->datalen)
SYSWARN("Failed to send command response data %zd", ret); return log_warn_errno(-1, errno, "Failed to send command response data %zd", ret);
return -1;
}
return 0; return 0;
} }
...@@ -277,13 +273,11 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped, ...@@ -277,13 +273,11 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
client_fd = lxc_cmd_send(name, cmd, lxcpath, hashed_sock_name); client_fd = lxc_cmd_send(name, cmd, lxcpath, hashed_sock_name);
if (client_fd < 0) { if (client_fd < 0) {
SYSTRACE("Command \"%s\" failed to connect command socket",
lxc_cmd_str(cmd->req.cmd));
if (errno == ECONNREFUSED || errno == EPIPE) if (errno == ECONNREFUSED || errno == EPIPE)
*stopped = 1; *stopped = 1;
return -1; return log_trace_errno(-1, errno, "Command \"%s\" failed to connect command socket",
lxc_cmd_str(cmd->req.cmd));
} }
ret = lxc_cmd_rsp_recv(client_fd, cmd); ret = lxc_cmd_rsp_recv(client_fd, cmd);
...@@ -335,13 +329,13 @@ int lxc_try_cmd(const char *name, const char *lxcpath) ...@@ -335,13 +329,13 @@ int lxc_try_cmd(const char *name, const char *lxcpath)
pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath) pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath)
{ {
int ret, stopped; int ret, stopped;
intmax_t pid; intmax_t pid = -1;
struct lxc_cmd_rr cmd = { struct lxc_cmd_rr cmd = {
.req = { .req = {
.cmd = LXC_CMD_GET_INIT_PID .cmd = LXC_CMD_GET_INIT_PID
}, },
.rsp = { .rsp = {
.data = INTMAX_TO_PTR((intmax_t){-1}) .data = INTMAX_TO_PTR(pid)
} }
}; };
...@@ -384,7 +378,9 @@ int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath) ...@@ -384,7 +378,9 @@ int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath)
{ {
int ret, stopped; int ret, stopped;
struct lxc_cmd_rr cmd = { struct lxc_cmd_rr cmd = {
.req = { .cmd = LXC_CMD_GET_CLONE_FLAGS }, .req = {
.cmd = LXC_CMD_GET_CLONE_FLAGS,
},
}; };
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL); ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
...@@ -398,7 +394,9 @@ static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req, ...@@ -398,7 +394,9 @@ static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
struct lxc_handler *handler, struct lxc_handler *handler,
struct lxc_epoll_descr *descr) struct lxc_epoll_descr *descr)
{ {
struct lxc_cmd_rsp rsp = { .data = INT_TO_PTR(handler->ns_clone_flags) }; struct lxc_cmd_rsp rsp = {
.data = INT_TO_PTR(handler->ns_clone_flags),
};
return lxc_cmd_rsp_send(fd, &rsp); return lxc_cmd_rsp_send(fd, &rsp);
} }
...@@ -544,7 +542,9 @@ int lxc_cmd_get_state(const char *name, const char *lxcpath) ...@@ -544,7 +542,9 @@ int lxc_cmd_get_state(const char *name, const char *lxcpath)
{ {
int ret, stopped; int ret, stopped;
struct lxc_cmd_rr cmd = { struct lxc_cmd_rr cmd = {
.req = { .cmd = LXC_CMD_GET_STATE } .req = {
.cmd = LXC_CMD_GET_STATE,
},
}; };
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL); ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
...@@ -554,22 +554,21 @@ int lxc_cmd_get_state(const char *name, const char *lxcpath) ...@@ -554,22 +554,21 @@ int lxc_cmd_get_state(const char *name, const char *lxcpath)
if (ret < 0) if (ret < 0)
return -1; return -1;
if (!ret) { if (!ret)
WARN("Container \"%s\" has stopped before sending its state", name); return log_warn(-1, "Container \"%s\" has stopped before sending its state", name);
return -1;
}
DEBUG("Container \"%s\" is in \"%s\" state", name,
lxc_state2str(PTR_TO_INT(cmd.rsp.data)));
return PTR_TO_INT(cmd.rsp.data); return log_debug(PTR_TO_INT(cmd.rsp.data),
"Container \"%s\" is in \"%s\" state", name,
lxc_state2str(PTR_TO_INT(cmd.rsp.data)));
} }
static int lxc_cmd_get_state_callback(int fd, struct lxc_cmd_req *req, static int lxc_cmd_get_state_callback(int fd, struct lxc_cmd_req *req,
struct lxc_handler *handler, struct lxc_handler *handler,
struct lxc_epoll_descr *descr) struct lxc_epoll_descr *descr)
{ {
struct lxc_cmd_rsp rsp = { .data = INT_TO_PTR(handler->state) }; struct lxc_cmd_rsp rsp = {
.data = INT_TO_PTR(handler->state),
};
return lxc_cmd_rsp_send(fd, &rsp); return lxc_cmd_rsp_send(fd, &rsp);
} }
...@@ -587,15 +586,15 @@ int lxc_cmd_stop(const char *name, const char *lxcpath) ...@@ -587,15 +586,15 @@ int lxc_cmd_stop(const char *name, const char *lxcpath)
{ {
int ret, stopped; int ret, stopped;
struct lxc_cmd_rr cmd = { struct lxc_cmd_rr cmd = {
.req = { .cmd = LXC_CMD_STOP }, .req = {
.cmd = LXC_CMD_STOP,
},
}; };
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL); ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
if (ret < 0) { if (ret < 0) {
if (stopped) { if (stopped)
INFO("Container \"%s\" is already stopped", name); return log_info(0, "Container \"%s\" is already stopped", name);
return 0;
}
return -1; return -1;
} }
...@@ -603,14 +602,10 @@ int lxc_cmd_stop(const char *name, const char *lxcpath) ...@@ -603,14 +602,10 @@ int lxc_cmd_stop(const char *name, const char *lxcpath)
/* We do not expect any answer, because we wait for the connection to be /* We do not expect any answer, because we wait for the connection to be
* closed. * closed.
*/ */
if (ret > 0) { if (ret > 0)
errno = -cmd.rsp.ret; return log_error_errno(-1, -cmd.rsp.ret, "Failed to stop container \"%s\"", name);
SYSERROR("Failed to stop container \"%s\"", name);
return -1;
}
INFO("Container \"%s\" has stopped", name); return log_info(0, "Container \"%s\" has stopped", name);
return 0;
} }
static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req, static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req,
...@@ -657,7 +652,7 @@ static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req, ...@@ -657,7 +652,7 @@ static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
struct lxc_epoll_descr *descr) struct lxc_epoll_descr *descr)
{ {
/* should never be called */ /* should never be called */
return -1; return log_error_errno(-1, ENOSYS, "Called lxc_cmd_terminal_winch_callback()");
} }
/* /*
...@@ -676,7 +671,10 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath) ...@@ -676,7 +671,10 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
__do_free struct lxc_cmd_console_rsp_data *rspdata = NULL; __do_free struct lxc_cmd_console_rsp_data *rspdata = NULL;
int ret, stopped; int ret, stopped;
struct lxc_cmd_rr cmd = { struct lxc_cmd_rr cmd = {
.req = { .cmd = LXC_CMD_CONSOLE, .data = INT_TO_PTR(*ttynum) }, .req = {
.cmd = LXC_CMD_CONSOLE,
.data = INT_TO_PTR(*ttynum),
},
}; };
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL); ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
...@@ -684,28 +682,20 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath) ...@@ -684,28 +682,20 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
return ret; return ret;
rspdata = cmd.rsp.data; rspdata = cmd.rsp.data;
if (cmd.rsp.ret < 0) { if (cmd.rsp.ret < 0)
errno = -cmd.rsp.ret; return log_error_errno(-1, -cmd.rsp.ret, "Denied access to tty");
SYSERROR("Denied access to tty");
return -1;
}
if (ret == 0) { if (ret == 0)
ERROR("tty number %d invalid, busy or all ttys busy", *ttynum); return log_error(-1, "tty number %d invalid, busy or all ttys busy", *ttynum);
return -1;
}
if (rspdata->masterfd < 0) { if (rspdata->masterfd < 0)
ERROR("Unable to allocate fd for tty %d", rspdata->ttynum); return log_error(-1, "Unable to allocate fd for tty %d", rspdata->ttynum);
return -1;
}
ret = cmd.rsp.ret; /* socket fd */ ret = cmd.rsp.ret; /* socket fd */
*fd = rspdata->masterfd; *fd = rspdata->masterfd;
*ttynum = rspdata->ttynum; *ttynum = rspdata->ttynum;
INFO("Alloced fd %d for tty %d via socket %d", *fd, rspdata->ttynum, ret);
return ret; return log_info(ret, "Alloced fd %d for tty %d via socket %d", *fd, rspdata->ttynum, ret);
} }
static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req, static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req,
...@@ -749,7 +739,9 @@ char *lxc_cmd_get_name(const char *hashed_sock_name) ...@@ -749,7 +739,9 @@ char *lxc_cmd_get_name(const char *hashed_sock_name)
{ {
int ret, stopped; int ret, stopped;
struct lxc_cmd_rr cmd = { struct lxc_cmd_rr cmd = {
.req = { .cmd = LXC_CMD_GET_NAME}, .req = {
.cmd = LXC_CMD_GET_NAME,
},
}; };
ret = lxc_cmd(NULL, &cmd, &stopped, NULL, hashed_sock_name); ret = lxc_cmd(NULL, &cmd, &stopped, NULL, hashed_sock_name);
...@@ -788,7 +780,9 @@ char *lxc_cmd_get_lxcpath(const char *hashed_sock_name) ...@@ -788,7 +780,9 @@ char *lxc_cmd_get_lxcpath(const char *hashed_sock_name)
{ {
int ret, stopped; int ret, stopped;
struct lxc_cmd_rr cmd = { struct lxc_cmd_rr cmd = {
.req = { .cmd = LXC_CMD_GET_LXCPATH}, .req = {
.cmd = LXC_CMD_GET_LXCPATH,
},
}; };
ret = lxc_cmd(NULL, &cmd, &stopped, NULL, hashed_sock_name); ret = lxc_cmd(NULL, &cmd, &stopped, NULL, hashed_sock_name);
...@@ -805,13 +799,11 @@ static int lxc_cmd_get_lxcpath_callback(int fd, struct lxc_cmd_req *req, ...@@ -805,13 +799,11 @@ static int lxc_cmd_get_lxcpath_callback(int fd, struct lxc_cmd_req *req,
struct lxc_handler *handler, struct lxc_handler *handler,
struct lxc_epoll_descr *descr) struct lxc_epoll_descr *descr)
{ {
struct lxc_cmd_rsp rsp; struct lxc_cmd_rsp rsp = {
.ret = 0,
memset(&rsp, 0, sizeof(rsp)); .data = (char *)handler->lxcpath,
.datalen = strlen(handler->lxcpath) + 1,
rsp.ret = 0; };
rsp.data = (char *)handler->lxcpath;
rsp.datalen = strlen(handler->lxcpath) + 1;
return lxc_cmd_rsp_send(fd, &rsp); return lxc_cmd_rsp_send(fd, &rsp);
} }
...@@ -824,11 +816,11 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath, ...@@ -824,11 +816,11 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
int state, stopped; int state, stopped;
ssize_t ret; ssize_t ret;
struct lxc_cmd_rr cmd = { struct lxc_cmd_rr cmd = {
.req = { .req = {
.cmd = LXC_CMD_ADD_STATE_CLIENT, .cmd = LXC_CMD_ADD_STATE_CLIENT,
.data = states, .data = states,
.datalen = (sizeof(lxc_state_t) * MAX_STATE) .datalen = (sizeof(lxc_state_t) * MAX_STATE)
}, },
}; };
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL); ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
...@@ -846,21 +838,15 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath, ...@@ -846,21 +838,15 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
* function. * function.
*/ */
clientfd = cmd.rsp.ret; clientfd = cmd.rsp.ret;
if (clientfd < 0) { if (clientfd < 0)
errno = -clientfd; return log_error_errno(-1, -clientfd, "Failed to receive socket fd");
SYSERROR("Failed to receive socket fd");
return -1;
}
state = PTR_TO_INT(cmd.rsp.data); state = PTR_TO_INT(cmd.rsp.data);
if (state < MAX_STATE) { if (state < MAX_STATE)
TRACE("Container is already in requested state %s", lxc_state2str(state)); return log_trace(state, "Container is already in requested state %s", lxc_state2str(state));
return state;
}
*state_client_fd = move_fd(clientfd); *state_client_fd = move_fd(clientfd);
TRACE("Added state client %d to state client list", *state_client_fd); return log_trace(MAX_STATE, "Added state client %d to state client list", *state_client_fd);
return MAX_STATE;
} }
static int lxc_cmd_add_state_client_callback(__owns int fd, struct lxc_cmd_req *req, static int lxc_cmd_add_state_client_callback(__owns int fd, struct lxc_cmd_req *req,
...@@ -908,11 +894,11 @@ int lxc_cmd_add_bpf_device_cgroup(const char *name, const char *lxcpath, ...@@ -908,11 +894,11 @@ int lxc_cmd_add_bpf_device_cgroup(const char *name, const char *lxcpath,
#ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX #ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX
int stopped = 0; int stopped = 0;
struct lxc_cmd_rr cmd = { struct lxc_cmd_rr cmd = {
.req = { .req = {
.cmd = LXC_CMD_ADD_BPF_DEVICE_CGROUP, .cmd = LXC_CMD_ADD_BPF_DEVICE_CGROUP,
.data = device, .data = device,
.datalen = sizeof(struct device_item), .datalen = sizeof(struct device_item),
}, },
}; };
int ret; int ret;
...@@ -1094,17 +1080,15 @@ int lxc_cmd_serve_state_clients(const char *name, const char *lxcpath, ...@@ -1094,17 +1080,15 @@ int lxc_cmd_serve_state_clients(const char *name, const char *lxcpath,
int stopped; int stopped;
ssize_t ret; ssize_t ret;
struct lxc_cmd_rr cmd = { struct lxc_cmd_rr cmd = {
.req = { .req = {
.cmd = LXC_CMD_SERVE_STATE_CLIENTS, .cmd = LXC_CMD_SERVE_STATE_CLIENTS,
.data = INT_TO_PTR(state) .data = INT_TO_PTR(state)
}, },
}; };
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL); ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to execute command"); return log_error_errno(-1, errno, "Failed to serve state clients");
return -1;
}
return 0; return 0;
} }
...@@ -1128,8 +1112,9 @@ static int lxc_cmd_serve_state_clients_callback(int fd, struct lxc_cmd_req *req, ...@@ -1128,8 +1112,9 @@ static int lxc_cmd_serve_state_clients_callback(int fd, struct lxc_cmd_req *req,
return 0; return 0;
reap_client_fd: reap_client_fd:
/* Special indicator to lxc_cmd_handler() to close the fd and do related /*
* cleanup. * Special indicator to lxc_cmd_handler() to close the fd and do
* related cleanup.
*/ */
return 1; return 1;
} }
...@@ -1150,10 +1135,8 @@ int lxc_cmd_seccomp_notify_add_listener(const char *name, const char *lxcpath, ...@@ -1150,10 +1135,8 @@ int lxc_cmd_seccomp_notify_add_listener(const char *name, const char *lxcpath,
}; };
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL); ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to execute command"); return log_error_errno(-1, errno, "Failed to add seccomp listener");
return -1;
}
return cmd.rsp.ret; return cmd.rsp.ret;
#else #else
...@@ -1224,7 +1207,7 @@ static int lxc_cmd_freeze_callback(int fd, struct lxc_cmd_req *req, ...@@ -1224,7 +1207,7 @@ static int lxc_cmd_freeze_callback(int fd, struct lxc_cmd_req *req,
{ {
int timeout = PTR_TO_INT(req->data); int timeout = PTR_TO_INT(req->data);
struct lxc_cmd_rsp rsp = { struct lxc_cmd_rsp rsp = {
.ret = -ENOENT, .ret = -ENOENT,
}; };
struct cgroup_ops *ops = handler->cgroup_ops; struct cgroup_ops *ops = handler->cgroup_ops;
...@@ -1257,7 +1240,7 @@ static int lxc_cmd_unfreeze_callback(int fd, struct lxc_cmd_req *req, ...@@ -1257,7 +1240,7 @@ static int lxc_cmd_unfreeze_callback(int fd, struct lxc_cmd_req *req,
{ {
int timeout = PTR_TO_INT(req->data); int timeout = PTR_TO_INT(req->data);
struct lxc_cmd_rsp rsp = { struct lxc_cmd_rsp rsp = {
.ret = -ENOENT, .ret = -ENOENT,
}; };
struct cgroup_ops *ops = handler->cgroup_ops; struct cgroup_ops *ops = handler->cgroup_ops;
...@@ -1451,28 +1434,20 @@ static int lxc_cmd_accept(int fd, uint32_t events, void *data, ...@@ -1451,28 +1434,20 @@ static int lxc_cmd_accept(int fd, uint32_t events, void *data,
int opt = 1, ret = -1; int opt = 1, ret = -1;
connection = accept(fd, NULL, 0); connection = accept(fd, NULL, 0);
if (connection < 0) { if (connection < 0)
SYSERROR("Failed to accept connection to run command"); return log_error_errno(LXC_MAINLOOP_ERROR, errno, "Failed to accept connection to run command");
return LXC_MAINLOOP_ERROR;
}
ret = fcntl(connection, F_SETFD, FD_CLOEXEC); ret = fcntl(connection, F_SETFD, FD_CLOEXEC);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set close-on-exec on incoming command connection"); return log_error_errno(ret, errno, "Failed to set close-on-exec on incoming command connection");
return ret;
}
ret = setsockopt(connection, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt)); ret = setsockopt(connection, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt));
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to enable necessary credentials on command socket"); return log_error_errno(ret, errno, "Failed to enable necessary credentials on command socket");
return ret;
}
ret = lxc_mainloop_add_handler(descr, connection, lxc_cmd_handler, data); ret = lxc_mainloop_add_handler(descr, connection, lxc_cmd_handler, data);
if (ret) { if (ret)
ERROR("Failed to add command handler"); return log_error(ret, "Failed to add command handler");
return ret;
}
move_fd(connection); move_fd(connection);
return ret; return ret;
...@@ -1490,21 +1465,17 @@ int lxc_cmd_init(const char *name, const char *lxcpath, const char *suffix) ...@@ -1490,21 +1465,17 @@ int lxc_cmd_init(const char *name, const char *lxcpath, const char *suffix)
fd = lxc_abstract_unix_open(path, SOCK_STREAM, 0); fd = lxc_abstract_unix_open(path, SOCK_STREAM, 0);
if (fd < 0) { if (fd < 0) {
SYSERROR("Failed to create command socket %s", &path[1]);
if (errno == EADDRINUSE) if (errno == EADDRINUSE)
ERROR("Container \"%s\" appears to be already running", name); ERROR("Container \"%s\" appears to be already running", name);
return -1; return log_error_errno(-1, errno, "Failed to create command socket %s", &path[1]);
} }
ret = fcntl(fd, F_SETFD, FD_CLOEXEC); ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set FD_CLOEXEC on command socket file descriptor"); return log_error_errno(-1, errno, "Failed to set FD_CLOEXEC on command socket file descriptor");
return -1;
}
TRACE("Created abstract unix socket \"%s\"", &path[1]); return log_trace(move_fd(fd), "Created abstract unix socket \"%s\"", &path[1]);
return move_fd(fd);
} }
int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr, int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
...@@ -1514,10 +1485,8 @@ int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr, ...@@ -1514,10 +1485,8 @@ int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
int ret; int ret;
ret = lxc_mainloop_add_handler(descr, fd, lxc_cmd_accept, handler); ret = lxc_mainloop_add_handler(descr, fd, lxc_cmd_accept, handler);
if (ret < 0) { if (ret < 0)
ERROR("Failed to add handler for command socket"); return log_error(ret, "Failed to add handler for command socket");
return ret;
}
move_fd(fd); move_fd(fd);
return ret; return ret;
......
...@@ -39,26 +39,18 @@ int lxc_cmd_sock_rcv_state(int state_client_fd, int timeout) ...@@ -39,26 +39,18 @@ int lxc_cmd_sock_rcv_state(int state_client_fd, int timeout)
out.tv_sec = timeout; out.tv_sec = timeout;
ret = setsockopt(state_client_fd, SOL_SOCKET, SO_RCVTIMEO, ret = setsockopt(state_client_fd, SOL_SOCKET, SO_RCVTIMEO,
(const void *)&out, sizeof(out)); (const void *)&out, sizeof(out));
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set %ds timeout on container " return log_error_errno(-1, errno, "Failed to set %ds timeout on container state socket", timeout);
"state socket",
timeout);
return -1;
}
} }
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
ret = lxc_recv_nointr(state_client_fd, &msg, sizeof(msg), 0); ret = lxc_recv_nointr(state_client_fd, &msg, sizeof(msg), 0);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to receive message"); return log_error_errno(-1, errno, "Failed to receive message");
return -1;
}
TRACE("Received state %s from state client %d",
lxc_state2str(msg.value), state_client_fd);
return msg.value; return log_trace(msg.value, "Received state %s from state client %d",
lxc_state2str(msg.value), state_client_fd);
} }
/* Register a new state client and retrieve state from command socket. */ /* Register a new state client and retrieve state from command socket. */
...@@ -110,26 +102,20 @@ int lxc_make_abstract_socket_name(char *path, size_t pathlen, ...@@ -110,26 +102,20 @@ int lxc_make_abstract_socket_name(char *path, size_t pathlen,
if (hashed_sock_name != NULL) { if (hashed_sock_name != NULL) {
ret = snprintf(offset, len, "lxc/%s/%s", hashed_sock_name, suffix); ret = snprintf(offset, len, "lxc/%s/%s", hashed_sock_name, suffix);
if (ret < 0 || ret >= len) { if (ret < 0 || (size_t)ret >= len)
ERROR("Failed to create abstract socket name"); return log_error_errno(-1, errno, "Failed to create abstract socket name");
return -1;
}
return 0; return 0;
} }
if (!lxcpath) { if (!lxcpath) {
lxcpath = lxc_global_config_value("lxc.lxcpath"); lxcpath = lxc_global_config_value("lxc.lxcpath");
if (!lxcpath) { if (!lxcpath)
ERROR("Failed to allocate memory"); return log_error(-1, "Failed to allocate memory");
return -1;
}
} }
ret = snprintf(offset, len, "%s/%s/%s", lxcpath, name, suffix); ret = snprintf(offset, len, "%s/%s/%s", lxcpath, name, suffix);
if (ret < 0) { if (ret < 0 || (size_t)ret >= len)
ERROR("Failed to create abstract socket name"); return log_error_errno(-1, errno, "Failed to create abstract socket name");
return -1;
}
if (ret < len) if (ret < len)
return 0; return 0;
...@@ -137,17 +123,13 @@ int lxc_make_abstract_socket_name(char *path, size_t pathlen, ...@@ -137,17 +123,13 @@ int lxc_make_abstract_socket_name(char *path, size_t pathlen,
tmplen = strlen(name) + strlen(lxcpath) + 2; tmplen = strlen(name) + strlen(lxcpath) + 2;
tmppath = must_realloc(NULL, tmplen); tmppath = must_realloc(NULL, tmplen);
ret = snprintf(tmppath, tmplen, "%s/%s", lxcpath, name); ret = snprintf(tmppath, tmplen, "%s/%s", lxcpath, name);
if (ret < 0 || (size_t)ret >= tmplen) { if (ret < 0 || (size_t)ret >= tmplen)
ERROR("Failed to create abstract socket name"); return log_error_errno(-1, errno, "Failed to create abstract socket name");
return -1;
}
hash = fnv_64a_buf(tmppath, ret, FNV1A_64_INIT); hash = fnv_64a_buf(tmppath, ret, FNV1A_64_INIT);
ret = snprintf(offset, len, "lxc/%016" PRIx64 "/%s", hash, suffix); ret = snprintf(offset, len, "lxc/%016" PRIx64 "/%s", hash, suffix);
if (ret < 0 || ret >= len) { if (ret < 0 || ret >= len)
ERROR("Failed to create abstract socket name"); return log_error_errno(-1, errno, "Failed to create abstract socket name");
return -1;
}
return 0; return 0;
} }
...@@ -198,8 +180,7 @@ int lxc_add_state_client(int state_client_fd, struct lxc_handler *handler, ...@@ -198,8 +180,7 @@ int lxc_add_state_client(int state_client_fd, struct lxc_handler *handler,
return state; return state;
} }
TRACE("Added state client %d to state client list", state_client_fd);
move_ptr(newclient); move_ptr(newclient);
move_ptr(tmplist); move_ptr(tmplist);
return MAX_STATE; return log_trace(MAX_STATE, "Added state client %d to state client list", state_client_fd);
} }
...@@ -288,28 +288,20 @@ static struct limit_opt limit_opt[] = { ...@@ -288,28 +288,20 @@ static struct limit_opt limit_opt[] = {
static int run_buffer(char *buffer) static int run_buffer(char *buffer)
{ {
__do_free char *output = NULL; __do_free char *output = NULL;
__do_lxc_pclose struct lxc_popen_FILE *f = NULL;
int fd, ret; int fd, ret;
struct lxc_popen_FILE *f;
f = lxc_popen(buffer); f = lxc_popen(buffer);
if (!f) { if (!f)
SYSERROR("Failed to popen() %s", buffer); return log_error_errno(-1, errno, "Failed to popen() %s", buffer);
return -1;
}
output = malloc(LXC_LOG_BUFFER_SIZE); output = malloc(LXC_LOG_BUFFER_SIZE);
if (!output) { if (!output)
ERROR("Failed to allocate memory for %s", buffer); return log_error_errno(-1, ENOMEM, "Failed to allocate memory for %s", buffer);
lxc_pclose(f);
return -1;
}
fd = fileno(f->f); fd = fileno(f->f);
if (fd < 0) { if (fd < 0)
SYSERROR("Failed to retrieve underlying file descriptor"); return log_error_errno(-1, errno, "Failed to retrieve underlying file descriptor");
lxc_pclose(f);
return -1;
}
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
ssize_t bytes_read; ssize_t bytes_read;
...@@ -324,17 +316,13 @@ static int run_buffer(char *buffer) ...@@ -324,17 +316,13 @@ static int run_buffer(char *buffer)
break; break;
} }
ret = lxc_pclose(f); ret = lxc_pclose(move_ptr(f));
if (ret == -1) { if (ret == -1)
SYSERROR("Script exited with error"); return log_error_errno(-1, errno, "Script exited with error");
return -1; else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0)
} else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { return log_error(-1, "Script exited with status %d", WEXITSTATUS(ret));
ERROR("Script exited with status %d", WEXITSTATUS(ret)); else if (WIFSIGNALED(ret))
return -1; return log_error(-1, "Script terminated by signal %d", WTERMSIG(ret));
} else if (WIFSIGNALED(ret)) {
ERROR("Script terminated by signal %d", WTERMSIG(ret));
return -1;
}
return 0; return 0;
} }
...@@ -348,8 +336,8 @@ int run_script_argv(const char *name, unsigned int hook_version, ...@@ -348,8 +336,8 @@ int run_script_argv(const char *name, unsigned int hook_version,
size_t size = 0; size_t size = 0;
if (hook_version == 0) if (hook_version == 0)
INFO("Executing script \"%s\" for container \"%s\", config " INFO("Executing script \"%s\" for container \"%s\", config section \"%s\"",
"section \"%s\"", script, name, section); script, name, section);
else else
INFO("Executing script \"%s\" for container \"%s\"", script, name); INFO("Executing script \"%s\" for container \"%s\"", script, name);
...@@ -386,26 +374,19 @@ int run_script_argv(const char *name, unsigned int hook_version, ...@@ -386,26 +374,19 @@ int run_script_argv(const char *name, unsigned int hook_version,
buf_pos = snprintf(buffer, size, "exec %s %s %s %s", script, name, section, hookname); buf_pos = snprintf(buffer, size, "exec %s %s %s %s", script, name, section, hookname);
else else
buf_pos = snprintf(buffer, size, "exec %s", script); buf_pos = snprintf(buffer, size, "exec %s", script);
if (buf_pos < 0 || (size_t)buf_pos >= size) { if (buf_pos < 0 || (size_t)buf_pos >= size)
ERROR("Failed to create command line for script \"%s\"", script); return log_error_errno(-1, errno, "Failed to create command line for script \"%s\"", script);
return -1;
}
if (hook_version == 1) { if (hook_version == 1) {
ret = setenv("LXC_HOOK_TYPE", hookname, 1); ret = setenv("LXC_HOOK_TYPE", hookname, 1);
if (ret < 0) { if (ret < 0) {
SYSERROR("Failed to set environment variable: " return log_error_errno(-1, errno, "Failed to set environment variable: LXC_HOOK_TYPE=%s", hookname);
"LXC_HOOK_TYPE=%s", hookname);
return -1;
} }
TRACE("Set environment variable: LXC_HOOK_TYPE=%s", hookname); TRACE("Set environment variable: LXC_HOOK_TYPE=%s", hookname);
ret = setenv("LXC_HOOK_SECTION", section, 1); ret = setenv("LXC_HOOK_SECTION", section, 1);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set environment variable: " return log_error_errno(-1, errno, "Failed to set environment variable: LXC_HOOK_SECTION=%s", section);
"LXC_HOOK_SECTION=%s", section);
return -1;
}
TRACE("Set environment variable: LXC_HOOK_SECTION=%s", section); TRACE("Set environment variable: LXC_HOOK_SECTION=%s", section);
if (strcmp(section, "net") == 0) { if (strcmp(section, "net") == 0) {
...@@ -415,48 +396,33 @@ int run_script_argv(const char *name, unsigned int hook_version, ...@@ -415,48 +396,33 @@ int run_script_argv(const char *name, unsigned int hook_version,
return -1; return -1;
ret = setenv("LXC_NET_TYPE", argv[0], 1); ret = setenv("LXC_NET_TYPE", argv[0], 1);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set environment variable: " return log_error_errno(-1, errno, "Failed to set environment variable: LXC_NET_TYPE=%s", argv[0]);
"LXC_NET_TYPE=%s", argv[0]);
return -1;
}
TRACE("Set environment variable: LXC_NET_TYPE=%s", argv[0]); TRACE("Set environment variable: LXC_NET_TYPE=%s", argv[0]);
parent = argv[1] ? argv[1] : ""; parent = argv[1] ? argv[1] : "";
if (strcmp(argv[0], "macvlan") == 0) { if (strcmp(argv[0], "macvlan") == 0) {
ret = setenv("LXC_NET_PARENT", parent, 1); ret = setenv("LXC_NET_PARENT", parent, 1);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set environment " return log_error_errno(-1, errno, "Failed to set environment variable: LXC_NET_PARENT=%s", parent);
"variable: LXC_NET_PARENT=%s", parent);
return -1;
}
TRACE("Set environment variable: LXC_NET_PARENT=%s", parent); TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
} else if (strcmp(argv[0], "phys") == 0) { } else if (strcmp(argv[0], "phys") == 0) {
ret = setenv("LXC_NET_PARENT", parent, 1); ret = setenv("LXC_NET_PARENT", parent, 1);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set environment " return log_error_errno(-1, errno, "Failed to set environment variable: LXC_NET_PARENT=%s", parent);
"variable: LXC_NET_PARENT=%s", parent);
return -1;
}
TRACE("Set environment variable: LXC_NET_PARENT=%s", parent); TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
} else if (strcmp(argv[0], "veth") == 0) { } else if (strcmp(argv[0], "veth") == 0) {
char *peer = argv[2] ? argv[2] : ""; char *peer = argv[2] ? argv[2] : "";
ret = setenv("LXC_NET_PEER", peer, 1); ret = setenv("LXC_NET_PEER", peer, 1);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set environment " return log_error_errno(-1, errno, "Failed to set environment variable: LXC_NET_PEER=%s", peer);
"variable: LXC_NET_PEER=%s", peer);
return -1;
}
TRACE("Set environment variable: LXC_NET_PEER=%s", peer); TRACE("Set environment variable: LXC_NET_PEER=%s", peer);
ret = setenv("LXC_NET_PARENT", parent, 1); ret = setenv("LXC_NET_PARENT", parent, 1);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set environment " return log_error_errno(-1, errno, "Failed to set environment variable: LXC_NET_PARENT=%s", parent);
"variable: LXC_NET_PARENT=%s", parent);
return -1;
}
TRACE("Set environment variable: LXC_NET_PARENT=%s", parent); TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
} }
} }
...@@ -466,10 +432,8 @@ int run_script_argv(const char *name, unsigned int hook_version, ...@@ -466,10 +432,8 @@ int run_script_argv(const char *name, unsigned int hook_version,
size_t len = size - buf_pos; size_t len = size - buf_pos;
ret = snprintf(buffer + buf_pos, len, " %s", argv[i]); ret = snprintf(buffer + buf_pos, len, " %s", argv[i]);
if (ret < 0 || (size_t)ret >= len) { if (ret < 0 || (size_t)ret >= len)
ERROR("Failed to create command line for script \"%s\"", script); return log_error_errno(-1, errno, "Failed to create command line for script \"%s\"", script);
return -1;
}
buf_pos += ret; buf_pos += ret;
} }
...@@ -554,11 +518,11 @@ int pin_rootfs(const char *rootfs) ...@@ -554,11 +518,11 @@ int pin_rootfs(const char *rootfs)
if (!S_ISDIR(s.st_mode)) if (!S_ISDIR(s.st_mode))
return -2; return -2;
ret = snprintf(absrootfspin, PATH_MAX, "%s/.lxc-keep", absrootfs); ret = snprintf(absrootfspin, sizeof(absrootfspin), "%s/.lxc-keep", absrootfs);
if (ret < 0 || ret >= PATH_MAX) if (ret < 0 || (size_t)ret >= sizeof(absrootfspin))
return -1; return -1;
fd = open(absrootfspin, O_CREAT | O_RDWR, S_IWUSR | S_IRUSR); fd = open(absrootfspin, O_CREAT | O_RDWR, S_IWUSR | S_IRUSR | O_CLOEXEC);
if (fd < 0) if (fd < 0)
return fd; return fd;
...@@ -566,10 +530,8 @@ int pin_rootfs(const char *rootfs) ...@@ -566,10 +530,8 @@ int pin_rootfs(const char *rootfs)
if (ret < 0) if (ret < 0)
return fd; return fd;
if (sfs.f_type == NFS_SUPER_MAGIC) { if (sfs.f_type == NFS_SUPER_MAGIC)
DEBUG("Rootfs on NFS, not unlinking pin file \"%s\"", absrootfspin); return log_debug(fd, "Rootfs on NFS, not unlinking pin file \"%s\"", absrootfspin);
return fd;
}
(void)unlink(absrootfspin); (void)unlink(absrootfspin);
...@@ -700,16 +662,13 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha ...@@ -700,16 +662,13 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
return -1; return -1;
} }
if (!default_mounts[i].destination) { if (!default_mounts[i].destination)
ERROR("BUG: auto mounts destination %d was NULL", i); return log_error(-1, "BUG: auto mounts destination %d was NULL", i);
return -1;
}
/* will act like strdup if %r is not present */ /* will act like strdup if %r is not present */
destination = lxc_string_replace("%r", conf->rootfs.path ? conf->rootfs.mount : "", default_mounts[i].destination); destination = lxc_string_replace("%r", conf->rootfs.path ? conf->rootfs.mount : "", default_mounts[i].destination);
if (!destination) { if (!destination)
return -1; return -1;
}
mflags = add_required_remount_flags(source, destination, mflags = add_required_remount_flags(source, destination,
default_mounts[i].flags); default_mounts[i].flags);
...@@ -718,8 +677,7 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha ...@@ -718,8 +677,7 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
conf->rootfs.path ? conf->rootfs.mount : NULL); conf->rootfs.path ? conf->rootfs.mount : NULL);
saved_errno = errno; saved_errno = errno;
if (r < 0 && errno == ENOENT) { if (r < 0 && errno == ENOENT) {
INFO("Mount source or target for \"%s\" on \"%s\" does " INFO("Mount source or target for \"%s\" on \"%s\" does not exist. Skipping", source, destination);
"not exist. Skipping", source, destination);
r = 0; r = 0;
} else if (r < 0) { } else if (r < 0) {
SYSERROR("Failed to mount \"%s\" on \"%s\" with flags %lu", source, destination, mflags); SYSERROR("Failed to mount \"%s\" on \"%s\" with flags %lu", source, destination, mflags);
...@@ -765,18 +723,14 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha ...@@ -765,18 +723,14 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
if (!handler->cgroup_ops->mount(handler->cgroup_ops, if (!handler->cgroup_ops->mount(handler->cgroup_ops,
handler, handler,
conf->rootfs.path ? conf->rootfs.mount : "", conf->rootfs.path ? conf->rootfs.mount : "",
cg_flags)) { cg_flags))
SYSERROR("Failed to mount \"/sys/fs/cgroup\""); return log_error_errno(-1, errno, "Failed to mount \"/sys/fs/cgroup\"");
return -1;
}
} }
if (flags & LXC_AUTO_SHMOUNTS_MASK) { if (flags & LXC_AUTO_SHMOUNTS_MASK) {
int ret = add_shmount_to_list(conf); int ret = add_shmount_to_list(conf);
if (ret < 0) { if (ret < 0)
ERROR("Failed to add shmount entry to container config"); return log_error(-1, "Failed to add shmount entry to container config");
return -1;
}
} }
return 0; return 0;
...@@ -790,10 +744,9 @@ static int setup_utsname(struct utsname *utsname) ...@@ -790,10 +744,9 @@ static int setup_utsname(struct utsname *utsname)
return 0; return 0;
ret = sethostname(utsname->nodename, strlen(utsname->nodename)); ret = sethostname(utsname->nodename, strlen(utsname->nodename));
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set the hostname to \"%s\"", utsname->nodename); return log_error_errno(-1, errno, "Failed to set the hostname to \"%s\"",
return -1; utsname->nodename);
}
INFO("Set hostname to \"%s\"", utsname->nodename); INFO("Set hostname to \"%s\"", utsname->nodename);
...@@ -823,7 +776,7 @@ static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs) ...@@ -823,7 +776,7 @@ static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs)
ret = snprintf(path, sizeof(path), "%s/dev/%s", ret = snprintf(path, sizeof(path), "%s/dev/%s",
rootfs->path ? rootfs->mount : "", d->name); rootfs->path ? rootfs->mount : "", d->name);
if (ret < 0 || ret >= PATH_MAX) if (ret < 0 || (size_t)ret >= sizeof(path))
return -1; return -1;
/* Stat the path first. If we don't get an error accept it as /* Stat the path first. If we don't get an error accept it as
...@@ -835,12 +788,10 @@ static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs) ...@@ -835,12 +788,10 @@ static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs)
ret = symlink(d->oldpath, path); ret = symlink(d->oldpath, path);
if (ret && errno != EEXIST) { if (ret && errno != EEXIST) {
if (errno == EROFS) { if (errno == EROFS)
WARN("Failed to create \"%s\". Read-only filesystem", path); WARN("Failed to create \"%s\". Read-only filesystem", path);
} else { else
SYSERROR("Failed to create \"%s\"", path); return log_error_errno(-1, errno, "Failed to create \"%s\"", path);
return -1;
}
} }
} }
...@@ -912,12 +863,10 @@ static int lxc_setup_ttys(struct lxc_conf *conf) ...@@ -912,12 +863,10 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
ret = mount(tty->name, lxcpath, "none", MS_BIND, 0); ret = mount(tty->name, lxcpath, "none", MS_BIND, 0);
if (ret < 0) { if (ret < 0) {
SYSWARN("Failed to bind mount \"%s\" onto \"%s\"", SYSWARN("Failed to bind mount \"%s\" onto \"%s\"", tty->name, lxcpath);
tty->name, lxcpath);
continue; continue;
} }
DEBUG("Bind mounted \"%s\" onto \"%s\"", tty->name, DEBUG("Bind mounted \"%s\" onto \"%s\"", tty->name, lxcpath);
lxcpath);
ret = snprintf(lxcpath, sizeof(lxcpath), "%s/tty%d", ret = snprintf(lxcpath, sizeof(lxcpath), "%s/tty%d",
ttydir, i + 1); ttydir, i + 1);
...@@ -925,11 +874,8 @@ static int lxc_setup_ttys(struct lxc_conf *conf) ...@@ -925,11 +874,8 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
return -1; return -1;
ret = symlink(lxcpath, path); ret = symlink(lxcpath, path);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to create symlink \"%s\" -> \"%s\"", return log_error_errno(-1, errno, "Failed to create symlink \"%s\" -> \"%s\"", path, lxcpath);
path, lxcpath);
return -1;
}
} else { } else {
/* If we populated /dev, then we need to create /* If we populated /dev, then we need to create
* /dev/ttyN * /dev/ttyN
...@@ -947,10 +893,8 @@ static int lxc_setup_ttys(struct lxc_conf *conf) ...@@ -947,10 +893,8 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
DEBUG("Bind mounted \"%s\" onto \"%s\"", tty->name, path); DEBUG("Bind mounted \"%s\" onto \"%s\"", tty->name, path);
} }
if (!append_ttyname(&conf->ttys.tty_names, tty->name)) { if (!append_ttyname(&conf->ttys.tty_names, tty->name))
ERROR("Error setting up container_ttys string"); return log_error(-1, "Error setting up container_ttys string");
return -1;
}
} }
INFO("Finished setting up %zu /dev/tty<N> device(s)", ttys->max); INFO("Finished setting up %zu /dev/tty<N> device(s)", ttys->max);
...@@ -959,7 +903,7 @@ static int lxc_setup_ttys(struct lxc_conf *conf) ...@@ -959,7 +903,7 @@ static int lxc_setup_ttys(struct lxc_conf *conf)
int lxc_allocate_ttys(struct lxc_conf *conf) int lxc_allocate_ttys(struct lxc_conf *conf)
{ {
size_t i; __do_free struct lxc_terminal_info *tty_new = NULL;
int ret; int ret;
struct lxc_tty_info *ttys = &conf->ttys; struct lxc_tty_info *ttys = &conf->ttys;
...@@ -967,29 +911,28 @@ int lxc_allocate_ttys(struct lxc_conf *conf) ...@@ -967,29 +911,28 @@ int lxc_allocate_ttys(struct lxc_conf *conf)
if (ttys->max == 0) if (ttys->max == 0)
return 0; return 0;
ttys->tty = malloc(sizeof(*ttys->tty) * ttys->max); tty_new = malloc(sizeof(struct lxc_terminal_info) * ttys->max);
if (!ttys->tty) if (!tty_new)
return -ENOMEM; return -ENOMEM;
ttys->tty = tty_new;
for (i = 0; i < ttys->max; i++) { for (size_t i = 0; i < ttys->max; i++) {
struct lxc_terminal_info *tty = &ttys->tty[i]; struct lxc_terminal_info *tty = &ttys->tty[i];
tty->master = -EBADF; tty->master = -EBADF;
tty->slave = -EBADF; tty->slave = -EBADF;
ret = openpty(&tty->master, &tty->slave, NULL, NULL, NULL); ret = openpty(&tty->master, &tty->slave, NULL, NULL, NULL);
if (ret < 0) { if (ret < 0) {
SYSERROR("Failed to create tty %zu", i);
ttys->max = i; ttys->max = i;
lxc_delete_tty(ttys); lxc_delete_tty(ttys);
return -ENOTTY; return log_error_errno(-ENOTTY, ENOTTY, "Failed to create tty %zu", i);
} }
ret = ttyname_r(tty->slave, tty->name, sizeof(tty->name)); ret = ttyname_r(tty->slave, tty->name, sizeof(tty->name));
if (ret < 0) { if (ret < 0) {
SYSERROR("Failed to retrieve name of tty %zu slave", i);
ttys->max = i; ttys->max = i;
lxc_delete_tty(ttys); lxc_delete_tty(ttys);
return -ENOTTY; return log_error_errno(-ENOTTY, ENOTTY, "Failed to retrieve name of tty %zu slave", i);
} }
DEBUG("Created tty \"%s\" with master fd %d and slave fd %d", DEBUG("Created tty \"%s\" with master fd %d and slave fd %d",
...@@ -1010,32 +953,22 @@ int lxc_allocate_ttys(struct lxc_conf *conf) ...@@ -1010,32 +953,22 @@ int lxc_allocate_ttys(struct lxc_conf *conf)
} }
INFO("Finished creating %zu tty devices", ttys->max); INFO("Finished creating %zu tty devices", ttys->max);
ttys->tty = move_ptr(tty_new);
return 0; return 0;
} }
void lxc_delete_tty(struct lxc_tty_info *ttys) void lxc_delete_tty(struct lxc_tty_info *ttys)
{ {
int i;
if (!ttys->tty) if (!ttys->tty)
return; return;
for (i = 0; i < ttys->max; i++) { for (int i = 0; i < ttys->max; i++) {
struct lxc_terminal_info *tty = &ttys->tty[i]; struct lxc_terminal_info *tty = &ttys->tty[i];
close_prot_errno_disarm(tty->master);
if (tty->master >= 0) { close_prot_errno_disarm(tty->slave);
close(tty->master);
tty->master = -EBADF;
}
if (tty->slave >= 0) {
close(tty->slave);
tty->slave = -EBADF;
}
} }
free(ttys->tty); free_disarm(ttys->tty);
ttys->tty = NULL;
} }
static int lxc_send_ttys_to_parent(struct lxc_handler *handler) static int lxc_send_ttys_to_parent(struct lxc_handler *handler)
...@@ -1060,8 +993,8 @@ static int lxc_send_ttys_to_parent(struct lxc_handler *handler) ...@@ -1060,8 +993,8 @@ static int lxc_send_ttys_to_parent(struct lxc_handler *handler)
if (ret < 0) if (ret < 0)
break; break;
TRACE("Sent tty \"%s\" with master fd %d and slave fd %d to " TRACE("Sent tty \"%s\" with master fd %d and slave fd %d to parent",
"parent", tty->name, tty->master, tty->slave); tty->name, tty->master, tty->slave);
} }
if (ret < 0) if (ret < 0)
...@@ -1233,10 +1166,8 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) ...@@ -1233,10 +1166,8 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
if (ret == 0 || (ret < 0 && errno == EEXIST)) { if (ret == 0 || (ret < 0 && errno == EEXIST)) {
DEBUG("Created device node \"%s\"", path); DEBUG("Created device node \"%s\"", path);
} else if (ret < 0) { } else if (ret < 0) {
if (errno != EPERM) { if (errno != EPERM)
SYSERROR("Failed to create device node \"%s\"", path); return log_error_errno(-1, errno, "Failed to create device node \"%s\"", path);
return -1;
}
use_mknod = LXC_DEVNODE_BIND; use_mknod = LXC_DEVNODE_BIND;
} }
...@@ -1270,10 +1201,8 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) ...@@ -1270,10 +1201,8 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
* device node so we can use it as a bind-mount target. * device node so we can use it as a bind-mount target.
*/ */
ret = mknod(path, S_IFREG | 0000, 0); ret = mknod(path, S_IFREG | 0000, 0);
if (ret < 0 && errno != EEXIST) { if (ret < 0 && errno != EEXIST)
SYSERROR("Failed to create file \"%s\"", path); return log_error_errno(-1, errno, "Failed to create file \"%s\"", path);
return -1;
}
} }
/* Fallback to bind-mounting the device from the host. */ /* Fallback to bind-mounting the device from the host. */
...@@ -1283,13 +1212,10 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) ...@@ -1283,13 +1212,10 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
ret = safe_mount(hostpath, path, 0, MS_BIND, NULL, ret = safe_mount(hostpath, path, 0, MS_BIND, NULL,
rootfs->path ? rootfs->mount : NULL); rootfs->path ? rootfs->mount : NULL);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to bind mount host device node \"%s\" " return log_error_errno(-1, errno, "Failed to bind mount host device node \"%s\" onto \"%s\"",
"onto \"%s\"", hostpath, path); hostpath, path);
return -1; DEBUG("Bind mounted host device node \"%s\" onto \"%s\"", hostpath, path);
}
DEBUG("Bind mounted host device node \"%s\" onto \"%s\"",
hostpath, path);
} }
(void)umask(cmask); (void)umask(cmask);
...@@ -1305,37 +1231,29 @@ static int lxc_mount_rootfs(struct lxc_conf *conf) ...@@ -1305,37 +1231,29 @@ static int lxc_mount_rootfs(struct lxc_conf *conf)
if (!rootfs->path) { if (!rootfs->path) {
ret = mount("", "/", NULL, MS_SLAVE | MS_REC, 0); ret = mount("", "/", NULL, MS_SLAVE | MS_REC, 0);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to remount \"/\" MS_REC | MS_SLAVE"); return log_error_errno(-1, errno, "Failed to remount \"/\" MS_REC | MS_SLAVE");
return -1;
}
return 0; return 0;
} }
ret = access(rootfs->mount, F_OK); ret = access(rootfs->mount, F_OK);
if (ret != 0) { if (ret != 0)
SYSERROR("Failed to access to \"%s\". Check it is present", return log_error_errno(-1, errno, "Failed to access to \"%s\". Check it is present",
rootfs->mount); rootfs->mount);
return -1;
}
bdev = storage_init(conf); bdev = storage_init(conf);
if (!bdev) { if (!bdev)
ERROR("Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\"", return log_error(-1, "Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\"",
rootfs->path, rootfs->mount, rootfs->path, rootfs->mount,
rootfs->options ? rootfs->options : "(null)"); rootfs->options ? rootfs->options : "(null)");
return -1;
}
ret = bdev->ops->mount(bdev); ret = bdev->ops->mount(bdev);
storage_put(bdev); storage_put(bdev);
if (ret < 0) { if (ret < 0)
ERROR("Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\"", return log_error(-1, "Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\"",
rootfs->path, rootfs->mount, rootfs->path, rootfs->mount,
rootfs->options ? rootfs->options : "(null)"); rootfs->options ? rootfs->options : "(null)");
return -1;
}
DEBUG("Mounted rootfs \"%s\" onto \"%s\" with options \"%s\"", DEBUG("Mounted rootfs \"%s\" onto \"%s\" with options \"%s\"",
rootfs->path, rootfs->mount, rootfs->path, rootfs->mount,
...@@ -1351,10 +1269,8 @@ int lxc_chroot(const struct lxc_rootfs *rootfs) ...@@ -1351,10 +1269,8 @@ int lxc_chroot(const struct lxc_rootfs *rootfs)
char *root = rootfs->mount; char *root = rootfs->mount;
nroot = realpath(root, NULL); nroot = realpath(root, NULL);
if (!nroot) { if (!nroot)
SYSERROR("Failed to resolve \"%s\"", root); return log_error_errno(-1, errno, "Failed to resolve \"%s\"", root);
return -1;
}
ret = chdir("/"); ret = chdir("/");
if (ret < 0) if (ret < 0)
...@@ -1364,16 +1280,12 @@ int lxc_chroot(const struct lxc_rootfs *rootfs) ...@@ -1364,16 +1280,12 @@ int lxc_chroot(const struct lxc_rootfs *rootfs)
* can't be moved. * can't be moved.
*/ */
ret = mount(nroot, "/", NULL, MS_REC | MS_BIND, NULL); ret = mount(nroot, "/", NULL, MS_REC | MS_BIND, NULL);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to mount \"%s\" onto \"/\" as MS_REC | MS_BIND", nroot); return log_error_errno(-1, errno, "Failed to mount \"%s\" onto \"/\" as MS_REC | MS_BIND", nroot);
return -1;
}
ret = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL); ret = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to remount \"/\""); return log_error_errno(-1, errno, "Failed to remount \"/\"");
return -1;
}
/* The following code cleans up inherited mounts which are not required /* The following code cleans up inherited mounts which are not required
* for CT. * for CT.
...@@ -1393,10 +1305,8 @@ int lxc_chroot(const struct lxc_rootfs *rootfs) ...@@ -1393,10 +1305,8 @@ int lxc_chroot(const struct lxc_rootfs *rootfs)
size_t len = 0; size_t len = 0;
f = fopen("./proc/self/mountinfo", "re"); f = fopen("./proc/self/mountinfo", "re");
if (!f) { if (!f)
SYSERROR("Failed to open \"/proc/self/mountinfo\""); return log_error_errno(-1, errno, "Failed to open \"/proc/self/mountinfo\"");
return -1;
}
while (getline(&line, &len, f) > 0) { while (getline(&line, &len, f) > 0) {
for (slider1 = line, i = 0; slider1 && i < 4; i++) for (slider1 = line, i = 0; slider1 && i < 4; i++)
...@@ -1432,16 +1342,12 @@ int lxc_chroot(const struct lxc_rootfs *rootfs) ...@@ -1432,16 +1342,12 @@ int lxc_chroot(const struct lxc_rootfs *rootfs)
/* It is weird, but chdir("..") moves us in a new root */ /* It is weird, but chdir("..") moves us in a new root */
ret = chdir(".."); ret = chdir("..");
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to chdir(\"..\")"); return log_error_errno(-1, errno, "Failed to chdir(\"..\")");
return -1;
}
ret = chroot("."); ret = chroot(".");
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to chroot(\".\")"); return log_error_errno(-1, errno, "Failed to chroot(\".\")");
return -1;
}
return 0; return 0;
} }
...@@ -1478,61 +1384,45 @@ static int lxc_pivot_root(const char *rootfs) ...@@ -1478,61 +1384,45 @@ static int lxc_pivot_root(const char *rootfs)
int ret; int ret;
oldroot = open("/", O_DIRECTORY | O_RDONLY | O_CLOEXEC); oldroot = open("/", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
if (oldroot < 0) { if (oldroot < 0)
SYSERROR("Failed to open old root directory"); return log_error_errno(-1, errno, "Failed to open old root directory");
return -1;
}
newroot = open(rootfs, O_DIRECTORY | O_RDONLY | O_CLOEXEC); newroot = open(rootfs, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
if (newroot < 0) { if (newroot < 0)
SYSERROR("Failed to open new root directory"); return log_error_errno(-1, errno, "Failed to open new root directory");
return -1;
}
/* change into new root fs */ /* change into new root fs */
ret = fchdir(newroot); ret = fchdir(newroot);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to change to new rootfs \"%s\"", rootfs); return log_error_errno(-1, errno, "Failed to change to new rootfs \"%s\"", rootfs);
return -1;
}
/* pivot_root into our new root fs */ /* pivot_root into our new root fs */
ret = pivot_root(".", "."); ret = pivot_root(".", ".");
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to pivot_root()"); return log_error_errno(-1, errno, "Failed to pivot_root()");
return -1;
}
/* At this point the old-root is mounted on top of our new-root. To /* At this point the old-root is mounted on top of our new-root. To
* unmounted it we must not be chdir'd into it, so escape back to * unmounted it we must not be chdir'd into it, so escape back to
* old-root. * old-root.
*/ */
ret = fchdir(oldroot); ret = fchdir(oldroot);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to enter old root directory"); return log_error_errno(-1, errno, "Failed to enter old root directory");
return -1;
}
/* Make oldroot rslave to make sure our umounts don't propagate to the /* Make oldroot rslave to make sure our umounts don't propagate to the
* host. * host.
*/ */
ret = mount("", ".", "", MS_SLAVE | MS_REC, NULL); ret = mount("", ".", "", MS_SLAVE | MS_REC, NULL);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to make oldroot rslave"); return log_error_errno(-1, errno, "Failed to make oldroot rslave");
return -1;
}
ret = umount2(".", MNT_DETACH); ret = umount2(".", MNT_DETACH);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to detach old root directory"); return log_error_errno(-1, errno, "Failed to detach old root directory");
return -1;
}
ret = fchdir(newroot); ret = fchdir(newroot);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to re-enter new root directory"); return log_error_errno(-1, errno, "Failed to re-enter new root directory");
return -1;
}
TRACE("pivot_root(\"%s\") successful", rootfs); TRACE("pivot_root(\"%s\") successful", rootfs);
...@@ -1541,10 +1431,8 @@ static int lxc_pivot_root(const char *rootfs) ...@@ -1541,10 +1431,8 @@ static int lxc_pivot_root(const char *rootfs)
static int lxc_setup_rootfs_switch_root(const struct lxc_rootfs *rootfs) static int lxc_setup_rootfs_switch_root(const struct lxc_rootfs *rootfs)
{ {
if (!rootfs->path) { if (!rootfs->path)
DEBUG("Container does not have a rootfs"); return log_debug(0, "Container does not have a rootfs");
return 0;
}
if (detect_ramfs_rootfs()) if (detect_ramfs_rootfs())
return lxc_chroot(rootfs); return lxc_chroot(rootfs);
...@@ -1591,11 +1479,8 @@ static int lxc_setup_devpts(struct lxc_conf *conf) ...@@ -1591,11 +1479,8 @@ static int lxc_setup_devpts(struct lxc_conf *conf)
char *mntopt_sets[5]; char *mntopt_sets[5];
char default_devpts_mntopts[256] = "gid=5,newinstance,ptmxmode=0666,mode=0620"; char default_devpts_mntopts[256] = "gid=5,newinstance,ptmxmode=0666,mode=0620";
if (conf->pty_max <= 0) { if (conf->pty_max <= 0)
DEBUG("No new devpts instance will be mounted since no pts " return log_debug(0, "No new devpts instance will be mounted since no pts devices are requested");
"devices are requested");
return 0;
}
ret = snprintf(devpts_mntopts, sizeof(devpts_mntopts), "%s,max=%zu", ret = snprintf(devpts_mntopts, sizeof(devpts_mntopts), "%s,max=%zu",
default_devpts_mntopts, conf->pty_max); default_devpts_mntopts, conf->pty_max);
...@@ -1606,10 +1491,8 @@ static int lxc_setup_devpts(struct lxc_conf *conf) ...@@ -1606,10 +1491,8 @@ static int lxc_setup_devpts(struct lxc_conf *conf)
/* Create mountpoint for devpts instance. */ /* Create mountpoint for devpts instance. */
ret = mkdir("/dev/pts", 0755); ret = mkdir("/dev/pts", 0755);
if (ret < 0 && errno != EEXIST) { if (ret < 0 && errno != EEXIST)
SYSERROR("Failed to create \"/dev/pts\" directory"); return log_error_errno(-1, errno, "Failed to create \"/dev/pts\" directory");
return -1;
}
/* gid=5 && max= */ /* gid=5 && max= */
mntopt_sets[0] = devpts_mntopts; mntopt_sets[0] = devpts_mntopts;
...@@ -1633,54 +1516,42 @@ static int lxc_setup_devpts(struct lxc_conf *conf) ...@@ -1633,54 +1516,42 @@ static int lxc_setup_devpts(struct lxc_conf *conf)
break; break;
} }
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to mount new devpts instance"); return log_error_errno(-1, errno, "Failed to mount new devpts instance");
return -1;
}
DEBUG("Mount new devpts instance with options \"%s\"", *opts); DEBUG("Mount new devpts instance with options \"%s\"", *opts);
/* Remove any pre-existing /dev/ptmx file. */ /* Remove any pre-existing /dev/ptmx file. */
ret = remove("/dev/ptmx"); ret = remove("/dev/ptmx");
if (ret < 0) { if (ret < 0) {
if (errno != ENOENT) { if (errno != ENOENT)
SYSERROR("Failed to remove existing \"/dev/ptmx\" file"); return log_error_errno(-1, errno, "Failed to remove existing \"/dev/ptmx\" file");
return -1;
}
} else { } else {
DEBUG("Removed existing \"/dev/ptmx\" file"); DEBUG("Removed existing \"/dev/ptmx\" file");
} }
/* Create dummy /dev/ptmx file as bind mountpoint for /dev/pts/ptmx. */ /* Create dummy /dev/ptmx file as bind mountpoint for /dev/pts/ptmx. */
ret = mknod("/dev/ptmx", S_IFREG | 0000, 0); ret = mknod("/dev/ptmx", S_IFREG | 0000, 0);
if (ret < 0 && errno != EEXIST) { if (ret < 0 && errno != EEXIST)
SYSERROR("Failed to create dummy \"/dev/ptmx\" file as bind mount target"); return log_error_errno(-1, errno, "Failed to create dummy \"/dev/ptmx\" file as bind mount target");
return -1;
}
DEBUG("Created dummy \"/dev/ptmx\" file as bind mount target"); DEBUG("Created dummy \"/dev/ptmx\" file as bind mount target");
/* Fallback option: create symlink /dev/ptmx -> /dev/pts/ptmx */ /* Fallback option: create symlink /dev/ptmx -> /dev/pts/ptmx */
ret = mount("/dev/pts/ptmx", "/dev/ptmx", NULL, MS_BIND, NULL); ret = mount("/dev/pts/ptmx", "/dev/ptmx", NULL, MS_BIND, NULL);
if (!ret) { if (!ret)
DEBUG("Bind mounted \"/dev/pts/ptmx\" to \"/dev/ptmx\""); return log_debug(0, "Bind mounted \"/dev/pts/ptmx\" to \"/dev/ptmx\"");
return 0; else
} else {
/* Fallthrough and try to create a symlink. */ /* Fallthrough and try to create a symlink. */
ERROR("Failed to bind mount \"/dev/pts/ptmx\" to \"/dev/ptmx\""); ERROR("Failed to bind mount \"/dev/pts/ptmx\" to \"/dev/ptmx\"");
}
/* Remove the dummy /dev/ptmx file we created above. */ /* Remove the dummy /dev/ptmx file we created above. */
ret = remove("/dev/ptmx"); ret = remove("/dev/ptmx");
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to remove existing \"/dev/ptmx\""); return log_error_errno(-1, errno, "Failed to remove existing \"/dev/ptmx\"");
return -1;
}
/* Fallback option: Create symlink /dev/ptmx -> /dev/pts/ptmx. */ /* Fallback option: Create symlink /dev/ptmx -> /dev/pts/ptmx. */
ret = symlink("/dev/pts/ptmx", "/dev/ptmx"); ret = symlink("/dev/pts/ptmx", "/dev/ptmx");
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to create symlink from \"/dev/ptmx\" to \"/dev/pts/ptmx\""); return log_error_errno(-1, errno, "Failed to create symlink from \"/dev/ptmx\" to \"/dev/pts/ptmx\"");
return -1;
}
DEBUG("Created symlink from \"/dev/ptmx\" to \"/dev/pts/ptmx\""); DEBUG("Created symlink from \"/dev/ptmx\" to \"/dev/pts/ptmx\"");
return 0; return 0;
...@@ -1695,10 +1566,8 @@ static int setup_personality(int persona) ...@@ -1695,10 +1566,8 @@ static int setup_personality(int persona)
return 0; return 0;
ret = personality(persona); ret = personality(persona);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set personality to \"0x%x\"", persona); return log_error_errno(-1, errno, "Failed to set personality to \"0x%x\"", persona);
return -1;
}
INFO("Set personality to \"0x%x\"", persona); INFO("Set personality to \"0x%x\"", persona);
#endif #endif
...@@ -1725,35 +1594,26 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, ...@@ -1725,35 +1594,26 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
*/ */
if (file_exists(path)) { if (file_exists(path)) {
ret = lxc_unstack_mountpoint(path, false); ret = lxc_unstack_mountpoint(path, false);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to unmount \"%s\"", path); return log_error_errno(-ret, errno, "Failed to unmount \"%s\"", path);
return -ret; else
} else {
DEBUG("Cleared all (%d) mounts from \"%s\"", ret, path); DEBUG("Cleared all (%d) mounts from \"%s\"", ret, path);
}
} }
/* For unprivileged containers autodev or automounts will already have /* For unprivileged containers autodev or automounts will already have
* taken care of creating /dev/console. * taken care of creating /dev/console.
*/ */
ret = mknod(path, S_IFREG | 0000, 0); ret = mknod(path, S_IFREG | 0000, 0);
if (ret < 0 && errno != EEXIST) { if (ret < 0 && errno != EEXIST)
SYSERROR("Failed to create console"); return log_error_errno(-errno, errno, "Failed to create console");
return -errno;
}
ret = fchmod(console->slave, S_IXUSR | S_IXGRP); ret = fchmod(console->slave, S_IXUSR | S_IXGRP);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set mode \"0%o\" to \"%s\"", return log_error_errno(-errno, errno, "Failed to set mode \"0%o\" to \"%s\"", S_IXUSR | S_IXGRP, console->name);
S_IXUSR | S_IXGRP, console->name);
return -errno;
}
ret = safe_mount(console->name, path, "none", MS_BIND, 0, rootfs_path); ret = safe_mount(console->name, path, "none", MS_BIND, 0, rootfs_path);
if (ret < 0) { if (ret < 0)
ERROR("Failed to mount \"%s\" on \"%s\"", console->name, path); return log_error_errno(-1, errno, "Failed to mount \"%s\" on \"%s\"", console->name, path);
return -1;
}
DEBUG("Mounted pts device \"%s\" onto \"%s\"", console->name, path); DEBUG("Mounted pts device \"%s\" onto \"%s\"", console->name, path);
return 0; return 0;
...@@ -1776,10 +1636,8 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, ...@@ -1776,10 +1636,8 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
return -1; return -1;
ret = mkdir(path, 0755); ret = mkdir(path, 0755);
if (ret && errno != EEXIST) { if (ret && errno != EEXIST)
SYSERROR("Failed to create \"%s\"", path); return log_error_errno(-errno, errno, "Failed to create \"%s\"", path);
return -errno;
}
DEBUG("Created directory for console and tty devices at \"%s\"", path); DEBUG("Created directory for console and tty devices at \"%s\"", path);
ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console", rootfs_path, ttydir); ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console", rootfs_path, ttydir);
...@@ -1787,10 +1645,8 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, ...@@ -1787,10 +1645,8 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
return -1; return -1;
ret = mknod(lxcpath, S_IFREG | 0000, 0); ret = mknod(lxcpath, S_IFREG | 0000, 0);
if (ret < 0 && errno != EEXIST) { if (ret < 0 && errno != EEXIST)
SYSERROR("Failed to create \"%s\"", lxcpath); return log_error_errno(-errno, errno, "Failed to create \"%s\"", lxcpath);
return -errno;
}
ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs_path); ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs_path);
if (ret < 0 || (size_t)ret >= sizeof(path)) if (ret < 0 || (size_t)ret >= sizeof(path))
...@@ -1798,41 +1654,30 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, ...@@ -1798,41 +1654,30 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
if (file_exists(path)) { if (file_exists(path)) {
ret = lxc_unstack_mountpoint(path, false); ret = lxc_unstack_mountpoint(path, false);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to unmount \"%s\"", path); return log_error_errno(-ret, errno, "Failed to unmount \"%s\"", path);
return -ret; else
} else {
DEBUG("Cleared all (%d) mounts from \"%s\"", ret, path); DEBUG("Cleared all (%d) mounts from \"%s\"", ret, path);
}
} }
ret = mknod(path, S_IFREG | 0000, 0); ret = mknod(path, S_IFREG | 0000, 0);
if (ret < 0 && errno != EEXIST) { if (ret < 0 && errno != EEXIST)
SYSERROR("Failed to create console"); return log_error_errno(-errno, errno, "Failed to create console");
return -errno;
}
ret = fchmod(console->slave, S_IXUSR | S_IXGRP); ret = fchmod(console->slave, S_IXUSR | S_IXGRP);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to set mode \"0%o\" to \"%s\"", return log_error_errno(-errno, errno, "Failed to set mode \"0%o\" to \"%s\"", S_IXUSR | S_IXGRP, console->name);
S_IXUSR | S_IXGRP, console->name);
return -errno;
}
/* bind mount console->name to '/dev/<ttydir>/console' */ /* bind mount console->name to '/dev/<ttydir>/console' */
ret = safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs_path); ret = safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs_path);
if (ret < 0) { if (ret < 0)
ERROR("Failed to mount \"%s\" on \"%s\"", console->name, lxcpath); return log_error_errno(-1, errno, "Failed to mount \"%s\" on \"%s\"", console->name, lxcpath);
return -1;
}
DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath); DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath);
/* bind mount '/dev/<ttydir>/console' to '/dev/console' */ /* bind mount '/dev/<ttydir>/console' to '/dev/console' */
ret = safe_mount(lxcpath, path, "none", MS_BIND, 0, rootfs_path); ret = safe_mount(lxcpath, path, "none", MS_BIND, 0, rootfs_path);
if (ret < 0) { if (ret < 0)
ERROR("Failed to mount \"%s\" on \"%s\"", console->name, lxcpath); return log_error_errno(-1, errno, "Failed to mount \"%s\" on \"%s\"", console->name, lxcpath);
return -1;
}
DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath); DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath);
DEBUG("Console has been setup under \"%s\" and mounted to \"%s\"", lxcpath, path); DEBUG("Console has been setup under \"%s\" and mounted to \"%s\"", lxcpath, path);
...@@ -1935,10 +1780,8 @@ int parse_propagationopts(const char *mntopts, unsigned long *pflags) ...@@ -1935,10 +1780,8 @@ int parse_propagationopts(const char *mntopts, unsigned long *pflags)
return 0; return 0;
s = strdup(mntopts); s = strdup(mntopts);
if (!s) { if (!s)
SYSERROR("Failed to allocate memory"); return log_error_errno(-ENOMEM, errno, "Failed to allocate memory");
return -ENOMEM;
}
*pflags = 0L; *pflags = 0L;
lxc_iterate_parts(p, s, ",") lxc_iterate_parts(p, s, ",")
...@@ -1986,33 +1829,28 @@ static int mount_entry(const char *fsname, const char *target, ...@@ -1986,33 +1829,28 @@ static int mount_entry(const char *fsname, const char *target,
#endif #endif
if (relative) { if (relative) {
ret = snprintf(srcbuf, PATH_MAX, "%s/%s", rootfs ? rootfs : "/", fsname ? fsname : ""); ret = snprintf(srcbuf, sizeof(srcbuf), "%s/%s", rootfs ? rootfs : "/", fsname ? fsname : "");
if (ret < 0 || ret >= PATH_MAX) { if (ret < 0 || ret >= sizeof(srcbuf))
ERROR("source path is too long"); return log_error_errno(-1, errno, "source path is too long");
return -1;
}
srcpath = srcbuf; srcpath = srcbuf;
} }
ret = safe_mount(srcpath, target, fstype, mountflags & ~MS_REMOUNT, data, ret = safe_mount(srcpath, target, fstype, mountflags & ~MS_REMOUNT, data,
rootfs); rootfs);
if (ret < 0) { if (ret < 0) {
if (optional) { if (optional)
SYSINFO("Failed to mount \"%s\" on \"%s\" (optional)", return log_info_errno(0, errno, "Failed to mount \"%s\" on \"%s\" (optional)",
srcpath ? srcpath : "(null)", target); srcpath ? srcpath : "(null)", target);
return 0;
}
SYSERROR("Failed to mount \"%s\" on \"%s\"", return log_error_errno(-1, errno, "Failed to mount \"%s\" on \"%s\"",
srcpath ? srcpath : "(null)", target); srcpath ? srcpath : "(null)", target);
return -1;
} }
if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) { if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) {
unsigned long rqd_flags = 0; unsigned long rqd_flags = 0;
DEBUG("Remounting \"%s\" on \"%s\" to respect bind or remount " DEBUG("Remounting \"%s\" on \"%s\" to respect bind or remount options",
"options", srcpath ? srcpath : "(none)", target ? target : "(none)"); srcpath ? srcpath : "(none)", target ? target : "(none)");
if (mountflags & MS_RDONLY) if (mountflags & MS_RDONLY)
rqd_flags |= MS_RDONLY; rqd_flags |= MS_RDONLY;
...@@ -2032,8 +1870,8 @@ static int mount_entry(const char *fsname, const char *target, ...@@ -2032,8 +1870,8 @@ static int mount_entry(const char *fsname, const char *target,
if (sb.f_flag & MS_NOEXEC) if (sb.f_flag & MS_NOEXEC)
required_flags |= MS_NOEXEC; required_flags |= MS_NOEXEC;
DEBUG("Flags for \"%s\" were %lu, required extra flags " DEBUG("Flags for \"%s\" were %lu, required extra flags are %lu",
"are %lu", srcpath, sb.f_flag, required_flags); srcpath, sb.f_flag, required_flags);
/* If this was a bind mount request, and required_flags /* If this was a bind mount request, and required_flags
* does not have any flags which are not already in * does not have any flags which are not already in
...@@ -2042,8 +1880,7 @@ static int mount_entry(const char *fsname, const char *target, ...@@ -2042,8 +1880,7 @@ static int mount_entry(const char *fsname, const char *target,
if (!(mountflags & MS_REMOUNT)) { if (!(mountflags & MS_REMOUNT)) {
if (!(required_flags & ~mountflags) && if (!(required_flags & ~mountflags) &&
rqd_flags == 0) { rqd_flags == 0) {
DEBUG("Mountflags already were %lu, " DEBUG("Mountflags already were %lu, skipping remount", mountflags);
"skipping remount", mountflags);
goto skipremount; goto skipremount;
} }
} }
...@@ -2054,15 +1891,14 @@ static int mount_entry(const char *fsname, const char *target, ...@@ -2054,15 +1891,14 @@ static int mount_entry(const char *fsname, const char *target,
ret = mount(srcpath, target, fstype, mountflags | MS_REMOUNT, data); ret = mount(srcpath, target, fstype, mountflags | MS_REMOUNT, data);
if (ret < 0) { if (ret < 0) {
if (optional) { if (optional)
SYSINFO("Failed to mount \"%s\" on \"%s\" (optional)", return log_info_errno(0, errno, "Failed to mount \"%s\" on \"%s\" (optional)",
srcpath ? srcpath : "(null)", target); srcpath ? srcpath : "(null)",
return 0; target);
}
return log_error_errno(-1, errno, "Failed to mount \"%s\" on \"%s\"",
SYSERROR("Failed to mount \"%s\" on \"%s\"", srcpath ? srcpath : "(null)",
srcpath ? srcpath : "(null)", target); target);
return -1;
} }
} }
...@@ -2072,15 +1908,10 @@ skipremount: ...@@ -2072,15 +1908,10 @@ skipremount:
if (pflags) { if (pflags) {
ret = mount(NULL, target, NULL, pflags, NULL); ret = mount(NULL, target, NULL, pflags, NULL);
if (ret < 0) { if (ret < 0) {
if (optional) { if (optional)
SYSINFO("Failed to change mount propagation " return log_info_errno(0, errno, "Failed to change mount propagation for \"%s\" (optional)", target);
"for \"%s\" (optional)", target); else
return 0; return log_error_errno(-1, errno, "Failed to change mount propagation for \"%s\" (optional)", target);
} else {
SYSERROR("Failed to change mount propagation "
"for \"%s\" (optional)", target);
return -1;
}
} }
DEBUG("Changed mount propagation for \"%s\"", target); DEBUG("Changed mount propagation for \"%s\"", target);
} }
...@@ -2138,10 +1969,8 @@ static int mount_entry_create_dir_file(const struct mntent *mntent, ...@@ -2138,10 +1969,8 @@ static int mount_entry_create_dir_file(const struct mntent *mntent,
if (hasmntopt(mntent, "create=dir")) { if (hasmntopt(mntent, "create=dir")) {
ret = mkdir_p(path, 0755); ret = mkdir_p(path, 0755);
if (ret < 0 && errno != EEXIST) { if (ret < 0 && errno != EEXIST)
SYSERROR("Failed to create directory \"%s\"", path); return log_error_errno(-1, errno, "Failed to create directory \"%s\"", path);
return -1;
}
} }
if (!hasmntopt(mntent, "create=file")) if (!hasmntopt(mntent, "create=file"))
...@@ -2158,10 +1987,8 @@ static int mount_entry_create_dir_file(const struct mntent *mntent, ...@@ -2158,10 +1987,8 @@ static int mount_entry_create_dir_file(const struct mntent *mntent,
p2 = dirname(p1); p2 = dirname(p1);
ret = mkdir_p(p2, 0755); ret = mkdir_p(p2, 0755);
if (ret < 0 && errno != EEXIST) { if (ret < 0 && errno != EEXIST)
SYSERROR("Failed to create directory \"%s\"", path); return log_error_errno(-1, errno, "Failed to create directory \"%s\"", path);
return -1;
}
ret = mknod(path, S_IFREG | 0000, 0); ret = mknod(path, S_IFREG | 0000, 0);
if (ret < 0 && errno != EEXIST) if (ret < 0 && errno != EEXIST)
...@@ -2264,10 +2091,8 @@ static int mount_entry_on_absolute_rootfs(struct mntent *mntent, ...@@ -2264,10 +2091,8 @@ static int mount_entry_on_absolute_rootfs(struct mntent *mntent,
skipvarlib: skipvarlib:
aux = strstr(mntent->mnt_dir, rootfs->path); aux = strstr(mntent->mnt_dir, rootfs->path);
if (!aux) { if (!aux)
WARN("Ignoring mount point \"%s\"", mntent->mnt_dir); return log_warn(ret, "Ignoring mount point \"%s\"", mntent->mnt_dir);
return ret;
}
offset = strlen(rootfs->path); offset = strlen(rootfs->path);
skipabs: skipabs:
...@@ -2316,35 +2141,38 @@ static int mount_file_entries(const struct lxc_conf *conf, ...@@ -2316,35 +2141,38 @@ static int mount_file_entries(const struct lxc_conf *conf,
return -1; return -1;
} }
if (!feof(file) || ferror(file)) { if (!feof(file) || ferror(file))
ERROR("Failed to parse mount entries"); return log_error(-1, "Failed to parse mount entries");
return -1;
}
return 0; return 0;
} }
static inline void __auto_endmntent__(FILE **f)
{
if (*f)
endmntent(*f);
}
#define __do_endmntent __attribute__((__cleanup__(__auto_endmntent__)))
static int setup_mount(const struct lxc_conf *conf, static int setup_mount(const struct lxc_conf *conf,
const struct lxc_rootfs *rootfs, const char *fstab, const struct lxc_rootfs *rootfs, const char *fstab,
const char *lxc_name, const char *lxc_path) const char *lxc_name, const char *lxc_path)
{ {
FILE *f; __do_endmntent FILE *f = NULL;
int ret; int ret;
if (!fstab) if (!fstab)
return 0; return 0;
f = setmntent(fstab, "r"); f = setmntent(fstab, "re");
if (!f) { if (!f)
SYSERROR("Failed to open \"%s\"", fstab); return log_error_errno(-1, errno, "Failed to open \"%s\"", fstab);
return -1;
}
ret = mount_file_entries(conf, rootfs, f, lxc_name, lxc_path); ret = mount_file_entries(conf, rootfs, f, lxc_name, lxc_path);
if (ret < 0) if (ret < 0)
ERROR("Failed to set up mount entries"); ERROR("Failed to set up mount entries");
endmntent(f);
return ret; return ret;
} }
...@@ -2379,10 +2207,8 @@ FILE *make_anonymous_mount_file(struct lxc_list *mount, ...@@ -2379,10 +2207,8 @@ FILE *make_anonymous_mount_file(struct lxc_list *mount,
return NULL; return NULL;
fd = lxc_make_tmpfile(template, true); fd = lxc_make_tmpfile(template, true);
if (fd < 0) { if (fd < 0)
SYSERROR("Could not create temporary mount file"); return log_error_errno(NULL, errno, "Could not create temporary mount file");
return NULL;
}
TRACE("Created temporary mount file"); TRACE("Created temporary mount file");
} }
...@@ -2496,17 +2322,13 @@ static int setup_caps(struct lxc_list *caps) ...@@ -2496,17 +2322,13 @@ static int setup_caps(struct lxc_list *caps)
drop_entry = iterator->elem; drop_entry = iterator->elem;
capid = parse_cap(drop_entry); capid = parse_cap(drop_entry);
if (capid < 0) { if (capid < 0)
ERROR("unknown capability %s", drop_entry); return log_error(-1, "unknown capability %s", drop_entry);
return -1;
}
ret = prctl(PR_CAPBSET_DROP, prctl_arg(capid), prctl_arg(0), ret = prctl(PR_CAPBSET_DROP, prctl_arg(capid), prctl_arg(0),
prctl_arg(0), prctl_arg(0)); prctl_arg(0), prctl_arg(0));
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to remove %s capability", drop_entry); return log_error_errno(-1, errno, "Failed to remove %s capability", drop_entry);
return -1;
}
DEBUG("Dropped %s (%d) capability", drop_entry, capid); DEBUG("Dropped %s (%d) capability", drop_entry, capid);
} }
...@@ -2537,10 +2359,8 @@ static int dropcaps_except(struct lxc_list *caps) ...@@ -2537,10 +2359,8 @@ static int dropcaps_except(struct lxc_list *caps)
if (capid == -2) if (capid == -2)
continue; continue;
if (capid < 0) { if (capid < 0)
ERROR("Unknown capability %s", keep_entry); return log_error(-1, "Unknown capability %s", keep_entry);
return -1;
}
DEBUG("Keep capability %s (%d)", keep_entry, capid); DEBUG("Keep capability %s (%d)", keep_entry, capid);
caplist[capid] = 1; caplist[capid] = 1;
...@@ -2554,10 +2374,8 @@ static int dropcaps_except(struct lxc_list *caps) ...@@ -2554,10 +2374,8 @@ static int dropcaps_except(struct lxc_list *caps)
ret = prctl(PR_CAPBSET_DROP, prctl_arg(i), prctl_arg(0), ret = prctl(PR_CAPBSET_DROP, prctl_arg(i), prctl_arg(0),
prctl_arg(0), prctl_arg(0)); prctl_arg(0), prctl_arg(0));
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to remove capability %d", i); return log_error_errno(-1, errno, "Failed to remove capability %d", i);
return -1;
}
} }
DEBUG("Capabilities have been setup"); DEBUG("Capabilities have been setup");
...@@ -2595,21 +2413,16 @@ int setup_resource_limits(struct lxc_list *limits, pid_t pid) ...@@ -2595,21 +2413,16 @@ int setup_resource_limits(struct lxc_list *limits, pid_t pid)
lim = it->elem; lim = it->elem;
resid = parse_resource(lim->resource); resid = parse_resource(lim->resource);
if (resid < 0) { if (resid < 0)
ERROR("Unknown resource %s", lim->resource); return log_error(-1, "Unknown resource %s", lim->resource);
return -1;
}
#if HAVE_PRLIMIT || HAVE_PRLIMIT64 #if HAVE_PRLIMIT || HAVE_PRLIMIT64
if (prlimit(pid, resid, &lim->limit, NULL) != 0) { if (prlimit(pid, resid, &lim->limit, NULL) != 0)
SYSERROR("Failed to set limit %s", lim->resource); return log_error_errno(-1, errno, "Failed to set limit %s", lim->resource);
return -1;
}
TRACE("Setup \"%s\" limit", lim->resource); TRACE("Setup \"%s\" limit", lim->resource);
#else #else
ERROR("Cannot set limit \"%s\" as prlimit is missing", lim->resource); return log_error(-1, "Cannot set limit \"%s\" as prlimit is missing", lim->resource);
return -1;
#endif #endif
} }
...@@ -2627,24 +2440,18 @@ int setup_sysctl_parameters(struct lxc_list *sysctls) ...@@ -2627,24 +2440,18 @@ int setup_sysctl_parameters(struct lxc_list *sysctls)
lxc_list_for_each (it, sysctls) { lxc_list_for_each (it, sysctls) {
elem = it->elem; elem = it->elem;
tmp = lxc_string_replace(".", "/", elem->key); tmp = lxc_string_replace(".", "/", elem->key);
if (!tmp) { if (!tmp)
ERROR("Failed to replace key %s", elem->key); return log_error(-1, "Failed to replace key %s", elem->key);
return -1;
}
ret = snprintf(filename, sizeof(filename), "/proc/sys/%s", tmp); ret = snprintf(filename, sizeof(filename), "/proc/sys/%s", tmp);
if (ret < 0 || (size_t)ret >= sizeof(filename)) { if (ret < 0 || (size_t)ret >= sizeof(filename))
ERROR("Error setting up sysctl parameters path"); return log_error(-1, "Error setting up sysctl parameters path");
return -1;
}
ret = lxc_write_to_file(filename, elem->value, ret = lxc_write_to_file(filename, elem->value,
strlen(elem->value), false, 0666); strlen(elem->value), false, 0666);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to setup sysctl parameters %s to %s", return log_error_errno(-1, errno, "Failed to setup sysctl parameters %s to %s",
elem->key, elem->value); elem->key, elem->value);
return -1;
}
} }
return 0; return 0;
...@@ -2661,24 +2468,17 @@ int setup_proc_filesystem(struct lxc_list *procs, pid_t pid) ...@@ -2661,24 +2468,17 @@ int setup_proc_filesystem(struct lxc_list *procs, pid_t pid)
lxc_list_for_each (it, procs) { lxc_list_for_each (it, procs) {
elem = it->elem; elem = it->elem;
tmp = lxc_string_replace(".", "/", elem->filename); tmp = lxc_string_replace(".", "/", elem->filename);
if (!tmp) { if (!tmp)
ERROR("Failed to replace key %s", elem->filename); return log_error(-1, "Failed to replace key %s", elem->filename);
return -1;
}
ret = snprintf(filename, sizeof(filename), "/proc/%d/%s", pid, tmp); ret = snprintf(filename, sizeof(filename), "/proc/%d/%s", pid, tmp);
if (ret < 0 || (size_t)ret >= sizeof(filename)) { if (ret < 0 || (size_t)ret >= sizeof(filename))
ERROR("Error setting up proc filesystem path"); return log_error(-1, "Error setting up proc filesystem path");
return -1;
}
ret = lxc_write_to_file(filename, elem->value, ret = lxc_write_to_file(filename, elem->value,
strlen(elem->value), false, 0666); strlen(elem->value), false, 0666);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to setup proc filesystem %s to %s", return log_error_errno(-1, errno, "Failed to setup proc filesystem %s to %s", elem->filename, elem->value);
elem->filename, elem->value);
return -1;
}
} }
return 0; return 0;
...@@ -2779,18 +2579,14 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, ...@@ -2779,18 +2579,14 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
return -E2BIG; return -E2BIG;
setgroups_fd = open(path, O_WRONLY); setgroups_fd = open(path, O_WRONLY);
if (setgroups_fd < 0 && errno != ENOENT) { if (setgroups_fd < 0 && errno != ENOENT)
SYSERROR("Failed to open \"%s\"", path); return log_error_errno(-1, errno, "Failed to open \"%s\"", path);
return -1;
}
if (setgroups_fd >= 0) { if (setgroups_fd >= 0) {
ret = lxc_write_nointr(setgroups_fd, "deny\n", ret = lxc_write_nointr(setgroups_fd, "deny\n",
STRLITERALLEN("deny\n")); STRLITERALLEN("deny\n"));
if (ret != STRLITERALLEN("deny\n")) { if (ret != STRLITERALLEN("deny\n"))
SYSERROR("Failed to write \"deny\" to \"/proc/%d/setgroups\"", pid); return log_error_errno(-1, errno, "Failed to write \"deny\" to \"/proc/%d/setgroups\"", pid);
return -1;
}
TRACE("Wrote \"deny\" to \"/proc/%d/setgroups\"", pid); TRACE("Wrote \"deny\" to \"/proc/%d/setgroups\"", pid);
} }
} }
...@@ -2800,18 +2596,14 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, ...@@ -2800,18 +2596,14 @@ int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
if (ret < 0 || ret >= PATH_MAX) if (ret < 0 || ret >= PATH_MAX)
return -E2BIG; return -E2BIG;
fd = open(path, O_WRONLY); fd = open(path, O_WRONLY | O_CLOEXEC);
if (fd < 0) { if (fd < 0)
SYSERROR("Failed to open \"%s\"", path); return log_error_errno(-1, errno, "Failed to open \"%s\"", path);
return -1;
}
ret = lxc_write_nointr(fd, buf, buf_size); ret = lxc_write_nointr(fd, buf, buf_size);
if (ret != buf_size) { if (ret != buf_size)
SYSERROR("Failed to write %cid mapping to \"%s\"", return log_error_errno(-1, errno, "Failed to write %cid mapping to \"%s\"",
idtype == ID_TYPE_UID ? 'u' : 'g', path); idtype == ID_TYPE_UID ? 'u' : 'g', path);
return -1;
}
return 0; return 0;
} }
...@@ -2843,36 +2635,27 @@ static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap) ...@@ -2843,36 +2635,27 @@ static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap)
return -1; return -1;
/* Check if the binary is setuid. */ /* Check if the binary is setuid. */
if (st.st_mode & S_ISUID) { if (st.st_mode & S_ISUID)
DEBUG("The binary \"%s\" does have the setuid bit set", path); return log_debug(1, "The binary \"%s\" does have the setuid bit set", path);
return 1;
}
#if HAVE_LIBCAP && LIBCAP_SUPPORTS_FILE_CAPABILITIES #if HAVE_LIBCAP && LIBCAP_SUPPORTS_FILE_CAPABILITIES
/* Check if it has the CAP_SETUID capability. */ /* Check if it has the CAP_SETUID capability. */
if ((cap & CAP_SETUID) && if ((cap & CAP_SETUID) &&
lxc_file_cap_is_set(path, CAP_SETUID, CAP_EFFECTIVE) && lxc_file_cap_is_set(path, CAP_SETUID, CAP_EFFECTIVE) &&
lxc_file_cap_is_set(path, CAP_SETUID, CAP_PERMITTED)) { lxc_file_cap_is_set(path, CAP_SETUID, CAP_PERMITTED))
DEBUG("The binary \"%s\" has CAP_SETUID in its CAP_EFFECTIVE " return log_debug(1, "The binary \"%s\" has CAP_SETUID in its CAP_EFFECTIVE and CAP_PERMITTED sets", path);
"and CAP_PERMITTED sets", path);
return 1;
}
/* Check if it has the CAP_SETGID capability. */ /* Check if it has the CAP_SETGID capability. */
if ((cap & CAP_SETGID) && if ((cap & CAP_SETGID) &&
lxc_file_cap_is_set(path, CAP_SETGID, CAP_EFFECTIVE) && lxc_file_cap_is_set(path, CAP_SETGID, CAP_EFFECTIVE) &&
lxc_file_cap_is_set(path, CAP_SETGID, CAP_PERMITTED)) { lxc_file_cap_is_set(path, CAP_SETGID, CAP_PERMITTED))
DEBUG("The binary \"%s\" has CAP_SETGID in its CAP_EFFECTIVE " return log_debug(1, "The binary \"%s\" has CAP_SETGID in its CAP_EFFECTIVE and CAP_PERMITTED sets", path);
"and CAP_PERMITTED sets", path);
return 1;
}
#else #else
/* If we cannot check for file capabilities we need to give the benefit /* If we cannot check for file capabilities we need to give the benefit
* of the doubt. Otherwise we might fail even though all the necessary * of the doubt. Otherwise we might fail even though all the necessary
* file capabilities are set. * file capabilities are set.
*/ */
DEBUG("Cannot check for file capabilities as full capability support is " DEBUG("Cannot check for file capabilities as full capability support is missing. Manual intervention needed");
"missing. Manual intervention needed");
#endif #endif
return 1; return 1;
...@@ -2979,13 +2762,12 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) ...@@ -2979,13 +2762,12 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
use_shadow ? " " : "", map->nsid, use_shadow ? " " : "", map->nsid,
map->hostid, map->range, map->hostid, map->range,
use_shadow ? "" : "\n"); use_shadow ? "" : "\n");
if (fill <= 0 || fill >= left) { /*
/* The kernel only takes <= 4k for writes to * The kernel only takes <= 4k for writes to
* /proc/<pid>/{g,u}id_map * /proc/<pid>/{g,u}id_map
*/ */
SYSERROR("Too many %cid mappings defined", u_or_g); if (fill <= 0 || fill >= left)
return -1; return log_error_errno(-1, errno, "Too many %cid mappings defined", u_or_g);
}
pos += fill; pos += fill;
} }
...@@ -2999,18 +2781,13 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) ...@@ -2999,18 +2781,13 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
ret = run_command(cmd_output, sizeof(cmd_output), ret = run_command(cmd_output, sizeof(cmd_output),
lxc_map_ids_exec_wrapper, lxc_map_ids_exec_wrapper,
(void *)mapbuf); (void *)mapbuf);
if (ret < 0) { if (ret < 0)
ERROR("new%cidmap failed to write mapping \"%s\": %s", return log_error(-1, "new%cidmap failed to write mapping \"%s\": %s", u_or_g, cmd_output, mapbuf);
u_or_g, cmd_output, mapbuf);
return -1;
}
TRACE("new%cidmap wrote mapping \"%s\"", u_or_g, mapbuf); TRACE("new%cidmap wrote mapping \"%s\"", u_or_g, mapbuf);
} else { } else {
ret = write_id_mapping(type, pid, mapbuf, pos - mapbuf); ret = write_id_mapping(type, pid, mapbuf, pos - mapbuf);
if (ret < 0) { if (ret < 0)
ERROR("Failed to write mapping: %s", mapbuf); return log_error(-1, "Failed to write mapping: %s", mapbuf);
return -1;
}
TRACE("Wrote mapping \"%s\"", mapbuf); TRACE("Wrote mapping \"%s\"", mapbuf);
} }
...@@ -3127,38 +2904,28 @@ int chown_mapped_root(const char *path, struct lxc_conf *conf) ...@@ -3127,38 +2904,28 @@ int chown_mapped_root(const char *path, struct lxc_conf *conf)
hostuid = geteuid(); hostuid = geteuid();
hostgid = getegid(); hostgid = getegid();
if (!get_mapped_rootid(conf, ID_TYPE_UID, &val)) { if (!get_mapped_rootid(conf, ID_TYPE_UID, &val))
ERROR("No uid mapping for container root"); return log_error(-1, "No uid mapping for container root");
return -1;
}
rootuid = (uid_t)val; rootuid = (uid_t)val;
if (!get_mapped_rootid(conf, ID_TYPE_GID, &val)) { if (!get_mapped_rootid(conf, ID_TYPE_GID, &val))
ERROR("No gid mapping for container root"); return log_error(-1, "No gid mapping for container root");
return -1;
}
rootgid = (gid_t)val; rootgid = (gid_t)val;
if (hostuid == 0) { if (hostuid == 0) {
if (chown(path, rootuid, rootgid) < 0) { if (chown(path, rootuid, rootgid) < 0)
ERROR("Error chowning %s", path); return log_error(-1, "Error chowning %s", path);
return -1;
}
return 0; return 0;
} }
if (rootuid == hostuid) { /* nothing to do */
/* nothing to do */ if (rootuid == hostuid)
INFO("Container root is our uid; no need to chown"); return log_info(0, "Container root is our uid; no need to chown");
return 0;
}
/* save the current gid of "path" */ /* save the current gid of "path" */
if (stat(path, &sb) < 0) { if (stat(path, &sb) < 0)
ERROR("Error stat %s", path); return log_error(-1, "Error stat %s", path);
return -1;
}
/* Update the path argument in case this was overlayfs. */ /* Update the path argument in case this was overlayfs. */
args1[sizeof(args1) / sizeof(args1[0]) - 2] = path; args1[sizeof(args1) / sizeof(args1[0]) - 2] = path;
...@@ -3171,53 +2938,39 @@ int chown_mapped_root(const char *path, struct lxc_conf *conf) ...@@ -3171,53 +2938,39 @@ int chown_mapped_root(const char *path, struct lxc_conf *conf)
DEBUG("trying to chown \"%s\" to %d", path, hostgid); DEBUG("trying to chown \"%s\" to %d", path, hostgid);
if (sb.st_uid == hostuid && if (sb.st_uid == hostuid &&
mapped_hostid(sb.st_gid, conf, ID_TYPE_GID) < 0 && mapped_hostid(sb.st_gid, conf, ID_TYPE_GID) < 0 &&
chown(path, -1, hostgid) < 0) { chown(path, -1, hostgid) < 0)
ERROR("Failed chgrping %s", path); return log_error(-1, "Failed chgrping %s", path);
return -1;
}
/* "u:0:rootuid:1" */ /* "u:0:rootuid:1" */
ret = snprintf(map1, 100, "u:0:%d:1", rootuid); ret = snprintf(map1, 100, "u:0:%d:1", rootuid);
if (ret < 0 || ret >= 100) { if (ret < 0 || ret >= 100)
ERROR("Error uid printing map string"); return log_error(-1, "Error uid printing map string");
return -1;
}
/* "u:hostuid:hostuid:1" */ /* "u:hostuid:hostuid:1" */
ret = snprintf(map2, 100, "u:%d:%d:1", hostuid, hostuid); ret = snprintf(map2, 100, "u:%d:%d:1", hostuid, hostuid);
if (ret < 0 || ret >= 100) { if (ret < 0 || ret >= 100)
ERROR("Error uid printing map string"); return log_error(-1, "Error uid printing map string");
return -1;
}
/* "g:0:rootgid:1" */ /* "g:0:rootgid:1" */
ret = snprintf(map3, 100, "g:0:%d:1", rootgid); ret = snprintf(map3, 100, "g:0:%d:1", rootgid);
if (ret < 0 || ret >= 100) { if (ret < 0 || ret >= 100)
ERROR("Error gid printing map string"); return log_error(-1, "Error gid printing map string");
return -1;
}
/* "g:pathgid:rootgid+pathgid:1" */ /* "g:pathgid:rootgid+pathgid:1" */
ret = snprintf(map4, 100, "g:%d:%d:1", (gid_t)sb.st_gid, ret = snprintf(map4, 100, "g:%d:%d:1", (gid_t)sb.st_gid,
rootgid + (gid_t)sb.st_gid); rootgid + (gid_t)sb.st_gid);
if (ret < 0 || ret >= 100) { if (ret < 0 || ret >= 100)
ERROR("Error gid printing map string"); return log_error(-1, "Error gid printing map string");
return -1;
}
/* "g:hostgid:hostgid:1" */ /* "g:hostgid:hostgid:1" */
ret = snprintf(map5, 100, "g:%d:%d:1", hostgid, hostgid); ret = snprintf(map5, 100, "g:%d:%d:1", hostgid, hostgid);
if (ret < 0 || ret >= 100) { if (ret < 0 || ret >= 100)
ERROR("Error gid printing map string"); return log_error(-1, "Error gid printing map string");
return -1;
}
/* "0:pathgid" (chown) */ /* "0:pathgid" (chown) */
ret = snprintf(ugid, 100, "0:%d", (gid_t)sb.st_gid); ret = snprintf(ugid, 100, "0:%d", (gid_t)sb.st_gid);
if (ret < 0 || ret >= 100) { if (ret < 0 || ret >= 100)
ERROR("Error owner printing format string for chown"); return log_error(-1, "Error owner printing format string for chown");
return -1;
}
if (hostgid == sb.st_gid) if (hostgid == sb.st_gid)
ret = run_command(cmd_output, sizeof(cmd_output), ret = run_command(cmd_output, sizeof(cmd_output),
...@@ -3371,10 +3124,8 @@ static int lxc_execute_bind_init(struct lxc_handler *handler) ...@@ -3371,10 +3124,8 @@ static int lxc_execute_bind_init(struct lxc_handler *handler)
if (ret < 0 || ret >= PATH_MAX) if (ret < 0 || ret >= PATH_MAX)
return -1; return -1;
if (!file_exists(path)) { if (!file_exists(path))
ERROR("The file \"%s\" does not exist on host", path); return log_error_errno(-1, errno, "The file \"%s\" does not exist on host", path);
return -1;
}
ret = snprintf(destpath, PATH_MAX, "%s" P_tmpdir "%s", conf->rootfs.mount, "/.lxc-init"); ret = snprintf(destpath, PATH_MAX, "%s" P_tmpdir "%s", conf->rootfs.mount, "/.lxc-init");
if (ret < 0 || ret >= PATH_MAX) if (ret < 0 || ret >= PATH_MAX)
...@@ -3382,17 +3133,13 @@ static int lxc_execute_bind_init(struct lxc_handler *handler) ...@@ -3382,17 +3133,13 @@ static int lxc_execute_bind_init(struct lxc_handler *handler)
if (!file_exists(destpath)) { if (!file_exists(destpath)) {
ret = mknod(destpath, S_IFREG | 0000, 0); ret = mknod(destpath, S_IFREG | 0000, 0);
if (ret < 0 && errno != EEXIST) { if (ret < 0 && errno != EEXIST)
SYSERROR("Failed to create dummy \"%s\" file as bind mount target", destpath); return log_error_errno(-1, errno, "Failed to create dummy \"%s\" file as bind mount target", destpath);
return -1;
}
} }
ret = safe_mount(path, destpath, "none", MS_BIND, NULL, conf->rootfs.mount); ret = safe_mount(path, destpath, "none", MS_BIND, NULL, conf->rootfs.mount);
if (ret < 0) { if (ret < 0)
SYSERROR("Failed to bind mount lxc.init.static into container"); return log_error_errno(-1, errno, "Failed to bind mount lxc.init.static into container");
return -1;
}
p = strdup(destpath + strlen(conf->rootfs.mount)); p = strdup(destpath + strlen(conf->rootfs.mount));
if (!p) if (!p)
...@@ -3420,28 +3167,21 @@ int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name, ...@@ -3420,28 +3167,21 @@ int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name,
* give us a mount in our own ns so we can pivot_root to it * give us a mount in our own ns so we can pivot_root to it
*/ */
ret = mount(path, path, "rootfs", MS_BIND, NULL); ret = mount(path, path, "rootfs", MS_BIND, NULL);
if (ret < 0) { if (ret < 0)
ERROR("Failed to bind mount container / onto itself"); return log_error(-1, "Failed to bind mount container / onto itself");
return -1;
}
TRACE("Bind mounted container / onto itself"); return log_trace(0, "Bind mounted container / onto itself");
return 0;
} }
remount_all_slave(); remount_all_slave();
ret = run_lxc_hooks(name, "pre-mount", conf, NULL); ret = run_lxc_hooks(name, "pre-mount", conf, NULL);
if (ret < 0) { if (ret < 0)
ERROR("Failed to run pre-mount hooks"); return log_error(-1, "Failed to run pre-mount hooks");
return -1;
}
ret = lxc_mount_rootfs(conf); ret = lxc_mount_rootfs(conf);
if (ret < 0) { if (ret < 0)
ERROR("Failed to setup rootfs for"); return log_error(-1, "Failed to setup rootfs for");
return -1;
}
conf->rootfs_setup = true; conf->rootfs_setup = true;
return 0; return 0;
...@@ -3463,11 +3203,8 @@ static bool verify_start_hooks(struct lxc_conf *conf) ...@@ -3463,11 +3203,8 @@ static bool verify_start_hooks(struct lxc_conf *conf)
return false; return false;
ret = access(path, X_OK); ret = access(path, X_OK);
if (ret < 0) { if (ret < 0)
SYSERROR("Start hook \"%s\" not found in container", return log_error_errno(false, errno, "Start hook \"%s\" not found in container", hookname);
hookname);
return false;
}
return true; return true;
} }
...@@ -3542,17 +3279,13 @@ int lxc_setup(struct lxc_handler *handler) ...@@ -3542,17 +3279,13 @@ int lxc_setup(struct lxc_handler *handler)
char *keyring_context = NULL; char *keyring_context = NULL;
ret = lxc_setup_rootfs_prepare_root(lxc_conf, name, lxcpath); ret = lxc_setup_rootfs_prepare_root(lxc_conf, name, lxcpath);
if (ret < 0) { if (ret < 0)
ERROR("Failed to setup rootfs"); return log_error(-1, "Failed to setup rootfs");
return -1;
}
if (handler->nsfd[LXC_NS_UTS] == -EBADF) { if (handler->nsfd[LXC_NS_UTS] == -EBADF) {
ret = setup_utsname(lxc_conf->utsname); ret = setup_utsname(lxc_conf->utsname);
if (ret < 0) { if (ret < 0)
ERROR("Failed to setup the utsname %s", name); return log_error(-1, "Failed to setup the utsname %s", name);
return -1;
}
} }
if (!lxc_conf->keyring_disable_session) { if (!lxc_conf->keyring_disable_session) {
...@@ -3570,48 +3303,36 @@ int lxc_setup(struct lxc_handler *handler) ...@@ -3570,48 +3303,36 @@ int lxc_setup(struct lxc_handler *handler)
if (handler->ns_clone_flags & CLONE_NEWNET) { if (handler->ns_clone_flags & CLONE_NEWNET) {
ret = lxc_setup_network_in_child_namespaces(lxc_conf, ret = lxc_setup_network_in_child_namespaces(lxc_conf,
&lxc_conf->network); &lxc_conf->network);
if (ret < 0) { if (ret < 0)
ERROR("Failed to setup network"); return log_error(-1, "Failed to setup network");
return -1;
}
ret = lxc_network_send_name_and_ifindex_to_parent(handler); ret = lxc_network_send_name_and_ifindex_to_parent(handler);
if (ret < 0) { if (ret < 0)
ERROR("Failed to send network device names and ifindices to parent"); return log_error(-1, "Failed to send network device names and ifindices to parent");
return -1;
}
} }
if (lxc_conf->autodev > 0) { if (lxc_conf->autodev > 0) {
ret = mount_autodev(name, &lxc_conf->rootfs, lxc_conf->autodevtmpfssize, lxcpath); ret = mount_autodev(name, &lxc_conf->rootfs, lxc_conf->autodevtmpfssize, lxcpath);
if (ret < 0) { if (ret < 0)
ERROR("Failed to mount \"/dev\""); return log_error(-1, "Failed to mount \"/dev\"");
return -1;
}
} }
/* Do automatic mounts (mainly /proc and /sys), but exclude those that /* Do automatic mounts (mainly /proc and /sys), but exclude those that
* need to wait until other stuff has finished. * need to wait until other stuff has finished.
*/ */
ret = lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & ~LXC_AUTO_CGROUP_MASK, handler); ret = lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & ~LXC_AUTO_CGROUP_MASK, handler);
if (ret < 0) { if (ret < 0)
ERROR("Failed to setup first automatic mounts"); return log_error(-1, "Failed to setup first automatic mounts");
return -1;
}
ret = setup_mount(lxc_conf, &lxc_conf->rootfs, lxc_conf->fstab, name, lxcpath); ret = setup_mount(lxc_conf, &lxc_conf->rootfs, lxc_conf->fstab, name, lxcpath);
if (ret < 0) { if (ret < 0)
ERROR("Failed to setup mounts"); return log_error(-1, "Failed to setup mounts");
return -1;
}
if (!lxc_list_empty(&lxc_conf->mount_list)) { if (!lxc_list_empty(&lxc_conf->mount_list)) {
ret = setup_mount_entries(lxc_conf, &lxc_conf->rootfs, ret = setup_mount_entries(lxc_conf, &lxc_conf->rootfs,
&lxc_conf->mount_list, name, lxcpath); &lxc_conf->mount_list, name, lxcpath);
if (ret < 0) { if (ret < 0)
ERROR("Failed to setup mount entries"); return log_error(-1, "Failed to setup mount entries");
return -1;
}
} }
if (lxc_conf->is_execute) { if (lxc_conf->is_execute) {
...@@ -3620,25 +3341,19 @@ int lxc_setup(struct lxc_handler *handler) ...@@ -3620,25 +3341,19 @@ int lxc_setup(struct lxc_handler *handler)
char path[PATH_MAX]; char path[PATH_MAX];
ret = snprintf(path, PATH_MAX, SBINDIR "/init.lxc.static"); ret = snprintf(path, PATH_MAX, SBINDIR "/init.lxc.static");
if (ret < 0 || ret >= PATH_MAX) { if (ret < 0 || ret >= PATH_MAX)
ERROR("Path to init.lxc.static too long"); return log_error(-1, "Path to init.lxc.static too long");
return -1;
}
fd = open(path, O_PATH | O_CLOEXEC); fd = open(path, O_PATH | O_CLOEXEC);
if (fd < 0) { if (fd < 0)
SYSERROR("Unable to open lxc.init.static"); return log_error_errno(-1, errno, "Unable to open lxc.init.static");
return -1;
}
((struct execute_args *)handler->data)->init_fd = fd; ((struct execute_args *)handler->data)->init_fd = fd;
((struct execute_args *)handler->data)->init_path = NULL; ((struct execute_args *)handler->data)->init_path = NULL;
} else { } else {
ret = lxc_execute_bind_init(handler); ret = lxc_execute_bind_init(handler);
if (ret < 0) { if (ret < 0)
ERROR("Failed to bind-mount the lxc init system"); return log_error(-1, "Failed to bind-mount the lxc init system");
return -1;
}
} }
} }
...@@ -3647,81 +3362,59 @@ int lxc_setup(struct lxc_handler *handler) ...@@ -3647,81 +3362,59 @@ int lxc_setup(struct lxc_handler *handler)
* automatically or via fstab entries. * automatically or via fstab entries.
*/ */
ret = lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & LXC_AUTO_CGROUP_MASK, handler); ret = lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & LXC_AUTO_CGROUP_MASK, handler);
if (ret < 0) { if (ret < 0)
ERROR("Failed to setup remaining automatic mounts"); return log_error(-1, "Failed to setup remaining automatic mounts");
return -1;
}
ret = run_lxc_hooks(name, "mount", lxc_conf, NULL); ret = run_lxc_hooks(name, "mount", lxc_conf, NULL);
if (ret < 0) { if (ret < 0)
ERROR("Failed to run mount hooks"); return log_error(-1, "Failed to run mount hooks");
return -1;
}
if (lxc_conf->autodev > 0) { if (lxc_conf->autodev > 0) {
ret = run_lxc_hooks(name, "autodev", lxc_conf, NULL); ret = run_lxc_hooks(name, "autodev", lxc_conf, NULL);
if (ret < 0) { if (ret < 0)
ERROR("Failed to run autodev hooks"); return log_error(-1, "Failed to run autodev hooks");
return -1;
}
ret = lxc_fill_autodev(&lxc_conf->rootfs); ret = lxc_fill_autodev(&lxc_conf->rootfs);
if (ret < 0) { if (ret < 0)
ERROR("Failed to populate \"/dev\""); return log_error(-1, "Failed to populate \"/dev\"");
return -1;
}
} }
/* Make sure any start hooks are in the container */ /* Make sure any start hooks are in the container */
if (!verify_start_hooks(lxc_conf)) { if (!verify_start_hooks(lxc_conf))
ERROR("Failed to verify start hooks"); return log_error(-1, "Failed to verify start hooks");
return -1;
}
ret = lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console, ret = lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console,
lxc_conf->ttys.dir); lxc_conf->ttys.dir);
if (ret < 0) { if (ret < 0)
ERROR("Failed to setup console"); return log_error(-1, "Failed to setup console");
return -1;
}
ret = lxc_setup_dev_symlinks(&lxc_conf->rootfs); ret = lxc_setup_dev_symlinks(&lxc_conf->rootfs);
if (ret < 0) { if (ret < 0)
ERROR("Failed to setup \"/dev\" symlinks"); return log_error(-1, "Failed to setup \"/dev\" symlinks");
return -1;
}
ret = lxc_create_tmp_proc_mount(lxc_conf); ret = lxc_create_tmp_proc_mount(lxc_conf);
if (ret < 0) { if (ret < 0)
ERROR("Failed to \"/proc\" LSMs"); return log_error(-1, "Failed to \"/proc\" LSMs");
return -1;
}
ret = lxc_setup_rootfs_switch_root(&lxc_conf->rootfs); ret = lxc_setup_rootfs_switch_root(&lxc_conf->rootfs);
if (ret < 0) { if (ret < 0)
ERROR("Failed to pivot root into rootfs"); return log_error(-1, "Failed to pivot root into rootfs");
return -1;
}
/* Setting the boot-id is best-effort for now. */ /* Setting the boot-id is best-effort for now. */
if (lxc_conf->autodev > 0) if (lxc_conf->autodev > 0)
(void)lxc_setup_boot_id(); (void)lxc_setup_boot_id();
ret = lxc_setup_devpts(lxc_conf); ret = lxc_setup_devpts(lxc_conf);
if (ret < 0) { if (ret < 0)
ERROR("Failed to setup new devpts instance"); return log_error(-1, "Failed to setup new devpts instance");
return -1;
}
ret = lxc_create_ttys(handler); ret = lxc_create_ttys(handler);
if (ret < 0) if (ret < 0)
return -1; return -1;
ret = setup_personality(lxc_conf->personality); ret = setup_personality(lxc_conf->personality);
if (ret < 0) { if (ret < 0)
ERROR("Failed to set personality"); return log_error(-1, "Failed to set personality");
return -1;
}
/* Set sysctl value to a path under /proc/sys as determined from the /* Set sysctl value to a path under /proc/sys as determined from the
* key. For e.g. net.ipv4.ip_forward translated to * key. For e.g. net.ipv4.ip_forward translated to
...@@ -3729,27 +3422,18 @@ int lxc_setup(struct lxc_handler *handler) ...@@ -3729,27 +3422,18 @@ int lxc_setup(struct lxc_handler *handler)
*/ */
if (!lxc_list_empty(&lxc_conf->sysctls)) { if (!lxc_list_empty(&lxc_conf->sysctls)) {
ret = setup_sysctl_parameters(&lxc_conf->sysctls); ret = setup_sysctl_parameters(&lxc_conf->sysctls);
if (ret < 0) { if (ret < 0)
ERROR("Failed to setup sysctl parameters"); return log_error(-1, "Failed to setup sysctl parameters");
return -1;
}
} }
if (!lxc_list_empty(&lxc_conf->keepcaps)) { if (!lxc_list_empty(&lxc_conf->keepcaps)) {
if (!lxc_list_empty(&lxc_conf->caps)) { if (!lxc_list_empty(&lxc_conf->caps))
ERROR("Container requests lxc.cap.drop and " return log_error(-1, "Container requests lxc.cap.drop and lxc.cap.keep: either use lxc.cap.drop or lxc.cap.keep, not both");
"lxc.cap.keep: either use lxc.cap.drop or "
"lxc.cap.keep, not both");
return -1;
}
if (dropcaps_except(&lxc_conf->keepcaps)) { if (dropcaps_except(&lxc_conf->keepcaps))
ERROR("Failed to keep capabilities"); return log_error(-1, "Failed to keep capabilities");
return -1;
}
} else if (setup_caps(&lxc_conf->caps)) { } else if (setup_caps(&lxc_conf->caps)) {
ERROR("Failed to drop capabilities"); return log_error(-1, "Failed to drop capabilities");
return -1;
} }
NOTICE("The container \"%s\" is set up", name); NOTICE("The container \"%s\" is set up", name);
...@@ -4053,10 +3737,8 @@ int lxc_clear_hooks(struct lxc_conf *c, const char *key) ...@@ -4053,10 +3737,8 @@ int lxc_clear_hooks(struct lxc_conf *c, const char *key)
} }
} }
if (!done) { if (!done)
ERROR("Invalid hook key: %s", key); return log_error(-1, "Invalid hook key: %s", key);
return -1;
}
return 0; return 0;
} }
...@@ -4229,8 +3911,9 @@ static struct id_map *find_mapped_hostid_entry(struct lxc_conf *conf, ...@@ -4229,8 +3911,9 @@ static struct id_map *find_mapped_hostid_entry(struct lxc_conf *conf,
static struct id_map *mapped_hostid_add(struct lxc_conf *conf, uid_t id, static struct id_map *mapped_hostid_add(struct lxc_conf *conf, uid_t id,
enum idtype type) enum idtype type)
{ {
__do_free struct id_map *entry = NULL;
int hostid_mapped; int hostid_mapped;
struct id_map *entry = NULL, *tmp = NULL; struct id_map *tmp = NULL;
entry = malloc(sizeof(*entry)); entry = malloc(sizeof(*entry));
if (!entry) if (!entry)
...@@ -4243,18 +3926,15 @@ static struct id_map *mapped_hostid_add(struct lxc_conf *conf, uid_t id, ...@@ -4243,18 +3926,15 @@ static struct id_map *mapped_hostid_add(struct lxc_conf *conf, uid_t id,
/* Find new mapping. */ /* Find new mapping. */
hostid_mapped = find_unmapped_nsid(conf, type); hostid_mapped = find_unmapped_nsid(conf, type);
if (hostid_mapped < 0) { if (hostid_mapped < 0)
DEBUG("Failed to find free mapping for id %d", id); return log_debug(NULL, "Failed to find free mapping for id %d", id);
free(entry);
return NULL;
}
entry->idtype = type; entry->idtype = type;
entry->nsid = hostid_mapped; entry->nsid = hostid_mapped;
entry->hostid = (unsigned long)id; entry->hostid = (unsigned long)id;
entry->range = 1; entry->range = 1;
return entry; return move_ptr(entry);
} }
struct lxc_list *get_minimal_idmap(struct lxc_conf *conf) struct lxc_list *get_minimal_idmap(struct lxc_conf *conf)
...@@ -4270,20 +3950,16 @@ struct lxc_list *get_minimal_idmap(struct lxc_conf *conf) ...@@ -4270,20 +3950,16 @@ struct lxc_list *get_minimal_idmap(struct lxc_conf *conf)
/* Find container root mappings. */ /* Find container root mappings. */
container_root_uid = mapped_nsid_add(conf, nsuid, ID_TYPE_UID); container_root_uid = mapped_nsid_add(conf, nsuid, ID_TYPE_UID);
if (!container_root_uid) { if (!container_root_uid)
DEBUG("Failed to find mapping for namespace uid %d", 0); return log_debug(NULL, "Failed to find mapping for namespace uid %d", 0);
return NULL;
}
euid = geteuid(); euid = geteuid();
if (euid >= container_root_uid->hostid && if (euid >= container_root_uid->hostid &&
euid < (container_root_uid->hostid + container_root_uid->range)) euid < (container_root_uid->hostid + container_root_uid->range))
host_uid_map = container_root_uid; host_uid_map = container_root_uid;
container_root_gid = mapped_nsid_add(conf, nsgid, ID_TYPE_GID); container_root_gid = mapped_nsid_add(conf, nsgid, ID_TYPE_GID);
if (!container_root_gid) { if (!container_root_gid)
DEBUG("Failed to find mapping for namespace gid %d", 0); return log_debug(NULL, "Failed to find mapping for namespace gid %d", 0);
return NULL;
}
egid = getegid(); egid = getegid();
if (egid >= container_root_gid->hostid && if (egid >= container_root_gid->hostid &&
egid < (container_root_gid->hostid + container_root_gid->range)) egid < (container_root_gid->hostid + container_root_gid->range))
...@@ -4292,17 +3968,13 @@ struct lxc_list *get_minimal_idmap(struct lxc_conf *conf) ...@@ -4292,17 +3968,13 @@ struct lxc_list *get_minimal_idmap(struct lxc_conf *conf)
/* Check whether the {g,u}id of the user has a mapping. */ /* Check whether the {g,u}id of the user has a mapping. */
if (!host_uid_map) if (!host_uid_map)
host_uid_map = mapped_hostid_add(conf, euid, ID_TYPE_UID); host_uid_map = mapped_hostid_add(conf, euid, ID_TYPE_UID);
if (!host_uid_map) { if (!host_uid_map)
DEBUG("Failed to find mapping for uid %d", euid); return log_debug(NULL, "Failed to find mapping for uid %d", euid);
return NULL;
}
if (!host_gid_map) if (!host_gid_map)
host_gid_map = mapped_hostid_add(conf, egid, ID_TYPE_GID); host_gid_map = mapped_hostid_add(conf, egid, ID_TYPE_GID);
if (!host_gid_map) { if (!host_gid_map)
DEBUG("Failed to find mapping for gid %d", egid); return log_debug(NULL, "Failed to find mapping for gid %d", egid);
return NULL;
}
/* Allocate new {g,u}id map list. */ /* Allocate new {g,u}id map list. */
idmap = malloc(sizeof(*idmap)); idmap = malloc(sizeof(*idmap));
...@@ -4656,8 +4328,7 @@ static char *getuname(void) ...@@ -4656,8 +4328,7 @@ static char *getuname(void)
if (ret == 0) if (ret == 0)
WARN("Could not find matched password record."); WARN("Could not find matched password record.");
ERROR("Failed to get password record - %u", geteuid()); return log_error(NULL, "Failed to get password record - %u", geteuid());
return NULL;
} }
return strdup(pwent.pw_name); return strdup(pwent.pw_name);
...@@ -4685,8 +4356,7 @@ static char *getgname(void) ...@@ -4685,8 +4356,7 @@ static char *getgname(void)
if (ret == 0) if (ret == 0)
WARN("Could not find matched group record"); WARN("Could not find matched group record");
ERROR("Failed to get group record - %u", getegid()); return log_error(NULL, "Failed to get group record - %u", getegid());
return NULL;
} }
return strdup(grent.gr_name); return strdup(grent.gr_name);
...@@ -4802,9 +4472,9 @@ static void free_cgroup_settings(struct lxc_list *result) ...@@ -4802,9 +4472,9 @@ static void free_cgroup_settings(struct lxc_list *result)
lxc_list_for_each_safe (iterator, result, next) { lxc_list_for_each_safe (iterator, result, next) {
lxc_list_del(iterator); lxc_list_del(iterator);
free(iterator); free_disarm(iterator);
} }
free(result); free_disarm(result);
} }
/* Return the list of cgroup_settings sorted according to the following rules /* Return the list of cgroup_settings sorted according to the following rules
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <dirent.h> #include <dirent.h>
#include <errno.h> #include <errno.h>
#include <mntent.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/types.h> #include <sys/types.h>
...@@ -12,11 +13,35 @@ ...@@ -12,11 +13,35 @@
#include "macro.h" #include "macro.h"
#define define_cleanup_attribute(type, func) \
static inline void func##_ptr(type *ptr) \
{ \
if (*ptr) \
func(*ptr); \
}
#define free_disarm(ptr) \
({ \
free(ptr); \
move_ptr(ptr); \
})
static inline void __auto_free__(void *p) static inline void __auto_free__(void *p)
{ {
free(*(void **)p); free(*(void **)p);
} }
static inline void free_string_list(char **list)
{
if (list) {
for (int i = 0; list[i]; i++)
free(list[i]);
free_disarm(list);
}
}
define_cleanup_attribute(char **, free_string_list);
#define __do_free_string_list __attribute__((__cleanup__(free_string_list_ptr)))
static inline void __auto_fclose__(FILE **f) static inline void __auto_fclose__(FILE **f)
{ {
if (*f) if (*f)
...@@ -37,12 +62,6 @@ static inline void __auto_closedir__(DIR **d) ...@@ -37,12 +62,6 @@ static inline void __auto_closedir__(DIR **d)
fd = -EBADF; \ fd = -EBADF; \
} }
#define free_disarm(ptr) \
({ \
free(ptr); \
move_ptr(ptr); \
})
static inline void __auto_close__(int *fd) static inline void __auto_close__(int *fd)
{ {
close_prot_errno_disarm(*fd); close_prot_errno_disarm(*fd);
......
...@@ -77,7 +77,6 @@ static inline void clear_bit(unsigned bit, uint32_t *bitarr) ...@@ -77,7 +77,6 @@ static inline void clear_bit(unsigned bit, uint32_t *bitarr)
bitarr[bit / NBITS] &= ~(1 << (bit % NBITS)); bitarr[bit / NBITS] &= ~(1 << (bit % NBITS));
} }
static char *copy_to_eol(char *s); static char *copy_to_eol(char *s);
static void free_string_list(char **list);
static char *get_mountpoint(char *line); static char *get_mountpoint(char *line);
static bool get_uid_gid(const char *user, uid_t *uid, gid_t *gid); static bool get_uid_gid(const char *user, uid_t *uid, gid_t *gid);
static int handle_login(const char *user, uid_t uid, gid_t gid); static int handle_login(const char *user, uid_t uid, gid_t gid);
...@@ -454,16 +453,6 @@ static size_t string_list_length(char **list) ...@@ -454,16 +453,6 @@ static size_t string_list_length(char **list)
return len; return len;
} }
/* Free null-terminated array of strings. */
static void free_string_list(char **list)
{
char **it;
for (it = list; it && *it; it++)
free(*it);
free(list);
}
/* Write single integer to file. */ /* Write single integer to file. */
static bool write_int(char *path, int v) static bool write_int(char *path, int v)
{ {
......
...@@ -73,6 +73,13 @@ extern struct lxc_popen_FILE *lxc_popen(const char *command); ...@@ -73,6 +73,13 @@ extern struct lxc_popen_FILE *lxc_popen(const char *command);
*/ */
extern int lxc_pclose(struct lxc_popen_FILE *fp); extern int lxc_pclose(struct lxc_popen_FILE *fp);
static inline void __auto_lxc_pclose__(struct lxc_popen_FILE **f)
{
if (*f)
lxc_pclose(*f);
}
#define __do_lxc_pclose __attribute__((__cleanup__(__auto_lxc_pclose__)))
/* /*
* wait on a child we forked * wait on a child we forked
*/ */
......
...@@ -35,8 +35,8 @@ struct thread_args { ...@@ -35,8 +35,8 @@ struct thread_args {
int thread_id; int thread_id;
bool success; bool success;
pid_t init_pid; pid_t init_pid;
char *inherited_ipc_ns; char inherited_ipc_ns[4096];
char *inherited_net_ns; char inherited_net_ns[4096];
}; };
void *ns_sharing_wrapper(void *data) void *ns_sharing_wrapper(void *data)
...@@ -45,8 +45,8 @@ void *ns_sharing_wrapper(void *data) ...@@ -45,8 +45,8 @@ void *ns_sharing_wrapper(void *data)
ssize_t ret; ssize_t ret;
char name[100]; char name[100];
char owning_ns_init_pid[100]; char owning_ns_init_pid[100];
char proc_ns_path[4096]; char proc_ns_path[256];
char ns_buf[4096]; char ns_buf[256];
struct lxc_container *c; struct lxc_container *c;
struct thread_args *args = data; struct thread_args *args = data;
...@@ -162,15 +162,11 @@ void *ns_sharing_wrapper(void *data) ...@@ -162,15 +162,11 @@ void *ns_sharing_wrapper(void *data)
args->success = true; args->success = true;
out: out:
if (c->is_running(c) && !c->stop(c)) { if (c->is_running(c) && !c->stop(c))
lxc_error("Failed to stop container \"%s\"\n", name); lxc_error("Failed to stop container \"%s\"\n", name);
goto out;
}
if (!c->destroy(c)) { if (!c->destroy(c))
lxc_error("Failed to destroy container \"%s\"\n", name); lxc_error("Failed to destroy container \"%s\"\n", name);
goto out;
}
pthread_exit(NULL); pthread_exit(NULL);
return NULL; return NULL;
...@@ -178,16 +174,19 @@ out: ...@@ -178,16 +174,19 @@ out:
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct thread_args *args = NULL;
size_t nthreads = 10;
int i, init_pid, j; int i, init_pid, j;
char proc_ns_path[4096]; char proc_ns_path[4096];
char ipc_ns_buf[4096]; char ipc_ns_buf[4096];
char net_ns_buf[4096]; char net_ns_buf[4096];
pthread_attr_t attr; pthread_attr_t attr;
pthread_t threads[10]; pthread_t threads[10];
struct thread_args args[10];
struct lxc_container *c; struct lxc_container *c;
int ret = EXIT_FAILURE; int ret = EXIT_FAILURE;
pthread_attr_init(&attr);
c = lxc_container_new("owning-ns", NULL); c = lxc_container_new("owning-ns", NULL);
if (!c) { if (!c) {
lxc_error("%s", "Failed to create container \"owning-ns\""); lxc_error("%s", "Failed to create container \"owning-ns\"");
...@@ -263,24 +262,28 @@ int main(int argc, char *argv[]) ...@@ -263,24 +262,28 @@ int main(int argc, char *argv[])
sleep(5); sleep(5);
pthread_attr_init(&attr); args = malloc(sizeof(struct thread_args) * nthreads);
if (!args) {
lxc_error("%s\n", "Failed to allocate memory");
goto on_error_stop;
}
for (j = 0; j < 10; j++) { for (j = 0; j < 10; j++) {
lxc_debug("Starting namespace sharing test iteration %d\n", j); lxc_debug("Starting namespace sharing test iteration %d\n", j);
for (i = 0; i < 10; i++) { for (i = 0; i < nthreads; i++) {
args[i].thread_id = i; args[i].thread_id = i;
args[i].success = false; args[i].success = false;
args[i].init_pid = init_pid; args[i].init_pid = init_pid;
args[i].inherited_ipc_ns = ipc_ns_buf; memcpy(args[i].inherited_ipc_ns, ipc_ns_buf, sizeof(args[i].inherited_ipc_ns));
args[i].inherited_net_ns = net_ns_buf; memcpy(args[i].inherited_net_ns, net_ns_buf, sizeof(args[i].inherited_net_ns));
ret = pthread_create(&threads[i], &attr, ns_sharing_wrapper, (void *) &args[i]); ret = pthread_create(&threads[i], &attr, ns_sharing_wrapper, (void *)&args[i]);
if (ret != 0) if (ret != 0)
goto on_error_stop; goto on_error_stop;
} }
for (i = 0; i < 10; i++) { for (i = 0; i < nthreads; i++) {
ret = pthread_join(threads[i], NULL); ret = pthread_join(threads[i], NULL);
if (ret != 0) if (ret != 0)
goto on_error_stop; goto on_error_stop;
...@@ -295,6 +298,9 @@ int main(int argc, char *argv[]) ...@@ -295,6 +298,9 @@ int main(int argc, char *argv[])
ret = EXIT_SUCCESS; ret = EXIT_SUCCESS;
on_error_stop: on_error_stop:
free(args);
pthread_attr_destroy(&attr);
if (c->is_running(c) && !c->stop(c)) if (c->is_running(c) && !c->stop(c))
lxc_error("%s\n", "Failed to stop container \"owning-ns\""); lxc_error("%s\n", "Failed to stop container \"owning-ns\"");
...@@ -305,5 +311,6 @@ on_error_put: ...@@ -305,5 +311,6 @@ on_error_put:
lxc_container_put(c); lxc_container_put(c);
if (ret == EXIT_SUCCESS) if (ret == EXIT_SUCCESS)
lxc_debug("%s\n", "All state namespace sharing tests passed"); lxc_debug("%s\n", "All state namespace sharing tests passed");
exit(ret); exit(ret);
} }
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