From: Christian Brauner Date: Fri, 12 Jan 2018 16:06:42 +0000 (+0100) Subject: tools: move lxc-unshare to API symbols only X-Git-Tag: lxc-3.0.0.beta1~36^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d567a9a7e9c660ab821b26e45de7c31dc368348f;p=thirdparty%2Flxc.git tools: move lxc-unshare to API symbols only Closes #2073. Signed-off-by: Christian Brauner --- diff --git a/src/lxc/tools/lxc_unshare.c b/src/lxc/tools/lxc_unshare.c index 9e062a0ca..98143d662 100644 --- a/src/lxc/tools/lxc_unshare.c +++ b/src/lxc/tools/lxc_unshare.c @@ -20,30 +20,27 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "config.h" -#include +#define _GNU_SOURCE #include +#include #include #include -#include #include +#include #include +#include #include #include +#include +#include #include #include #include #include -#include -#include "caps.h" -#include "cgroup.h" -#include "error.h" -#include "log.h" -#include "namespace.h" -#include "network.h" -#include "utils.h" +#include "arguments.h" +#include "tool_utils.h" struct my_iflist { @@ -67,7 +64,7 @@ static void usage(char *cmd) static bool lookup_user(const char *optarg, uid_t *uid) { - char name[MAXPATHLEN]; + char name[TOOL_MAXPATHLEN]; struct passwd *pwent = NULL; if (!optarg || (optarg[0] == '\0')) @@ -147,11 +144,34 @@ static int do_start(void *arg) 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[]) { char *del; char **it, **args; - int opt, status; + int opt; int ret; char *namespaces = NULL; int flags = 0, daemonize = 0; @@ -284,7 +304,7 @@ int main(int argc, char *argv[]) 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) { close(start_arg.wait_fd); fprintf(stderr, "uid mapping failed\n"); @@ -301,19 +321,40 @@ int main(int argc, char *argv[]) if (my_iflist) { for (tmpif = my_iflist; tmpif; tmpif = tmpif->mi_next) { - if (lxc_netdev_move_by_name(tmpif->mi_ifname, pid, NULL) < 0) - fprintf(stderr,"Could not move interface %s into container %d: %s\n", tmpif->mi_ifname, pid, strerror(errno)); + pid_t pid; + + 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) exit(EXIT_SUCCESS); - if (waitpid(pid, &status, 0) < 0) { + if (wait_for_pid(pid) != 0) { fprintf(stderr, "failed to wait for '%d'\n", pid); exit(EXIT_FAILURE); } /* Call exit() directly on this function because it retuns an exit code. */ - exit(lxc_error_set_and_log(pid, status)); + exit(EXIT_SUCCESS); } diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c index 71b499659..7279b3d4c 100644 --- a/src/lxc/tools/tool_utils.c +++ b/src/lxc/tools/tool_utils.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,7 @@ #include +#include "arguments.h" #include "tool_utils.h" int lxc_fill_elevated_privileges(char *flaglist, int *flags) @@ -1131,3 +1133,64 @@ again: goto again; 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; +} diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h index 278402ab3..b93713714 100644 --- a/src/lxc/tools/tool_utils.h +++ b/src/lxc/tools/tool_utils.h @@ -176,4 +176,28 @@ extern ssize_t lxc_write_nointr(int fd, const void* buf, size_t count); 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 */