tools: move lxc-unshare to API symbols only

Closes #2073. Signed-off-by: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent b678c6d8
...@@ -20,30 +20,27 @@ ...@@ -20,30 +20,27 @@
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "config.h"
#include <stdio.h> #define _GNU_SOURCE
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <getopt.h> #include <getopt.h>
#include <libgen.h> #include <libgen.h>
#include <netinet/in.h>
#include <pwd.h> #include <pwd.h>
#include <sched.h>
#include <signal.h> #include <signal.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/eventfd.h> #include <sys/eventfd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h>
#include "caps.h" #include "arguments.h"
#include "cgroup.h" #include "tool_utils.h"
#include "error.h"
#include "log.h"
#include "namespace.h"
#include "network.h"
#include "utils.h"
struct my_iflist struct my_iflist
{ {
...@@ -67,7 +64,7 @@ static void usage(char *cmd) ...@@ -67,7 +64,7 @@ static void usage(char *cmd)
static bool lookup_user(const char *optarg, uid_t *uid) static bool lookup_user(const char *optarg, uid_t *uid)
{ {
char name[MAXPATHLEN]; char name[TOOL_MAXPATHLEN];
struct passwd *pwent = NULL; struct passwd *pwent = NULL;
if (!optarg || (optarg[0] == '\0')) if (!optarg || (optarg[0] == '\0'))
...@@ -147,11 +144,34 @@ static int do_start(void *arg) ...@@ -147,11 +144,34 @@ static int do_start(void *arg)
return 1; return 1;
} }
int write_id_mapping(pid_t pid, const char *buf, size_t buf_size)
{
char path[TOOL_MAXPATHLEN];
int fd, ret;
ret = snprintf(path, TOOL_MAXPATHLEN, "/proc/%d/uid_map", pid);
if (ret < 0 || ret >= TOOL_MAXPATHLEN)
return -E2BIG;
fd = open(path, O_WRONLY);
if (fd < 0)
return -1;
errno = 0;
ret = lxc_write_nointr(fd, buf, buf_size);
close(fd);
if (ret < 0 || (size_t)ret != buf_size)
return -1;
return 0;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
char *del; char *del;
char **it, **args; char **it, **args;
int opt, status; int opt;
int ret; int ret;
char *namespaces = NULL; char *namespaces = NULL;
int flags = 0, daemonize = 0; int flags = 0, daemonize = 0;
...@@ -284,7 +304,7 @@ int main(int argc, char *argv[]) ...@@ -284,7 +304,7 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
ret = write_id_mapping(ID_TYPE_UID, pid, umap, strlen(umap)); ret = write_id_mapping(pid, umap, strlen(umap));
if (ret < 0) { if (ret < 0) {
close(start_arg.wait_fd); close(start_arg.wait_fd);
fprintf(stderr, "uid mapping failed\n"); fprintf(stderr, "uid mapping failed\n");
...@@ -301,19 +321,40 @@ int main(int argc, char *argv[]) ...@@ -301,19 +321,40 @@ int main(int argc, char *argv[])
if (my_iflist) { if (my_iflist) {
for (tmpif = my_iflist; tmpif; tmpif = tmpif->mi_next) { for (tmpif = my_iflist; tmpif; tmpif = tmpif->mi_next) {
if (lxc_netdev_move_by_name(tmpif->mi_ifname, pid, NULL) < 0) pid_t pid;
fprintf(stderr,"Could not move interface %s into container %d: %s\n", tmpif->mi_ifname, pid, strerror(errno));
pid = fork();
if (pid < 0)
fprintf(stderr, "Failed to move network device "
"\"%s\" to network namespace\n",
tmpif->mi_ifname);
if (pid == 0) {
char buf[256];
ret = snprintf(buf, 256, "%d", pid);
if (ret < 0 || ret >= 256)
exit(EXIT_FAILURE);
execlp("ip", "ip", "link", "set", "dev", tmpif->mi_ifname, "netns", buf, (char *)NULL);
exit(EXIT_FAILURE);
}
if (wait_for_pid(pid) != 0)
fprintf(stderr, "Could not move interface %s "
"into container %d: %s\n",
tmpif->mi_ifname, pid, strerror(errno));
} }
} }
if (daemonize) if (daemonize)
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
if (waitpid(pid, &status, 0) < 0) { if (wait_for_pid(pid) != 0) {
fprintf(stderr, "failed to wait for '%d'\n", pid); fprintf(stderr, "failed to wait for '%d'\n", pid);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* Call exit() directly on this function because it retuns an exit code. */ /* Call exit() directly on this function because it retuns an exit code. */
exit(lxc_error_set_and_log(pid, status)); exit(EXIT_SUCCESS);
} }
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <strings.h> #include <strings.h>
#include <unistd.h> #include <unistd.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <sys/mount.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
...@@ -42,6 +43,7 @@ ...@@ -42,6 +43,7 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h"
#include "tool_utils.h" #include "tool_utils.h"
int lxc_fill_elevated_privileges(char *flaglist, int *flags) int lxc_fill_elevated_privileges(char *flaglist, int *flags)
...@@ -1131,3 +1133,64 @@ again: ...@@ -1131,3 +1133,64 @@ again:
goto again; goto again;
return ret; return ret;
} }
static int mount_fs(const char *source, const char *target, const char *type)
{
/* the umount may fail */
if (umount(target) < 0)
if (mount(source, target, type, 0, NULL) < 0)
return -1;
return 0;
}
void lxc_setup_fs(void)
{
(void)mount_fs("proc", "/proc", "proc");
/* if /dev has been populated by us, /dev/shm does not exist */
if (access("/dev/shm", F_OK))
(void)mkdir("/dev/shm", 0777);
/* if we can't mount /dev/shm, continue anyway */
(void)mount_fs("shmfs", "/dev/shm", "tmpfs");
/* If we were able to mount /dev/shm, then /dev exists */
/* Sure, but it's read-only per config :) */
if (access("/dev/mqueue", F_OK))
(void)mkdir("/dev/mqueue", 0666);
/* continue even without posix message queue support */
(void)mount_fs("mqueue", "/dev/mqueue", "mqueue");
}
struct clone_arg {
int (*fn)(void *);
void *arg;
};
static int do_clone(void *arg)
{
struct clone_arg *clone_arg = arg;
return clone_arg->fn(clone_arg->arg);
}
pid_t lxc_clone(int (*fn)(void *), void *arg, int flags)
{
struct clone_arg clone_arg = {
.fn = fn,
.arg = arg,
};
size_t stack_size = lxc_getpagesize();
void *stack = alloca(stack_size);
pid_t ret;
#ifdef __ia64__
ret = __clone2(do_clone, stack, stack_size, flags | SIGCHLD, &clone_arg);
#else
ret = clone(do_clone, stack + stack_size, flags | SIGCHLD, &clone_arg);
#endif
return ret;
}
...@@ -176,4 +176,28 @@ extern ssize_t lxc_write_nointr(int fd, const void* buf, size_t count); ...@@ -176,4 +176,28 @@ extern ssize_t lxc_write_nointr(int fd, const void* buf, size_t count);
extern char *get_rundir(); extern char *get_rundir();
extern void lxc_setup_fs(void);
static inline uint64_t lxc_getpagesize(void)
{
int64_t pgsz;
pgsz = sysconf(_SC_PAGESIZE);
if (pgsz <= 0)
pgsz = 1 << 12;
return pgsz;
}
#if defined(__ia64__)
int __clone2(int (*__fn) (void *__arg), void *__child_stack_base,
size_t __child_stack_size, int __flags, void *__arg, ...);
#else
int clone(int (*fn)(void *), void *child_stack,
int flags, void *arg, ...
/* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
#endif
extern pid_t lxc_clone(int (*fn)(void *), void *arg, int flags);
#endif /* __LXC_UTILS_H */ #endif /* __LXC_UTILS_H */
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