* 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 <stdio.h>
+#define _GNU_SOURCE
#include <errno.h>
+#include <fcntl.h>
#include <getopt.h>
#include <libgen.h>
-#include <netinet/in.h>
#include <pwd.h>
+#include <sched.h>
#include <signal.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <netinet/in.h>
+#include <unistd.h>
#include <sys/eventfd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <unistd.h>
-#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
{
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'))
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;
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");
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);
}
#include <strings.h>
#include <unistd.h>
#include <linux/sched.h>
+#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <lxc/lxccontainer.h>
+#include "arguments.h"
#include "tool_utils.h"
int lxc_fill_elevated_privileges(char *flaglist, int *flags)
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;
+}
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 */