Commit 42f055d0 by Serge Hallyn Committed by GitHub

Merge pull request #1801 from brauner/2017-09-09/userns_exec

conf: add userns_exec_full()
parents 17872651 ed8704d0
...@@ -782,7 +782,7 @@ static const struct dev_symlinks dev_symlinks[] = { ...@@ -782,7 +782,7 @@ static const struct dev_symlinks dev_symlinks[] = {
{"/proc/self/fd/2", "stderr"}, {"/proc/self/fd/2", "stderr"},
}; };
static int setup_dev_symlinks(const struct lxc_rootfs *rootfs) static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs)
{ {
char path[MAXPATHLEN]; char path[MAXPATHLEN];
int ret,i; int ret,i;
...@@ -3220,13 +3220,16 @@ int lxc_setup(struct lxc_handler *handler) ...@@ -3220,13 +3220,16 @@ int lxc_setup(struct lxc_handler *handler)
} }
} }
if (!lxc_conf->is_execute && lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console, lxc_conf->ttydir)) { ret = lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console,
ERROR("failed to setup the console for '%s'", name); lxc_conf->ttydir);
if (ret < 0) {
ERROR("Failed to setup console");
return -1; return -1;
} }
if (!lxc_conf->is_execute && setup_dev_symlinks(&lxc_conf->rootfs)) { ret = lxc_setup_dev_symlinks(&lxc_conf->rootfs);
ERROR("failed to setup /dev symlinks for '%s'", name); if (ret < 0) {
ERROR("Failed to setup /dev symlinks");
return -1; return -1;
} }
...@@ -3816,8 +3819,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, ...@@ -3816,8 +3819,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
ret = lxc_map_ids(idmap, pid); ret = lxc_map_ids(idmap, pid);
if (ret < 0) { if (ret < 0) {
ERROR("error setting up {g,u}id mappings for child process " ERROR("error setting up {g,u}id mappings for child process "
"\"%d\"", "\"%d\"", pid);
pid);
goto on_error; goto on_error;
} }
...@@ -3849,6 +3851,184 @@ on_error: ...@@ -3849,6 +3851,184 @@ on_error:
return ret; return ret;
} }
int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data,
const char *fn_name)
{
pid_t pid;
uid_t euid, egid;
struct userns_fn_data d;
int p[2];
struct id_map *map;
struct lxc_list *cur;
char c = '1';
int ret = -1;
struct lxc_list *idmap = NULL, *tmplist = NULL;
struct id_map *container_root_uid = NULL, *container_root_gid = NULL,
*host_uid_map = NULL, *host_gid_map = NULL;
ret = pipe(p);
if (ret < 0) {
SYSERROR("opening pipe");
return -1;
}
d.fn = fn;
d.fn_name = fn_name;
d.arg = data;
d.p[0] = p[0];
d.p[1] = p[1];
/* Clone child in new user namespace. */
pid = lxc_clone(run_userns_fn, &d, CLONE_NEWUSER);
if (pid < 0) {
ERROR("failed to clone child process in new user namespace");
goto on_error;
}
close(p[0]);
p[0] = -1;
euid = geteuid();
egid = getegid();
/* Allocate new {g,u}id map list. */
idmap = malloc(sizeof(*idmap));
if (!idmap)
goto on_error;
lxc_list_init(idmap);
/* Find container root. */
lxc_list_for_each(cur, &conf->id_map) {
struct id_map *tmpmap;
tmplist = malloc(sizeof(*tmplist));
if (!tmplist)
goto on_error;
tmpmap = malloc(sizeof(*tmpmap));
if (!tmpmap) {
free(tmplist);
goto on_error;
}
memset(tmpmap, 0, sizeof(*tmpmap));
memcpy(tmpmap, cur->elem, sizeof(*tmpmap));
tmplist->elem = tmpmap;
lxc_list_add_tail(idmap, tmplist);
map = cur->elem;
if (map->idtype == ID_TYPE_UID)
if (euid >= map->hostid && euid < map->hostid + map->range)
host_uid_map = map;
if (map->idtype == ID_TYPE_GID)
if (egid >= map->hostid && egid < map->hostid + map->range)
host_gid_map = map;
if (map->nsid != 0)
continue;
if (map->idtype == ID_TYPE_UID)
if (container_root_uid == NULL)
container_root_uid = map;
if (map->idtype == ID_TYPE_GID)
if (container_root_gid == NULL)
container_root_gid = map;
}
if (!container_root_uid || !container_root_gid) {
ERROR("No mapping for container root found");
goto on_error;
}
/* Check whether the {g,u}id of the user has a mapping. */
if (!host_uid_map)
host_uid_map = idmap_add(conf, euid, ID_TYPE_UID);
else
host_uid_map = container_root_uid;
if (!host_gid_map)
host_gid_map = idmap_add(conf, egid, ID_TYPE_GID);
else
host_gid_map = container_root_gid;
if (!host_uid_map) {
DEBUG("Failed to find mapping for uid %d", euid);
goto on_error;
}
if (!host_gid_map) {
DEBUG("Failed to find mapping for gid %d", egid);
goto on_error;
}
if (host_uid_map && (host_uid_map != container_root_uid)) {
/* Add container root to the map. */
tmplist = malloc(sizeof(*tmplist));
if (!tmplist)
goto on_error;
lxc_list_add_elem(tmplist, host_uid_map);
lxc_list_add_tail(idmap, tmplist);
}
/* idmap will now keep track of that memory. */
host_uid_map = NULL;
if (host_gid_map && (host_gid_map != container_root_gid)) {
tmplist = malloc(sizeof(*tmplist));
if (!tmplist)
goto on_error;
lxc_list_add_elem(tmplist, host_gid_map);
lxc_list_add_tail(idmap, tmplist);
}
/* idmap will now keep track of that memory. */
host_gid_map = NULL;
if (lxc_log_get_level() == LXC_LOG_LEVEL_TRACE ||
conf->loglevel == LXC_LOG_LEVEL_TRACE) {
lxc_list_for_each(cur, idmap) {
map = cur->elem;
TRACE("establishing %cid mapping for \"%d\" in new "
"user namespace: nsuid %lu - hostid %lu - range "
"%lu",
(map->idtype == ID_TYPE_UID) ? 'u' : 'g', pid,
map->nsid, map->hostid, map->range);
}
}
/* Set up {g,u}id mapping for user namespace of child process. */
ret = lxc_map_ids(idmap, pid);
if (ret < 0) {
ERROR("error setting up {g,u}id mappings for child process "
"\"%d\"", pid);
goto on_error;
}
/* Tell child to proceed. */
if (write(p[1], &c, 1) != 1) {
SYSERROR("failed telling child process \"%d\" to proceed", pid);
goto on_error;
}
/* Wait for child to finish. */
ret = wait_for_pid(pid);
on_error:
if (idmap)
lxc_free_idmap(idmap);
if (host_uid_map && (host_uid_map != container_root_uid))
free(host_uid_map);
if (host_gid_map && (host_gid_map != container_root_gid))
free(host_gid_map);
if (p[0] != -1)
close(p[0]);
close(p[1]);
return ret;
}
/* not thread-safe, do not use from api without first forking */ /* not thread-safe, do not use from api without first forking */
static char* getuname(void) static char* getuname(void)
{ {
......
...@@ -381,6 +381,8 @@ extern int chown_mapped_root(char *path, struct lxc_conf *conf); ...@@ -381,6 +381,8 @@ extern int chown_mapped_root(char *path, struct lxc_conf *conf);
extern int lxc_ttys_shift_ids(struct lxc_conf *c); extern int lxc_ttys_shift_ids(struct lxc_conf *c);
extern int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, extern int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
const char *fn_name); const char *fn_name);
extern int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *),
void *data, const char *fn_name);
extern int parse_mntopts(const char *mntopts, unsigned long *mntflags, extern int parse_mntopts(const char *mntopts, unsigned long *mntflags,
char **mntdata); char **mntdata);
extern void tmp_proc_unmount(struct lxc_conf *lxc_conf); extern void tmp_proc_unmount(struct lxc_conf *lxc_conf);
......
...@@ -1920,42 +1920,51 @@ struct parse_line_conf { ...@@ -1920,42 +1920,51 @@ struct parse_line_conf {
static int parse_line(char *buffer, void *data) static int parse_line(char *buffer, void *data)
{ {
struct lxc_config_t *config;
char *dot, *key, *line, *linep, *value; char *dot, *key, *line, *linep, *value;
struct parse_line_conf *plc = data; bool empty_line;
struct lxc_config_t *config;
int ret = 0; int ret = 0;
char *dup = buffer;
struct parse_line_conf *plc = data;
if (lxc_is_line_empty(buffer)) /* If there are newlines in the config file we should keep them. */
return 0; empty_line = lxc_is_line_empty(dup);
if (empty_line)
dup = "\n";
/* We have to dup the buffer otherwise, at the re-exec for reboot we /* We have to dup the buffer otherwise, at the re-exec for reboot we
* modified the original string on the stack by replacing '=' by '\0' * modified the original string on the stack by replacing '=' by '\0'
* below. * below.
*/ */
linep = line = strdup(buffer); linep = line = strdup(dup);
if (!line) if (!line)
return -1; return -1;
if (!plc->from_include) if (!plc->from_include) {
if ((ret = append_unexp_config_line(line, plc->conf))) ret = append_unexp_config_line(line, plc->conf);
goto out; if (ret < 0)
goto on_error;
}
if (empty_line)
return 0;
line += lxc_char_left_gc(line, strlen(line)); line += lxc_char_left_gc(line, strlen(line));
/* ignore comments */ /* ignore comments */
if (line[0] == '#') if (line[0] == '#')
goto out; goto on_error;
/* martian option - don't add it to the config itself */ /* martian option - don't add it to the config itself */
if (strncmp(line, "lxc.", 4)) if (strncmp(line, "lxc.", 4))
goto out; goto on_error;
ret = -1; ret = -1;
dot = strstr(line, "="); dot = strchr(line, '=');
if (!dot) { if (!dot) {
ERROR("invalid configuration line: %s", line); ERROR("Invalid configuration line: %s", line);
goto out; goto on_error;
} }
*dot = '\0'; *dot = '\0';
...@@ -1980,7 +1989,7 @@ static int parse_line(char *buffer, void *data) ...@@ -1980,7 +1989,7 @@ static int parse_line(char *buffer, void *data)
config = lxc_get_config(key); config = lxc_get_config(key);
if (!config) { if (!config) {
ERROR("Unknown configuration key \"%s\"", key); ERROR("Unknown configuration key \"%s\"", key);
goto out; goto on_error;
} }
/* [START]: REMOVE IN LXC 3.0 */ /* [START]: REMOVE IN LXC 3.0 */
...@@ -1998,7 +2007,7 @@ static int parse_line(char *buffer, void *data) ...@@ -1998,7 +2007,7 @@ static int parse_line(char *buffer, void *data)
ret = config->set(key, value, plc->conf, NULL); ret = config->set(key, value, plc->conf, NULL);
out: on_error:
free(linep); free(linep);
return ret; return ret;
} }
......
...@@ -92,8 +92,6 @@ int parse_idmaps(const char *idmap, char *type, unsigned long *nsid, ...@@ -92,8 +92,6 @@ int parse_idmaps(const char *idmap, char *type, unsigned long *nsid,
/* Move beyond \0. */ /* Move beyond \0. */
slide++; slide++;
/* align */
window = slide;
/* Validate that only whitespace follows. */ /* Validate that only whitespace follows. */
slide += strspn(slide, " \t\r"); slide += strspn(slide, " \t\r");
/* If there was only one whitespace then we whiped it with our \0 above. /* If there was only one whitespace then we whiped it with our \0 above.
...@@ -118,8 +116,6 @@ int parse_idmaps(const char *idmap, char *type, unsigned long *nsid, ...@@ -118,8 +116,6 @@ int parse_idmaps(const char *idmap, char *type, unsigned long *nsid,
/* Move beyond \0. */ /* Move beyond \0. */
slide++; slide++;
/* align */
window = slide;
/* Validate that only whitespace follows. */ /* Validate that only whitespace follows. */
slide += strspn(slide, " \t\r"); slide += strspn(slide, " \t\r");
/* If there was only one whitespace then we whiped it with our \0 above. /* If there was only one whitespace then we whiped it with our \0 above.
......
...@@ -228,11 +228,6 @@ extern int lxc_console_mainloop_add(struct lxc_epoll_descr *descr, ...@@ -228,11 +228,6 @@ extern int lxc_console_mainloop_add(struct lxc_epoll_descr *descr,
{ {
struct lxc_console *console = &conf->console; struct lxc_console *console = &conf->console;
if (conf->is_execute) {
INFO("no console for lxc-execute.");
return 0;
}
if (!conf->rootfs.path) { if (!conf->rootfs.path) {
INFO("no rootfs, no console."); INFO("no rootfs, no console.");
return 0; return 0;
...@@ -480,7 +475,6 @@ static int lxc_console_peer_default(struct lxc_console *console) ...@@ -480,7 +475,6 @@ static int lxc_console_peer_default(struct lxc_console *console)
console->tios = malloc(sizeof(*console->tios)); console->tios = malloc(sizeof(*console->tios));
if (!console->tios) { if (!console->tios) {
SYSERROR("failed to allocate memory"); SYSERROR("failed to allocate memory");
ret = -ENOMEM;
goto on_error1; goto on_error1;
} }
...@@ -492,7 +486,6 @@ static int lxc_console_peer_default(struct lxc_console *console) ...@@ -492,7 +486,6 @@ static int lxc_console_peer_default(struct lxc_console *console)
on_error2: on_error2:
free(console->tios); free(console->tios);
console->tios = NULL; console->tios = NULL;
ret = -ENOTTY;
on_error1: on_error1:
close(console->peer); close(console->peer);
...@@ -528,11 +521,6 @@ int lxc_console_create(struct lxc_conf *conf) ...@@ -528,11 +521,6 @@ int lxc_console_create(struct lxc_conf *conf)
struct lxc_console *console = &conf->console; struct lxc_console *console = &conf->console;
int ret; int ret;
if (conf->is_execute) {
INFO("not allocating a console device for lxc-execute.");
return 0;
}
if (!conf->rootfs.path) { if (!conf->rootfs.path) {
INFO("container does not have a rootfs, console device will be shared with the host"); INFO("container does not have a rootfs, console device will be shared with the host");
return 0; return 0;
......
...@@ -551,7 +551,7 @@ static void exec_criu(struct criu_opts *opts) ...@@ -551,7 +551,7 @@ static void exec_criu(struct criu_opts *opts)
external_not_veth = false; external_not_veth = false;
} }
if (n->name) { if (n->name[0] != '\0') {
if (strlen(n->name) >= sizeof(eth)) if (strlen(n->name) >= sizeof(eth))
goto err; goto err;
strncpy(eth, n->name, sizeof(eth)); strncpy(eth, n->name, sizeof(eth));
......
...@@ -638,7 +638,7 @@ static int count_entries(char *buf, off_t len, char *name, char *net_type, char ...@@ -638,7 +638,7 @@ static int count_entries(char *buf, off_t len, char *name, char *net_type, char
{ {
int count = 0; int count = 0;
bool owner = false;; bool owner = false;;
char *buf_end = &buf[len]; char *buf_end;
buf_end = &buf[len]; buf_end = &buf[len];
while ((buf = find_line(buf, buf_end, name, net_type, net_link, NULL, while ((buf = find_line(buf, buf_end, name, net_type, net_link, NULL,
......
...@@ -2569,12 +2569,17 @@ static bool has_snapshots(struct lxc_container *c) ...@@ -2569,12 +2569,17 @@ static bool has_snapshots(struct lxc_container *c)
} }
static bool do_destroy_container(struct lxc_conf *conf) { static bool do_destroy_container(struct lxc_conf *conf) {
int ret;
if (am_unpriv()) { if (am_unpriv()) {
if (userns_exec_1(conf, storage_destroy_wrapper, conf, ret = userns_exec_full(conf, storage_destroy_wrapper, conf,
"storage_destroy_wrapper") < 0) "storage_destroy_wrapper");
if (ret < 0)
return false; return false;
return true; return true;
} }
return storage_destroy(conf); return storage_destroy(conf);
} }
...@@ -2708,8 +2713,8 @@ static bool container_destroy(struct lxc_container *c, ...@@ -2708,8 +2713,8 @@ static bool container_destroy(struct lxc_container *c,
if (ret < 0 || (size_t)ret >= len) if (ret < 0 || (size_t)ret >= len)
goto out; goto out;
if (am_unpriv()) if (am_unpriv())
ret = userns_exec_1(conf, lxc_rmdir_onedev_wrapper, path, ret = userns_exec_full(conf, lxc_rmdir_onedev_wrapper, path,
"lxc_rmdir_onedev_wrapper"); "lxc_rmdir_onedev_wrapper");
else else
ret = lxc_rmdir_onedev(path, "snaps"); ret = lxc_rmdir_onedev(path, "snaps");
if (ret < 0) { if (ret < 0) {
...@@ -3551,8 +3556,8 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char ...@@ -3551,8 +3556,8 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
data.flags = flags; data.flags = flags;
data.hookargs = hookargs; data.hookargs = hookargs;
if (am_unpriv()) if (am_unpriv())
ret = userns_exec_1(c->lxc_conf, clone_update_rootfs_wrapper, ret = userns_exec_full(c->lxc_conf, clone_update_rootfs_wrapper,
&data, "clone_update_rootfs_wrapper"); &data, "clone_update_rootfs_wrapper");
else else
ret = clone_update_rootfs(&data); ret = clone_update_rootfs(&data);
if (ret < 0) if (ret < 0)
......
...@@ -243,7 +243,6 @@ int lxc_monitor_open(const char *lxcpath) ...@@ -243,7 +243,6 @@ int lxc_monitor_open(const char *lxcpath)
ERROR("Failed to connect to monitor socket: %s.", strerror(errno)); ERROR("Failed to connect to monitor socket: %s.", strerror(errno));
goto on_error; goto on_error;
} }
ret = 0;
return fd; return fd;
......
...@@ -935,7 +935,6 @@ int netdev_get_mtu(int ifindex) ...@@ -935,7 +935,6 @@ int netdev_get_mtu(int ifindex)
goto out; goto out;
recv_len = err; recv_len = err;
err = 0;
/* Satisfy the typing for the netlink macros */ /* Satisfy the typing for the netlink macros */
msg = answer->nlmsghdr; msg = answer->nlmsghdr;
...@@ -1377,7 +1376,6 @@ int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr) ...@@ -1377,7 +1376,6 @@ int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr)
data = (unsigned char *)sockaddr->sa_data; data = (unsigned char *)sockaddr->sa_data;
while ((*macaddr != '\0') && (i < ETH_ALEN)) { while ((*macaddr != '\0') && (i < ETH_ALEN)) {
val = 0;
c = *macaddr++; c = *macaddr++;
if (isdigit(c)) if (isdigit(c))
val = c - '0'; val = c - '0';
......
...@@ -1142,7 +1142,7 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1142,7 +1142,7 @@ static int lxc_spawn(struct lxc_handler *handler)
bool wants_to_map_ids; bool wants_to_map_ids;
int saved_ns_fd[LXC_NS_MAX]; int saved_ns_fd[LXC_NS_MAX];
struct lxc_list *id_map; struct lxc_list *id_map;
int failed_before_rename = 0, preserve_mask = 0; int preserve_mask = 0;
bool cgroups_connected = false; bool cgroups_connected = false;
id_map = &handler->conf->id_map; id_map = &handler->conf->id_map;
...@@ -1256,15 +1256,11 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1256,15 +1256,11 @@ static int lxc_spawn(struct lxc_handler *handler)
goto out_delete_net; goto out_delete_net;
} }
if (lxc_sync_wake_child(handler, LXC_SYNC_STARTUP)) { if (lxc_sync_wake_child(handler, LXC_SYNC_STARTUP))
failed_before_rename = 1;
goto out_delete_net; goto out_delete_net;
}
if (lxc_sync_wait_child(handler, LXC_SYNC_CONFIGURE)) { if (lxc_sync_wait_child(handler, LXC_SYNC_CONFIGURE))
failed_before_rename = 1;
goto out_delete_net; goto out_delete_net;
}
if (!cgroup_create_legacy(handler)) { if (!cgroup_create_legacy(handler)) {
ERROR("Failed to setup legacy cgroups for container \"%s\".", name); ERROR("Failed to setup legacy cgroups for container \"%s\".", name);
...@@ -1281,9 +1277,6 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1281,9 +1277,6 @@ static int lxc_spawn(struct lxc_handler *handler)
if (!cgroup_chown(handler)) if (!cgroup_chown(handler))
goto out_delete_net; goto out_delete_net;
if (failed_before_rename)
goto out_delete_net;
handler->netnsfd = lxc_preserve_ns(handler->pid, "net"); handler->netnsfd = lxc_preserve_ns(handler->pid, "net");
if (handler->netnsfd < 0) { if (handler->netnsfd < 0) {
ERROR("Failed to preserve network namespace"); ERROR("Failed to preserve network namespace");
...@@ -1596,8 +1589,8 @@ static void lxc_destroy_container_on_signal(struct lxc_handler *handler, ...@@ -1596,8 +1589,8 @@ static void lxc_destroy_container_on_signal(struct lxc_handler *handler,
} }
if (!handler->am_root) if (!handler->am_root)
ret = userns_exec_1(handler->conf, lxc_rmdir_onedev_wrapper, ret = userns_exec_full(handler->conf, lxc_rmdir_onedev_wrapper,
destroy, "lxc_rmdir_onedev_wrapper"); destroy, "lxc_rmdir_onedev_wrapper");
else else
ret = lxc_rmdir_onedev(destroy, NULL); ret = lxc_rmdir_onedev(destroy, NULL);
...@@ -1615,9 +1608,12 @@ static int lxc_rmdir_onedev_wrapper(void *data) ...@@ -1615,9 +1608,12 @@ static int lxc_rmdir_onedev_wrapper(void *data)
} }
static bool do_destroy_container(struct lxc_handler *handler) { static bool do_destroy_container(struct lxc_handler *handler) {
int ret;
if (!handler->am_root) { if (!handler->am_root) {
if (userns_exec_1(handler->conf, storage_destroy_wrapper, ret = userns_exec_full(handler->conf, storage_destroy_wrapper,
handler->conf, "storage_destroy_wrapper") < 0) handler->conf, "storage_destroy_wrapper");
if (ret < 0)
return false; return false;
return true; return true;
......
...@@ -164,8 +164,8 @@ int aufs_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, ...@@ -164,8 +164,8 @@ int aufs_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
rdata.src = odelta; rdata.src = odelta;
rdata.dest = ndelta; rdata.dest = ndelta;
if (am_unpriv()) if (am_unpriv())
ret = userns_exec_1(conf, lxc_rsync_delta_wrapper, ret = userns_exec_full(conf, lxc_rsync_delta_wrapper,
&rdata, "lxc_rsync_delta_wrapper"); &rdata, "lxc_rsync_delta_wrapper");
else else
ret = run_command(cmd_output, sizeof(cmd_output), ret = run_command(cmd_output, sizeof(cmd_output),
lxc_rsync_delta_wrapper, lxc_rsync_delta_wrapper,
......
...@@ -434,8 +434,8 @@ bool btrfs_create_clone(struct lxc_conf *conf, struct lxc_storage *orig, ...@@ -434,8 +434,8 @@ bool btrfs_create_clone(struct lxc_conf *conf, struct lxc_storage *orig,
data.orig = orig; data.orig = orig;
data.new = new; data.new = new;
if (am_unpriv()) { if (am_unpriv()) {
ret = userns_exec_1(conf, lxc_storage_rsync_exec_wrapper, &data, ret = userns_exec_full(conf, lxc_storage_rsync_exec_wrapper,
"lxc_storage_rsync_exec_wrapper"); &data, "lxc_storage_rsync_exec_wrapper");
if (ret < 0) { if (ret < 0) {
ERROR("Failed to rsync from \"%s\" into \"%s\"", ERROR("Failed to rsync from \"%s\" into \"%s\"",
orig->dest, new->dest); orig->dest, new->dest);
......
...@@ -109,9 +109,9 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char ...@@ -109,9 +109,9 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
return -1; return -1;
} }
strncpy(delta, new->dest, lastslashidx + 1); memcpy(delta, new->dest, lastslashidx + 1);
strncpy(delta + lastslashidx, "delta0", sizeof("delta0") - 1); memcpy(delta + lastslashidx, "delta0", sizeof("delta0") - 1);
delta[lastslashidx + sizeof("delta0")] = '\0'; delta[lastslashidx + sizeof("delta0") - 1] = '\0';
ret = mkdir(delta, 0755); ret = mkdir(delta, 0755);
if (ret < 0 && errno != EEXIST) { if (ret < 0 && errno != EEXIST) {
...@@ -141,12 +141,13 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char ...@@ -141,12 +141,13 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
return -1; return -1;
} }
strncpy(work, new->dest, lastslashidx + 1); memcpy(work, new->dest, lastslashidx + 1);
strncpy(work + lastslashidx, "olwork", sizeof("olwork") - 1); memcpy(work + lastslashidx, "olwork", sizeof("olwork") - 1);
work[lastslashidx + sizeof("olwork")] = '\0'; work[lastslashidx + sizeof("olwork") - 1] = '\0';
if (mkdir(work, 0755) < 0) { ret = mkdir(work, 0755);
SYSERROR("error: mkdir %s", work); if (ret < 0) {
SYSERROR("Failed to create directory \"%s\"", work);
free(delta); free(delta);
free(work); free(work);
return -1; return -1;
...@@ -200,9 +201,8 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char ...@@ -200,9 +201,8 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
nsrc = strchr(osrc, ':') + 1; nsrc = strchr(osrc, ':') + 1;
if ((nsrc != osrc + 8) && (nsrc != osrc + 10)) { if ((nsrc != osrc + 8) && (nsrc != osrc + 10)) {
ERROR("Detected \":\" in \"%s\" at wrong position", osrc);
free(osrc); free(osrc);
ERROR("Detected \":\" in \"%s\" at wrong position",
osrc);
return -22; return -22;
} }
...@@ -219,9 +219,9 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char ...@@ -219,9 +219,9 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
ret = mkdir(ndelta, 0755); ret = mkdir(ndelta, 0755);
if (ret < 0 && errno != EEXIST) { if (ret < 0 && errno != EEXIST) {
SYSERROR("Failed to create directory \"%s\"", ndelta);
free(osrc); free(osrc);
free(ndelta); free(ndelta);
SYSERROR("Failed to create directory \"%s\"", ndelta);
return -1; return -1;
} }
...@@ -237,9 +237,9 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char ...@@ -237,9 +237,9 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
*/ */
lastslash = strrchr(ndelta, '/'); lastslash = strrchr(ndelta, '/');
if (!lastslash) { if (!lastslash) {
ERROR("Failed to detect \"/\" in \"%s\"", ndelta);
free(osrc); free(osrc);
free(ndelta); free(ndelta);
ERROR("Failed to detect \"/\" in \"%s\"", ndelta);
return -1; return -1;
} }
lastslash++; lastslash++;
...@@ -253,16 +253,16 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char ...@@ -253,16 +253,16 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
return -1; return -1;
} }
strncpy(work, ndelta, lastslashidx + 1); memcpy(work, ndelta, lastslashidx + 1);
strncpy(work + lastslashidx, "olwork", sizeof("olwork") - 1); memcpy(work + lastslashidx, "olwork", sizeof("olwork") - 1);
work[lastslashidx + sizeof("olwork")] = '\0'; work[lastslashidx + sizeof("olwork") - 1] = '\0';
ret = mkdir(work, 0755); ret = mkdir(work, 0755);
if (ret < 0 && errno != EEXIST) { if (ret < 0 && errno != EEXIST) {
SYSERROR("Failed to create directory \"%s\"", ndelta);
free(osrc); free(osrc);
free(ndelta); free(ndelta);
free(work); free(work);
SYSERROR("Failed to create directory \"%s\"", ndelta);
return -1; return -1;
} }
...@@ -322,7 +322,7 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char ...@@ -322,7 +322,7 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
s1 = strrchr(clean_old_path, '/'); s1 = strrchr(clean_old_path, '/');
if (!s1) { if (!s1) {
ERROR("Failed to detect \"/\" in string \"%s\"", s1); ERROR("Failed to detect \"/\" in string \"%s\"", clean_old_path);
free(clean_old_path); free(clean_old_path);
free(clean_new_path); free(clean_new_path);
return -1; return -1;
...@@ -330,7 +330,7 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char ...@@ -330,7 +330,7 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
s2 = strrchr(clean_new_path, '/'); s2 = strrchr(clean_new_path, '/');
if (!s2) { if (!s2) {
ERROR("Failed to detect \"/\" in string \"%s\"", s2); ERROR("Failed to detect \"/\" in string \"%s\"", clean_new_path);
free(clean_old_path); free(clean_old_path);
free(clean_new_path); free(clean_new_path);
return -1; return -1;
...@@ -417,8 +417,8 @@ int ovl_create(struct lxc_storage *bdev, const char *dest, const char *n, ...@@ -417,8 +417,8 @@ int ovl_create(struct lxc_storage *bdev, const char *dest, const char *n,
return -1; return -1;
} }
strncpy(delta, dest, len); memcpy(delta, dest, len);
strncpy(delta + len - 6, "delta0", sizeof("delta0") - 1); memcpy(delta + len - 6, "delta0", sizeof("delta0") - 1);
delta[len + sizeof("delta0")] = '\0'; delta[len + sizeof("delta0")] = '\0';
ret = mkdir_p(delta, 0755); ret = mkdir_p(delta, 0755);
...@@ -575,9 +575,9 @@ int ovl_mount(struct lxc_storage *bdev) ...@@ -575,9 +575,9 @@ int ovl_mount(struct lxc_storage *bdev)
return -22; return -22;
} }
strncpy(work, upper, lastslashidx + 1); memcpy(work, upper, lastslashidx + 1);
strncpy(work + lastslashidx, "olwork", sizeof("olwork") - 1); memcpy(work + lastslashidx, "olwork", sizeof("olwork") - 1);
work[lastslashidx + sizeof("olwork")] = '\0'; work[lastslashidx + sizeof("olwork") - 1] = '\0';
ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata); ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata);
if (ret < 0) { if (ret < 0) {
...@@ -747,8 +747,9 @@ int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs, ...@@ -747,8 +747,9 @@ int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs,
char lxcpath[MAXPATHLEN]; char lxcpath[MAXPATHLEN];
char **opts; char **opts;
int ret; int ret;
size_t arrlen, dirlen, i, len, rootfslen; size_t arrlen, i, len, rootfslen;
int fret = -1; int fret = -1;
size_t dirlen = 0;
char *rootfs_dir = NULL, *rootfs_path = NULL, *upperdir = NULL, char *rootfs_dir = NULL, *rootfs_path = NULL, *upperdir = NULL,
*workdir = NULL; *workdir = NULL;
...@@ -772,8 +773,7 @@ int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs, ...@@ -772,8 +773,7 @@ int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs,
} }
if (rootfs_path) { if (rootfs_path) {
ret = ret = snprintf(lxcpath, MAXPATHLEN, "%s/%s", lxc_path, lxc_name);
snprintf(lxcpath, MAXPATHLEN, "%s/%s", lxc_path, lxc_name);
if (ret < 0 || ret >= MAXPATHLEN) if (ret < 0 || ret >= MAXPATHLEN)
goto err; goto err;
...@@ -971,8 +971,8 @@ static int ovl_do_rsync(const char *src, const char *dest, ...@@ -971,8 +971,8 @@ static int ovl_do_rsync(const char *src, const char *dest,
rdata.src = (char *)src; rdata.src = (char *)src;
rdata.dest = (char *)dest; rdata.dest = (char *)dest;
if (am_unpriv()) if (am_unpriv())
ret = userns_exec_1(conf, lxc_rsync_exec_wrapper, &rdata, ret = userns_exec_full(conf, lxc_rsync_exec_wrapper, &rdata,
"lxc_rsync_exec_wrapper"); "lxc_rsync_exec_wrapper");
else else
ret = run_command(cmd_output, sizeof(cmd_output), ret = run_command(cmd_output, sizeof(cmd_output),
lxc_rsync_exec_wrapper, (void *)&rdata); lxc_rsync_exec_wrapper, (void *)&rdata);
......
...@@ -502,8 +502,9 @@ struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname, ...@@ -502,8 +502,9 @@ struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname,
data.orig = orig; data.orig = orig;
data.new = new; data.new = new;
if (am_unpriv()) if (am_unpriv())
ret = userns_exec_1(c->lxc_conf, lxc_storage_rsync_exec_wrapper, ret = userns_exec_full(c->lxc_conf,
&data, "lxc_storage_rsync_exec_wrapper"); lxc_storage_rsync_exec_wrapper, &data,
"lxc_storage_rsync_exec_wrapper");
else else
ret = run_command(cmd_output, sizeof(cmd_output), ret = run_command(cmd_output, sizeof(cmd_output),
lxc_storage_rsync_exec_wrapper, (void *)&data); lxc_storage_rsync_exec_wrapper, (void *)&data);
......
...@@ -136,7 +136,6 @@ extern struct lxc_storage *storage_create(const char *dest, const char *type, ...@@ -136,7 +136,6 @@ extern struct lxc_storage *storage_create(const char *dest, const char *type,
extern void storage_put(struct lxc_storage *bdev); extern void storage_put(struct lxc_storage *bdev);
extern bool storage_destroy(struct lxc_conf *conf); extern bool storage_destroy(struct lxc_conf *conf);
/* callback function to be used with userns_exec_1() */
extern int storage_destroy_wrapper(void *data); extern int storage_destroy_wrapper(void *data);
extern bool rootfs_is_blockdev(struct lxc_conf *conf); extern bool rootfs_is_blockdev(struct lxc_conf *conf);
extern char *lxc_storage_get_path(char *src, const char *prefix); extern char *lxc_storage_get_path(char *src, const char *prefix);
......
...@@ -228,6 +228,9 @@ int main(int argc, char *argv[]) ...@@ -228,6 +228,9 @@ int main(int argc, char *argv[])
* dest: del + 1 == OUNT|PID * dest: del + 1 == OUNT|PID
* src: del + 3 == NT|PID * src: del + 3 == NT|PID
*/ */
if (!namespaces)
usage(argv[0]);
while ((del = strstr(namespaces, "MOUNT"))) while ((del = strstr(namespaces, "MOUNT")))
memmove(del + 1, del + 3, strlen(del) - 2); memmove(del + 1, del + 3, strlen(del) - 2);
......
...@@ -316,10 +316,8 @@ int main(int argc, char *argv[]) ...@@ -316,10 +316,8 @@ int main(int argc, char *argv[])
argv = &argv[optind]; argv = &argv[optind];
argc = argc - optind; argc = argc - optind;
if (argc < 1) { if (argc < 1)
argv = default_args; argv = default_args;
argc = 1;
}
if (pipe(pipe1) < 0 || pipe(pipe2) < 0) { if (pipe(pipe1) < 0 || pipe(pipe2) < 0) {
perror("pipe"); perror("pipe");
...@@ -367,10 +365,9 @@ int main(int argc, char *argv[]) ...@@ -367,10 +365,9 @@ int main(int argc, char *argv[])
buf[0] = '1'; buf[0] = '1';
if (lxc_map_ids(&active_map, pid)) { if (lxc_map_ids(&active_map, pid))
fprintf(stderr, "error mapping child\n"); fprintf(stderr, "error mapping child\n");
ret = 0;
}
if (write(pipe2[1], buf, 1) < 0) { if (write(pipe2[1], buf, 1) < 0) {
perror("write to pipe"); perror("write to pipe");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
......
...@@ -494,7 +494,6 @@ extern struct lxc_popen_FILE *lxc_popen(const char *command) ...@@ -494,7 +494,6 @@ extern struct lxc_popen_FILE *lxc_popen(const char *command)
int child_std_end = STDOUT_FILENO; int child_std_end = STDOUT_FILENO;
close(parent_end); close(parent_end);
parent_end = -1;
if (child_end != child_std_end) { if (child_end != child_std_end) {
/* dup2() doesn't dup close-on-exec flag */ /* dup2() doesn't dup close-on-exec flag */
...@@ -533,7 +532,6 @@ extern struct lxc_popen_FILE *lxc_popen(const char *command) ...@@ -533,7 +532,6 @@ extern struct lxc_popen_FILE *lxc_popen(const char *command)
/* parent */ /* parent */
close(child_end); close(child_end);
child_end = -1;
if (child_pid < 0) { if (child_pid < 0) {
ERROR("fork failure"); ERROR("fork failure");
...@@ -2330,9 +2328,11 @@ int run_command(char *buf, size_t buf_size, int (*child_fn)(void *), void *args) ...@@ -2330,9 +2328,11 @@ int run_command(char *buf, size_t buf_size, int (*child_fn)(void *), void *args)
/* close the write-end of the pipe */ /* close the write-end of the pipe */
close(pipefd[1]); close(pipefd[1]);
bytes = read(pipefd[0], buf, (buf_size > 0) ? (buf_size - 1) : 0); if (buf && buf_size > 0) {
if (bytes > 0) bytes = read(pipefd[0], buf, buf_size - 1);
buf[bytes - 1] = '\0'; if (bytes > 0)
buf[bytes - 1] = '\0';
}
fret = wait_for_pid(child); fret = wait_for_pid(child);
/* close the read-end of the pipe */ /* close the read-end of the pipe */
......
...@@ -188,7 +188,8 @@ int main(int argc, char *argv[]) { ...@@ -188,7 +188,8 @@ int main(int argc, char *argv[]) {
} }
modes[i] = tok; modes[i] = tok;
} }
modes[i] = NULL; if (modes)
modes[i] = NULL;
break; break;
} }
default: /* '?' */ default: /* '?' */
......
...@@ -40,10 +40,8 @@ static int destroy_busybox(void) ...@@ -40,10 +40,8 @@ static int destroy_busybox(void)
return -1; return -1;
} }
if (pid == 0) { if (pid == 0) {
ret = execlp("lxc-destroy", "lxc-destroy", "-f", "-n", MYNAME, NULL); execlp("lxc-destroy", "lxc-destroy", "-f", "-n", MYNAME, NULL);
// Should not return exit(EXIT_FAILURE);
perror("execl");
exit(1);
} }
again: again:
ret = waitpid(pid, &status, 0); ret = waitpid(pid, &status, 0);
...@@ -72,10 +70,8 @@ static int create_busybox(void) ...@@ -72,10 +70,8 @@ static int create_busybox(void)
return -1; return -1;
} }
if (pid == 0) { if (pid == 0) {
ret = execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL); execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL);
// Should not return exit(EXIT_FAILURE);
perror("execl");
exit(1);
} }
again: again:
ret = waitpid(pid, &status, 0); ret = waitpid(pid, &status, 0);
......
...@@ -38,10 +38,8 @@ static int create_container(void) ...@@ -38,10 +38,8 @@ static int create_container(void)
return -1; return -1;
} }
if (pid == 0) { if (pid == 0) {
ret = execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL); execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL);
// Should not return exit(EXIT_FAILURE);
perror("execl");
exit(1);
} }
again: again:
ret = waitpid(pid, &status, 0); ret = waitpid(pid, &status, 0);
......
...@@ -38,10 +38,8 @@ static int create_container(void) ...@@ -38,10 +38,8 @@ static int create_container(void)
return -1; return -1;
} }
if (pid == 0) { if (pid == 0) {
ret = execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL); execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL);
// Should not return exit(EXIT_FAILURE);
perror("execl");
exit(1);
} }
again: again:
ret = waitpid(pid, &status, 0); ret = waitpid(pid, &status, 0);
......
...@@ -40,10 +40,8 @@ static int destroy_container(void) ...@@ -40,10 +40,8 @@ static int destroy_container(void)
return -1; return -1;
} }
if (pid == 0) { if (pid == 0) {
ret = execlp("lxc-destroy", "lxc-destroy", "-f", "-n", MYNAME, NULL); execlp("lxc-destroy", "lxc-destroy", "-f", "-n", MYNAME, NULL);
// Should not return exit(EXIT_FAILURE);
perror("execl");
exit(1);
} }
again: again:
ret = waitpid(pid, &status, 0); ret = waitpid(pid, &status, 0);
...@@ -72,10 +70,8 @@ static int create_container(void) ...@@ -72,10 +70,8 @@ static int create_container(void)
return -1; return -1;
} }
if (pid == 0) { if (pid == 0) {
ret = execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL); execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL);
// Should not return exit(EXIT_FAILURE);
perror("execl");
exit(1);
} }
again: again:
ret = waitpid(pid, &status, 0); ret = waitpid(pid, &status, 0);
......
...@@ -40,10 +40,8 @@ static int destroy_container(void) ...@@ -40,10 +40,8 @@ static int destroy_container(void)
return -1; return -1;
} }
if (pid == 0) { if (pid == 0) {
ret = execlp("lxc-destroy", "lxc-destroy", "-f", "-n", MYNAME, NULL); execlp("lxc-destroy", "lxc-destroy", "-f", "-n", MYNAME, NULL);
// Should not return exit(EXIT_FAILURE);
perror("execl");
exit(1);
} }
again: again:
ret = waitpid(pid, &status, 0); ret = waitpid(pid, &status, 0);
...@@ -72,10 +70,8 @@ static int create_container(void) ...@@ -72,10 +70,8 @@ static int create_container(void)
return -1; return -1;
} }
if (pid == 0) { if (pid == 0) {
ret = execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL); execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL);
// Should not return exit(EXIT_FAILURE);
perror("execl");
exit(1);
} }
again: again:
ret = waitpid(pid, &status, 0); ret = waitpid(pid, &status, 0);
......
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