Unverified Commit 4d8a34c3 by Stéphane Graber Committed by GitHub

Merge pull request #2862 from brauner/2019-02-17/save_rexec

cleanup macros and rexec fixes
parents 7a8959d5 8f350e63
......@@ -363,6 +363,7 @@ init_lxc_SOURCES = cmd/lxc_init.c \
compiler.h \
error.h \
initutils.c initutils.h \
memory_utils.h \
parse.c parse.h \
raw_syscalls.c raw_syscalls.h \
string_utils.c string_utils.h
......@@ -384,10 +385,11 @@ lxc_user_nic_SOURCES = cmd/lxc_user_nic.c \
syscall_wrappers.h
lxc_usernsexec_SOURCES = cmd/lxc_usernsexec.c \
conf.c conf.h \
file_utils.c file_utils.h \
list.h \
log.c log.h \
macro.h \
file_utils.c file_utils.h \
memory_utils.h \
string_utils.c string_utils.h \
syscall_wrappers.h \
utils.c utils.h
......@@ -411,6 +413,7 @@ init_lxc_static_SOURCES = cmd/lxc_init.c \
file_utils.c file_utils.h \
log.c log.h \
macro.h \
memory_utils.h \
namespace.c namespace.h \
string_utils.c string_utils.h
......
......@@ -37,6 +37,7 @@
#include "config.h"
#include "log.h"
#include "memory_utils.h"
#include "raw_syscalls.h"
#include "utils.h"
......@@ -155,12 +156,11 @@ int lxc_abstract_unix_connect(const char *path)
int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds,
void *data, size_t size)
{
int ret;
__do_free char *cmsgbuf;
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg = NULL;
char buf[1] = {0};
char *cmsgbuf;
size_t cmsgbufsize = CMSG_SPACE(num_sendfds * sizeof(int));
memset(&msg, 0, sizeof(msg));
......@@ -189,20 +189,18 @@ int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds,
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
free(cmsgbuf);
return ret;
return sendmsg(fd, &msg, MSG_NOSIGNAL);
}
int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
void *data, size_t size)
{
__do_free char *cmsgbuf;
int ret;
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg = NULL;
char buf[1] = {0};
char *cmsgbuf;
size_t cmsgbufsize = CMSG_SPACE(num_recvfds * sizeof(int));
memset(&msg, 0, sizeof(msg));
......@@ -234,7 +232,6 @@ int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
memcpy(recvfds, CMSG_DATA(cmsg), num_recvfds * sizeof(int));
out:
free(cmsgbuf);
return ret;
}
......
......@@ -59,6 +59,7 @@
#include "lxcseccomp.h"
#include "macro.h"
#include "mainloop.h"
#include "memory_utils.h"
#include "namespace.h"
#include "raw_syscalls.h"
#include "syscall_wrappers.h"
......@@ -76,31 +77,28 @@ static lxc_attach_options_t attach_static_default_options = LXC_ATTACH_OPTIONS_D
static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
{
__do_free char *line = NULL;
__do_fclose FILE *proc_file = NULL;
int ret;
bool found;
FILE *proc_file;
char proc_fn[LXC_PROC_STATUS_LEN];
struct lxc_proc_context_info *info;
size_t line_bufsz = 0;
char *line = NULL;
struct lxc_proc_context_info *info = NULL;
/* Read capabilities. */
ret = snprintf(proc_fn, LXC_PROC_STATUS_LEN, "/proc/%d/status", pid);
if (ret < 0 || ret >= LXC_PROC_STATUS_LEN)
goto on_error;
return NULL;
proc_file = fopen(proc_fn, "r");
if (!proc_file) {
SYSERROR("Could not open %s", proc_fn);
goto on_error;
SYSERROR("Failed to open %s", proc_fn);
return NULL;
}
info = calloc(1, sizeof(*info));
if (!info) {
SYSERROR("Could not allocate memory");
fclose(proc_file);
if (!info)
return NULL;
}
found = false;
......@@ -112,13 +110,10 @@ static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
}
}
free(line);
fclose(proc_file);
if (!found) {
ERROR("Could not read capability bounding set from %s",
proc_fn);
goto on_error;
ERROR("Could not read capability bounding set from %s", proc_fn);
free(info);
return NULL;
}
info->lsm_label = lsm_process_label_get(pid);
......@@ -126,10 +121,6 @@ static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
memset(info->ns_fd, -1, sizeof(int) * LXC_NS_MAX);
return info;
on_error:
free(info);
return NULL;
}
static inline void lxc_proc_close_ns_fd(struct lxc_proc_context_info *ctx)
......@@ -440,13 +431,14 @@ static int lxc_attach_set_environment(struct lxc_proc_context_info *init_ctx,
static char *lxc_attach_getpwshell(uid_t uid)
{
__do_free char *line = NULL;
__do_fclose FILE *pipe_f = NULL;
int fd, ret;
pid_t pid;
int pipes[2];
FILE *pipe_f;
bool found = false;
size_t line_bufsz = 0;
char *line = NULL, *result = NULL;
char *result = NULL;
/* We need to fork off a process that runs the getent program, and we
* need to capture its output, so we use a pipe for that purpose.
......@@ -567,9 +559,6 @@ static char *lxc_attach_getpwshell(uid_t uid)
found = true;
}
free(line);
fclose(pipe_f);
ret = wait_for_pid(pid);
if (ret < 0) {
free(result);
......@@ -586,10 +575,10 @@ static char *lxc_attach_getpwshell(uid_t uid)
static void lxc_attach_get_init_uidgid(uid_t *init_uid, gid_t *init_gid)
{
FILE *proc_file;
__do_free char *line = NULL;
__do_fclose FILE *proc_file = NULL;
char proc_fn[LXC_PROC_STATUS_LEN];
int ret;
char *line = NULL;
size_t line_bufsz = 0;
long value = -1;
uid_t uid = (uid_t)-1;
......@@ -620,9 +609,6 @@ static void lxc_attach_get_init_uidgid(uid_t *init_uid, gid_t *init_gid)
break;
}
fclose(proc_file);
free(line);
/* Only override arguments if we found something. */
if (uid != (uid_t)-1)
*init_uid = uid;
......@@ -637,9 +623,9 @@ static void lxc_attach_get_init_uidgid(uid_t *init_uid, gid_t *init_gid)
static bool fetch_seccomp(struct lxc_container *c, lxc_attach_options_t *options)
{
__do_free char *path = NULL;
int ret;
bool bret;
char *path;
if (!(options->namespaces & CLONE_NEWNS) ||
!(options->attach_flags & LXC_ATTACH_LSM)) {
......@@ -667,7 +653,6 @@ static bool fetch_seccomp(struct lxc_container *c, lxc_attach_options_t *options
/* Copy the value into the new lxc_conf. */
bret = c->set_config_item(c, "lxc.seccomp.profile", path);
free(path);
if (!bret)
return false;
......@@ -684,8 +669,7 @@ static bool fetch_seccomp(struct lxc_container *c, lxc_attach_options_t *options
static bool no_new_privs(struct lxc_container *c, lxc_attach_options_t *options)
{
bool bret;
char *val;
__do_free char *val = NULL;
/* Remove current setting. */
if (!c->set_config_item(c, "lxc.no_new_privs", "")) {
......@@ -701,24 +685,18 @@ static bool no_new_privs(struct lxc_container *c, lxc_attach_options_t *options)
}
/* Set currently active setting. */
bret = c->set_config_item(c, "lxc.no_new_privs", val);
free(val);
return bret;
return c->set_config_item(c, "lxc.no_new_privs", val);
}
static signed long get_personality(const char *name, const char *lxcpath)
{
char *p;
signed long ret;
__do_free char *p;
p = lxc_cmd_get_config_item(name, "lxc.arch", lxcpath);
if (!p)
return -1;
ret = lxc_config_parse_arch(p);
free(p);
return ret;
return lxc_config_parse_arch(p);
}
struct attach_clone_payload {
......@@ -1547,11 +1525,11 @@ int lxc_attach_run_command(void *payload)
int lxc_attach_run_shell(void* payload)
{
__do_free char *buf = NULL;
uid_t uid;
struct passwd pwent;
struct passwd *pwentp = NULL;
char *user_shell;
char *buf;
size_t bufsize;
int ret;
......@@ -1598,6 +1576,5 @@ int lxc_attach_run_shell(void* payload)
if (!pwentp)
free(user_shell);
free(buf);
return -1;
}
......@@ -33,6 +33,7 @@
#include "cgroup_utils.h"
#include "config.h"
#include "macro.h"
#include "memory_utils.h"
#include "utils.h"
int get_cgroup_version(char *line)
......@@ -65,12 +66,8 @@ bool is_cgroupfs_v2(char *line)
bool test_writeable_v1(char *mountpoint, char *path)
{
char *fullpath = must_make_path(mountpoint, path, NULL);
int ret;
ret = access(fullpath, W_OK);
free(fullpath);
return ret == 0;
__do_free char *fullpath = must_make_path(mountpoint, path, NULL);
return (access(fullpath, W_OK) == 0);
}
bool test_writeable_v2(char *mountpoint, char *path)
......@@ -81,39 +78,26 @@ bool test_writeable_v2(char *mountpoint, char *path)
* file.
*/
int ret;
char *cgroup_path, *cgroup_procs_file, *cgroup_threads_file;
__do_free char *cgroup_path = NULL, *cgroup_procs_file = NULL,
*cgroup_threads_file = NULL;
cgroup_path = must_make_path(mountpoint, path, NULL);
cgroup_procs_file = must_make_path(cgroup_path, "cgroup.procs", NULL);
ret = access(cgroup_path, W_OK);
if (ret < 0) {
free(cgroup_path);
free(cgroup_procs_file);
if (ret < 0)
return false;
}
ret = access(cgroup_procs_file, W_OK);
free(cgroup_procs_file);
if (ret < 0) {
free(cgroup_path);
if (ret < 0)
return false;
}
/* Newer versions of cgroup2 now also require write access to the
* "cgroup.threads" file.
*/
cgroup_threads_file = must_make_path(cgroup_path, "cgroup.threads", NULL);
free(cgroup_path);
if (!file_exists(cgroup_threads_file)) {
free(cgroup_threads_file);
if (!file_exists(cgroup_threads_file))
return true;
}
ret = access(cgroup_threads_file, W_OK);
free(cgroup_threads_file);
if (ret < 0)
return false;
return ret == 0;
return (access(cgroup_threads_file, W_OK) == 0);
}
......@@ -47,6 +47,7 @@
#include "config.h"
#include "error.h"
#include "initutils.h"
#include "memory_utils.h"
#include "parse.h"
#include "raw_syscalls.h"
#include "string_utils.h"
......@@ -100,10 +101,10 @@ static struct arguments my_args = {
static void prevent_forking(void)
{
FILE *f;
size_t len = 0;
char *line = NULL;
__do_free char *line = NULL;
__do_fclose FILE *f = NULL;
char path[PATH_MAX];
size_t len = 0;
f = fopen("/proc/self/cgroup", "r");
if (!f)
......@@ -138,14 +139,14 @@ static void prevent_forking(void)
if (ret < 0 || (size_t)ret >= sizeof(path)) {
if (my_args.quiet)
fprintf(stderr, "Failed to create string\n");
goto on_error;
return;
}
fd = open(path, O_WRONLY);
if (fd < 0) {
if (my_args.quiet)
fprintf(stderr, "Failed to open \"%s\"\n", path);
goto on_error;
return;
}
ret = write(fd, "1", 1);
......@@ -153,17 +154,13 @@ static void prevent_forking(void)
fprintf(stderr, "Failed to write to \"%s\"\n", path);
close(fd);
break;
return;
}
on_error:
free(line);
fclose(f);
}
static void kill_children(pid_t pid)
{
FILE *f;
__do_fclose FILE *f = NULL;
char path[PATH_MAX];
int ret;
......@@ -187,15 +184,12 @@ static void kill_children(pid_t pid)
if (fscanf(f, "%d ", &find_pid) != 1) {
if (my_args.quiet)
fprintf(stderr, "Failed to retrieve pid\n");
fclose(f);
return;
}
(void)kill_children(find_pid);
(void)kill(find_pid, SIGKILL);
}
fclose(f);
}
static void remove_self(void)
......
......@@ -111,10 +111,9 @@ static int open_and_lock(char *path)
static char *get_username(void)
{
__do_free char *buf = NULL;
struct passwd pwent;
struct passwd *pwentp = NULL;
char *buf;
char *username;
size_t bufsize;
int ret;
......@@ -132,14 +131,10 @@ static char *get_username(void)
usernic_error("%s", "Could not find matched password record\n");
CMD_SYSERROR("Failed to get username: %u\n", getuid());
free(buf);
return NULL;
}
username = strdup(pwent.pw_name);
free(buf);
return username;
return strdup(pwent.pw_name);
}
static void free_groupnames(char **groupnames)
......@@ -157,13 +152,13 @@ static void free_groupnames(char **groupnames)
static char **get_groupnames(void)
{
__do_free char *buf = NULL;
__do_free gid_t *group_ids = NULL;
int ngroups;
gid_t *group_ids;
int ret, i;
char **groupnames;
struct group grent;
struct group *grentp = NULL;
char *buf;
size_t bufsize;
ngroups = getgroups(0, NULL);
......@@ -182,14 +177,12 @@ static char **get_groupnames(void)
ret = getgroups(ngroups, group_ids);
if (ret < 0) {
free(group_ids);
CMD_SYSERROR("Failed to get process groups\n");
return NULL;
}
groupnames = malloc(sizeof(char *) * (ngroups + 1));
if (!groupnames) {
free(group_ids);
CMD_SYSERROR("Failed to allocate memory while getting group names\n");
return NULL;
}
......@@ -202,7 +195,6 @@ static char **get_groupnames(void)
buf = malloc(bufsize);
if (!buf) {
free(group_ids);
free_groupnames(groupnames);
CMD_SYSERROR("Failed to allocate memory while getting group names\n");
return NULL;
......@@ -215,8 +207,6 @@ static char **get_groupnames(void)
usernic_error("%s", "Could not find matched group record\n");
CMD_SYSERROR("Failed to get group name: %u\n", group_ids[i]);
free(buf);
free(group_ids);
free_groupnames(groupnames);
return NULL;
}
......@@ -224,16 +214,11 @@ static char **get_groupnames(void)
groupnames[i] = strdup(grent.gr_name);
if (!groupnames[i]) {
usernic_error("Failed to copy group name \"%s\"", grent.gr_name);
free(buf);
free(group_ids);
free_groupnames(groupnames);
return NULL;
}
}
free(buf);
free(group_ids);
return groupnames;
}
......@@ -321,13 +306,13 @@ static void free_alloted(struct alloted_s **head)
static int get_alloted(char *me, char *intype, char *link,
struct alloted_s **alloted)
{
__do_free char *line = NULL;
__do_fclose FILE *fin = NULL;
int n, ret;
char name[100], type[100], br[100];
char **groups;
FILE *fin;
int count = 0;
size_t len = 0;
char *line = NULL;
fin = fopen(LXC_USERNIC_CONF, "r");
if (!fin) {
......@@ -378,8 +363,6 @@ static int get_alloted(char *me, char *intype, char *link,
}
free_groupnames(groups);
fclose(fin);
free(line);
/* Now return the total number of nics that this user can create. */
return count;
......@@ -610,12 +593,12 @@ struct entry_line {
static bool cull_entries(int fd, char *name, char *net_type, char *net_link,
char *net_dev, bool *found_nicname)
{
__do_free struct entry_line *entry_lines = NULL;
int i, ret;
char *buf, *buf_end, *buf_start;
struct stat sb;
int n = 0;
bool found, keep;
struct entry_line *entry_lines = NULL;
ret = fstat(fd, &sb);
if (ret < 0) {
......@@ -641,7 +624,6 @@ static bool cull_entries(int fd, char *name, char *net_type, char *net_link,
newe = realloc(entry_lines, sizeof(*entry_lines) * (n + 1));
if (!newe) {
free(entry_lines);
lxc_strmunmap(buf, sb.st_size);
return false;
}
......@@ -672,8 +654,6 @@ static bool cull_entries(int fd, char *name, char *net_type, char *net_link,
buf_start++;
}
free(entry_lines);
ret = ftruncate(fd, buf_start - buf);
lxc_strmunmap(buf, sb.st_size);
if (ret < 0)
......@@ -706,9 +686,10 @@ static int count_entries(char *buf, off_t len, char *name, char *net_type, char
static char *get_nic_if_avail(int fd, struct alloted_s *names, int pid,
char *intype, char *br, int allowed, char **cnic)
{
__do_free char *newline = NULL;
int ret;
size_t slen;
char *newline, *owner;
char *owner;
char nicname[IFNAMSIZ];
struct stat sb;
struct alloted_s *n;
......@@ -795,7 +776,6 @@ static char *get_nic_if_avail(int fd, struct alloted_s *names, int pid,
slen = strlen(owner) + strlen(intype) + strlen(br) + strlen(nicname) + 4;
newline = malloc(slen + 1);
if (!newline) {
free(newline);
CMD_SYSERROR("Failed allocate memory\n");
return NULL;
}
......@@ -805,7 +785,6 @@ static char *get_nic_if_avail(int fd, struct alloted_s *names, int pid,
if (lxc_netdev_delete_by_name(nicname) != 0)
usernic_error("Error unlinking %s\n", nicname);
free(newline);
return NULL;
}
......@@ -824,7 +803,6 @@ static char *get_nic_if_avail(int fd, struct alloted_s *names, int pid,
if (lxc_netdev_delete_by_name(nicname) != 0)
usernic_error("Error unlinking %s\n", nicname);
free(newline);
return NULL;
}
......@@ -832,7 +810,6 @@ static char *get_nic_if_avail(int fd, struct alloted_s *names, int pid,
* \0 byte! Files are not \0-terminated!
*/
memmove(buf + sb.st_size, newline, slen);
free(newline);
lxc_strmunmap(buf, sb.st_size + slen);
return strdup(nicname);
......@@ -1115,11 +1092,11 @@ do_partial_cleanup:
int main(int argc, char *argv[])
{
__do_free char *me = NULL, *newname = NULL, *nicname = NULL;
int fd, n, pid, request, ret;
char *me, *newname;
struct user_nic_args args;
int container_veth_ifidx = -1, host_veth_ifidx = -1, netns_fd = -1;
char *cnic = NULL, *nicname = NULL;
char *cnic = NULL;
struct alloted_s *alloted = NULL;
if (argc < 7 || argc > 8) {
......@@ -1248,7 +1225,6 @@ int main(int argc, char *argv[])
}
n = get_alloted(me, args.type, args.link, &alloted);
free(me);
if (request == LXC_USERNIC_DELETE) {
struct alloted_s *it;
......@@ -1313,14 +1289,11 @@ int main(int argc, char *argv[])
if (ret < 0)
usernic_error("Failed to delete \"%s\"\n", cnic);
free(nicname);
_exit(EXIT_FAILURE);
}
host_veth_ifidx = if_nametoindex(nicname);
if (!host_veth_ifidx) {
free(newname);
free(nicname);
CMD_SYSERROR("Failed to get netdev index\n");
_exit(EXIT_FAILURE);
}
......@@ -1330,8 +1303,6 @@ int main(int argc, char *argv[])
*/
fprintf(stdout, "%s:%d:%s:%d\n", newname, container_veth_ifidx, nicname,
host_veth_ifidx);
free(newname);
free(nicname);
fflush(stdout);
_exit(EXIT_SUCCESS);
......
......@@ -47,6 +47,7 @@
#include "list.h"
#include "log.h"
#include "macro.h"
#include "memory_utils.h"
#include "file_utils.h"
#include "string_utils.h"
#include "syscall_wrappers.h"
......@@ -198,13 +199,13 @@ static int parse_map(char *map)
*/
static int read_default_map(char *fnam, int which, char *user)
{
__do_free char *line = NULL;
__do_fclose FILE *fin = NULL;
size_t len;
char *p1, *p2;
unsigned long ul1, ul2;
FILE *fin;
int ret = -1;
size_t sz = 0;
char *line = NULL;
struct lxc_list *tmp = NULL;
struct id_map *newmap = NULL;
......@@ -259,16 +260,13 @@ static int read_default_map(char *fnam, int which, char *user)
break;
}
fclose(fin);
free(line);
return ret;
}
static int find_default_map(void)
{
__do_free char *buf = NULL;
size_t bufsize;
char *buf;
struct passwd pwent;
int ret = -1;
struct passwd *pwentp = NULL;
......@@ -287,24 +285,18 @@ static int find_default_map(void)
CMD_SYSERROR("Failed to find matched password record");
CMD_SYSERROR("Failed to get password record for uid %d", getuid());
ret = -1;
goto out;
return -1;
}
ret = read_default_map(subuidfile, ID_TYPE_UID, pwent.pw_name);
if (ret < 0)
goto out;
return -1;
ret = read_default_map(subgidfile, ID_TYPE_GID, pwent.pw_name);
if (ret < 0)
goto out;
ret = 0;
out:
free(buf);
return -1;
return ret;
return 0;
}
int main(int argc, char *argv[])
......
......@@ -232,7 +232,7 @@ static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
const char *lxcpath, const char *hashed_sock_name)
{
int client_fd, saved_errno;
__do_close_prot_errno int client_fd = -EBADF;
ssize_t ret = -1;
client_fd = lxc_cmd_connect(name, lxcpath, hashed_sock_name, "command");
......@@ -242,25 +242,18 @@ static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
ret = lxc_abstract_unix_send_credential(client_fd, &cmd->req,
sizeof(cmd->req));
if (ret < 0 || (size_t)ret != sizeof(cmd->req))
goto on_error;
return -1;
if (cmd->req.datalen <= 0)
return client_fd;
return steal_fd(client_fd);
errno = EMSGSIZE;
ret = lxc_send_nointr(client_fd, (void *)cmd->req.data,
cmd->req.datalen, MSG_NOSIGNAL);
if (ret < 0 || ret != (ssize_t)cmd->req.datalen)
goto on_error;
return client_fd;
on_error:
saved_errno = errno;
close(client_fd);
errno = saved_errno;
return -1;
return -1;
return steal_fd(client_fd);
}
/*
......@@ -285,7 +278,7 @@ on_error:
static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
const char *lxcpath, const char *hashed_sock_name)
{
int client_fd, saved_errno;
__do_close_prot_errno int client_fd = -EBADF;
int ret = -1;
bool stay_connected = false;
......@@ -310,15 +303,8 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
if (ret < 0 && errno == ECONNRESET)
*stopped = 1;
if (!stay_connected || ret <= 0) {
saved_errno = errno;
close(client_fd);
errno = saved_errno;
return ret;
}
if (stay_connected)
cmd->rsp.ret = client_fd;
if (stay_connected && ret > 0)
cmd->rsp.ret = steal_fd(client_fd);
return ret;
}
......@@ -698,8 +684,8 @@ static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
*/
int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
{
__do_free struct lxc_cmd_console_rsp_data *rspdata = NULL;
int ret, stopped;
struct lxc_cmd_console_rsp_data *rspdata;
struct lxc_cmd_rr cmd = {
.req = { .cmd = LXC_CMD_CONSOLE, .data = INT_TO_PTR(*ttynum) },
};
......@@ -708,23 +694,21 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
if (ret < 0)
return ret;
rspdata = cmd.rsp.data;
if (cmd.rsp.ret < 0) {
errno = -cmd.rsp.ret;
SYSERROR("Denied access to tty");
ret = -1;
goto out;
return -1;
}
if (ret == 0) {
ERROR("tty number %d invalid, busy or all ttys busy", *ttynum);
ret = -1;
goto out;
return -1;
}
rspdata = cmd.rsp.data;
if (rspdata->masterfd < 0) {
ERROR("Unable to allocate fd for tty %d", rspdata->ttynum);
goto out;
return -1;
}
ret = cmd.rsp.ret; /* socket fd */
......@@ -732,8 +716,6 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
*ttynum = rspdata->ttynum;
INFO("Alloced fd %d for tty %d via socket %d", *fd, rspdata->ttynum, ret);
out:
free(cmd.rsp.data);
return ret;
}
......@@ -846,6 +828,7 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
lxc_state_t states[MAX_STATE],
int *state_client_fd)
{
__do_close_prot_errno int clientfd = -EBADF;
int state, stopped;
ssize_t ret;
struct lxc_cmd_rr cmd = {
......@@ -870,8 +853,9 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
/* We should now be guaranteed to get an answer from the state sending
* function.
*/
if (cmd.rsp.ret < 0) {
errno = -cmd.rsp.ret;
clientfd = cmd.rsp.ret;
if (clientfd < 0) {
errno = -clientfd;
SYSERROR("Failed to receive socket fd");
return -1;
}
......@@ -879,12 +863,11 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
state = PTR_TO_INT(cmd.rsp.data);
if (state < MAX_STATE) {
TRACE("Container is already in requested state %s", lxc_state2str(state));
close(cmd.rsp.ret);
return state;
}
*state_client_fd = cmd.rsp.ret;
TRACE("Added state client %d to state client list", cmd.rsp.ret);
*state_client_fd = steal_fd(clientfd);
TRACE("Added state client %d to state client list", *state_client_fd);
return MAX_STATE;
}
......@@ -1074,7 +1057,6 @@ static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler *handler,
struct lxc_epoll_descr *descr,
const lxc_cmd_t cmd)
{
struct lxc_state_client *client;
struct lxc_list *cur, *next;
lxc_terminal_free(handler->conf, fd);
......@@ -1085,7 +1067,8 @@ static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler *handler,
}
lxc_list_for_each_safe(cur, &handler->conf->state_clients, next) {
client = cur->elem;
struct lxc_state_client *client = cur->elem;
if (client->clientfd != fd)
continue;
......@@ -1174,7 +1157,7 @@ out_close:
static int lxc_cmd_accept(int fd, uint32_t events, void *data,
struct lxc_epoll_descr *descr)
{
int connection;
__do_close_prot_errno int connection = -EBADF;
int opt = 1, ret = -1;
connection = accept(fd, NULL, 0);
......@@ -1186,38 +1169,34 @@ static int lxc_cmd_accept(int fd, uint32_t events, void *data,
ret = fcntl(connection, F_SETFD, FD_CLOEXEC);
if (ret < 0) {
SYSERROR("Failed to set close-on-exec on incoming command connection");
goto out_close;
return ret;
}
ret = setsockopt(connection, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt));
if (ret < 0) {
SYSERROR("Failed to enable necessary credentials on command socket");
goto out_close;
return ret;
}
ret = lxc_mainloop_add_handler(descr, connection, lxc_cmd_handler, data);
if (ret) {
ERROR("Failed to add command handler");
goto out_close;
return ret;
}
out:
steal_fd(connection);
return ret;
out_close:
close(connection);
goto out;
}
int lxc_cmd_init(const char *name, const char *lxcpath, const char *suffix)
{
int fd, ret;
__do_close_prot_errno int fd = -EBADF;
int ret;
char path[LXC_AUDS_ADDR_LEN] = {0};
ret = lxc_make_abstract_socket_name(path, sizeof(path), name, lxcpath, NULL, suffix);
if (ret < 0)
return -1;
TRACE("Creating abstract unix socket \"%s\"", &path[1]);
fd = lxc_abstract_unix_open(path, SOCK_STREAM, 0);
if (fd < 0) {
......@@ -1231,24 +1210,25 @@ int lxc_cmd_init(const char *name, const char *lxcpath, const char *suffix)
ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
if (ret < 0) {
SYSERROR("Failed to set FD_CLOEXEC on command socket file descriptor");
close(fd);
return -1;
}
return fd;
TRACE("Created abstract unix socket \"%s\"", &path[1]);
return steal_fd(fd);
}
int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
struct lxc_handler *handler)
{
__do_close_prot_errno int fd = handler->conf->maincmd_fd;
int ret;
int fd = handler->conf->maincmd_fd;
ret = lxc_mainloop_add_handler(descr, fd, lxc_cmd_accept, handler);
if (ret < 0) {
ERROR("Failed to add handler for command socket");
close(fd);
return ret;
}
steal_fd(fd);
return ret;
}
......@@ -222,7 +222,7 @@ int lxc_make_tmpfile(char *template, bool rm)
mode_t msk;
msk = umask(0022);
fd = mkstemp(template);
fd = mkostemp(template, O_CLOEXEC);
umask(msk);
if (fd < 0)
return -1;
......@@ -366,3 +366,33 @@ on_error:
return NULL;
}
int fd_to_fd(int from, int to)
{
for (;;) {
uint8_t buf[PATH_MAX];
uint8_t *p = buf;
ssize_t bytes_to_write;
ssize_t bytes_read;
bytes_read = lxc_read_nointr(from, buf, sizeof buf);
if (bytes_read < 0)
return -1;
if (bytes_read == 0)
break;
bytes_to_write = (size_t)bytes_read;
do {
ssize_t bytes_written;
bytes_written = lxc_write_nointr(to, p, bytes_to_write);
if (bytes_written < 0)
return -1;
bytes_to_write -= bytes_written;
p += bytes_written;
} while (bytes_to_write > 0);
}
return 0;
}
......@@ -57,5 +57,6 @@ extern FILE *fopen_cloexec(const char *path, const char *mode);
extern ssize_t lxc_sendfile_nointr(int out_fd, int in_fd, off_t *offset,
size_t count);
extern char *file_to_buf(char *path, size_t *length);
extern int fd_to_fd(int from, int to);
#endif /* __LXC_FILE_UTILS_H */
......@@ -400,4 +400,11 @@ enum {
_ptr_; \
})
#define steal_fd(fd) \
({ \
int _fd_ = (fd); \
(fd) = -EBADF; \
_fd_; \
})
#endif /* __LXC_MACRO_H */
......@@ -26,6 +26,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include "macro.h"
static inline void __auto_free__(void *p)
{
......@@ -44,6 +47,20 @@ static inline void __auto_closedir__(DIR **d)
closedir(*d);
}
#define close_prot_errno_disarm(fd) \
if (fd >= 0) { \
int _e_ = errno; \
close(fd); \
errno = _e_; \
fd = -EBADF; \
}
static inline void __auto_close__(int *fd)
{
close_prot_errno_disarm(*fd);
}
#define __do_close_prot_errno __attribute__((__cleanup__(__auto_close__)))
#define __do_free __attribute__((__cleanup__(__auto_free__)))
#define __do_fclose __attribute__((__cleanup__(__auto_fclose__)))
#define __do_closedir __attribute__((__cleanup__(__auto_closedir__)))
......
......@@ -83,53 +83,98 @@ static int parse_argv(char ***argv)
static int is_memfd(void)
{
int fd, saved_errno, seals;
__do_close_prot_errno int fd = -EBADF;
int seals;
fd = open("/proc/self/exe", O_RDONLY | O_CLOEXEC);
if (fd < 0)
return -ENOTRECOVERABLE;
seals = fcntl(fd, F_GET_SEALS);
saved_errno = errno;
close(fd);
errno = saved_errno;
if (seals < 0)
if (seals < 0) {
struct stat s = {0};
if (fstat(fd, &s) == 0) {
fprintf(stderr, "AAAAA: %ld\n", (long)s.st_nlink);
return (s.st_nlink == 0);
}
return -EINVAL;
}
return seals == LXC_MEMFD_REXEC_SEALS;
}
static void lxc_rexec_as_memfd(char **argv, char **envp, const char *memfd_name)
{
int saved_errno;
ssize_t bytes_sent;
int fd = -1, memfd = -1;
__do_close_prot_errno int fd = -EBADF, memfd = -EBADF, tmpfd = -EBADF;
int ret;
memfd = memfd_create(memfd_name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
if (memfd < 0)
return;
if (memfd < 0) {
char template[PATH_MAX];
ret = snprintf(template, sizeof(template),
P_tmpdir "/.%s_XXXXXX", memfd_name);
if (ret < 0 || (size_t)ret >= sizeof(template))
return;
tmpfd = lxc_make_tmpfile(template, true);
if (tmpfd < 0)
return;
ret = fchmod(tmpfd, 0700);
if (ret)
return;
}
fd = open("/proc/self/exe", O_RDONLY | O_CLOEXEC);
if (fd < 0)
goto on_error;
return;
/* sendfile() handles up to 2GB. */
bytes_sent = lxc_sendfile_nointr(memfd, fd, NULL, LXC_SENDFILE_MAX);
saved_errno = errno;
close(fd);
errno = saved_errno;
if (bytes_sent < 0)
goto on_error;
if (fcntl(memfd, F_ADD_SEALS, LXC_MEMFD_REXEC_SEALS))
goto on_error;
fexecve(memfd, argv, envp);
on_error:
saved_errno = errno;
close(memfd);
errno = saved_errno;
if (memfd >= 0) {
ssize_t bytes_sent = 0;
struct stat st = {0};
ret = fstat(fd, &st);
if (ret)
return;
while (bytes_sent < st.st_size) {
ssize_t sent;
sent = lxc_sendfile_nointr(memfd, fd, NULL,
st.st_size - bytes_sent);
if (sent < 0)
return;
bytes_sent += sent;
}
} else if (fd_to_fd(fd, tmpfd)) {
return;
}
close_prot_errno_disarm(fd);
if (memfd >= 0 && fcntl(memfd, F_ADD_SEALS, LXC_MEMFD_REXEC_SEALS))
return;
if (memfd >= 0) {
fexecve(memfd, argv, envp);
} else {
__do_close_prot_errno int execfd = -EBADF;
char procfd[LXC_PROC_PID_FD_LEN];
ret = snprintf(procfd, sizeof(procfd), "/proc/self/fd/%d", tmpfd);
if (ret < 0 || (size_t)ret >= sizeof(procfd))
return;
execfd = open(procfd, O_PATH | O_CLOEXEC);
close_prot_errno_disarm(tmpfd);
if (execfd < 0)
return;
fexecve(execfd, argv, envp);
}
}
/*
......
......@@ -452,7 +452,6 @@ int lxc_serve_state_clients(const char *name, struct lxc_handler *handler,
size_t retlen;
ssize_t ret;
struct lxc_list *cur, *next;
struct lxc_state_client *client;
struct lxc_msg msg = {.type = lxc_msg_state, .value = state};
if (state == THAWED)
......@@ -472,7 +471,7 @@ int lxc_serve_state_clients(const char *name, struct lxc_handler *handler,
return -E2BIG;
lxc_list_for_each_safe(cur, &handler->conf->state_clients, next) {
client = cur->elem;
struct lxc_state_client *client = cur->elem;
if (client->states[state] == 0) {
TRACE("State %s not registered for state client %d",
......
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