]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxccontainer: add container API function and structs for injecting a mount
authorLiza Tretyakova <elizabet.tretyakova@gmail.com>
Wed, 2 May 2018 08:07:58 +0000 (11:07 +0300)
committerChristian Brauner <christian.brauner@ubuntu.com>
Sun, 22 Jul 2018 13:25:16 +0000 (15:25 +0200)
Signed-off-by: Liza Tretyakova <elizabet.tretyakova@gmail.com>
src/lxc/lxccontainer.c
src/lxc/lxccontainer.h

index cd4891ab03f38260848e1eb6c385c48f24f83dab..b03d049ed65543d420a7fbae4e59f85f3fe1d687 100644 (file)
 #include <stdarg.h>
 #include <stdint.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <sys/file.h>
 #include <sys/mman.h>
 #include <sys/mount.h>
+#include <sys/stat.h>
 #include <sys/syscall.h>
 #include <sys/sysmacros.h>
 #include <sys/types.h>
@@ -460,6 +462,25 @@ static rettype fnname(struct lxc_container *c, t1 a1, t2 a2, t3 a3)        \
        return ret;                                                     \
 }
 
+#define WRAP_API_6(rettype, fnname, t1, t2, t3, t4, t5, t6)                            \
+static rettype fnname(struct lxc_container *c, t1 a1, t2 a2, t3 a3,    \
+                                               t4 a4, t5 a5, t6 a6)    \
+{                                                                      \
+       rettype ret;                                                    \
+       bool reset_config = false;                                      \
+                                                                       \
+       if (!current_config && c && c->lxc_conf) {                      \
+               current_config = c->lxc_conf;                           \
+               reset_config = true;                                    \
+       }                                                               \
+                                                                       \
+       ret = do_##fnname(c, a1, a2, a3, a4, a5, a6);                           \
+       if (reset_config)                                               \
+               current_config = NULL;                                  \
+                                                                       \
+       return ret;                                                     \
+}
+
 WRAP_API(bool, lxcapi_is_defined)
 
 static const char *do_lxcapi_state(struct lxc_container *c)
@@ -4893,6 +4914,119 @@ static bool do_lxcapi_restore(struct lxc_container *c, char *directory, bool ver
 
 WRAP_API_2(bool, lxcapi_restore, char *, bool)
 
+static int do_lxcapi_mount(struct lxc_container *c,
+                       const char *source, const char *target,
+                       const char *filesystemtype, unsigned long mountflags,
+                       const void *data, struct lxc_mount *mnt) {
+       char *suff, *sret;
+       char template[MAXPATHLEN], path[MAXPATHLEN];
+       pid_t pid, init_pid;
+       size_t len;
+       int ret = -1, fd = -EBADF;
+
+       if (!c || !c->lxc_conf) {
+               ERROR("Container or configuration is NULL");
+               return -EINVAL;
+       }
+
+       if (!c->lxc_conf->lxc_shmount.path_host) {
+               ERROR("Host path to shared mountpoint must be specified in the config\n");
+               return -EINVAL;
+       }
+       len = strlen(c->lxc_conf->lxc_shmount.path_host) + sizeof("/.lxcmount_XXXXXX") - 1;
+
+       ret = snprintf(template, len + 1, "%s/.lxcmount_XXXXXX", c->lxc_conf->lxc_shmount.path_host);
+       if (ret < 0 || (size_t)ret >= len + 1) {
+               SYSERROR("Error writing shmounts tempdir name");
+               goto out;
+       }
+
+       /* Create a temporary dir under the shared mountpoint */
+       sret = mkdtemp(template);
+       if (!sret) {
+               SYSERROR("Could not create shmounts temporary dir");
+               goto out;
+       }
+
+       /* Do the fork */
+       pid = fork();
+       if (pid < 0) {
+               SYSERROR("Could not fork");
+               goto out;
+       }
+
+       if (pid == 0) {
+               /* Do the mount */
+               ret = mount(source, template, filesystemtype, mountflags, data);
+               if (ret < 0) {
+                       SYSERROR("Failed to mount \"%s\" onto \"%s\"", source, template);
+                       _exit(EXIT_FAILURE);
+               }
+
+               init_pid = do_lxcapi_init_pid(c);
+               if (init_pid < 0) {
+                       ERROR("Failed to obtain container's init pid");
+                       _exit(EXIT_FAILURE);
+               }
+
+               /* Enter the container namespaces */
+               if (!lxc_list_empty(&c->lxc_conf->id_map)) {
+                       if (!switch_to_ns(init_pid, "user")){
+                               ERROR("Failed to enter user namespace");
+                               _exit(EXIT_FAILURE);
+                       }
+               }
+               if (!switch_to_ns(init_pid, "mnt")) {
+                       ERROR("Failed to enter mount namespace");
+                       _exit(EXIT_FAILURE);
+               }
+
+               suff = strrchr(template, '/');
+               if (!suff)
+                       _exit(EXIT_FAILURE);
+
+               len = strlen(c->lxc_conf->lxc_shmount.path_cont) + sizeof("/.lxcmount_XXXXXX") - 1;
+               ret = snprintf(path, len + 1, "%s%s", c->lxc_conf->lxc_shmount.path_cont, suff);
+               if (ret < 0 || (size_t)ret >= len + 1) {
+                       SYSERROR("Error writing container mountpoint name");
+                       _exit(EXIT_FAILURE);
+               }
+
+               ret = mkdir_p(target, 0700);
+               if (ret < 0) {
+                       ERROR("Failed to create container temp mountpoint");
+                       _exit(EXIT_FAILURE);
+               }
+
+               ret = mount(path, target, NULL, MS_REC | MS_MOVE, NULL);
+               if (ret < 0) {
+                       SYSERROR("Failed to move the mount from \"%s\" to \"%s\"", path, target);
+                       _exit(EXIT_FAILURE);
+               }
+
+               _exit(EXIT_SUCCESS);
+       }
+
+       ret = wait_for_pid(pid);
+       if (ret < 0) {
+               SYSERROR("Wait for the child with pid %ld failed", (long) pid);
+               goto out;
+       }
+
+       ret = 0;
+
+       (void)umount2(template, MNT_DETACH);
+       (void)unlink(template);
+
+out:
+       if (fd >= 0)
+               close(fd);
+       return ret;
+}
+
+WRAP_API_6(int, lxcapi_mount, const char *, const char *, const char *,
+          unsigned long, const void *, struct lxc_mount*)
+
 static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...)
 {
        va_list ap;
@@ -5045,6 +5179,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
        c->restore = lxcapi_restore;
        c->migrate = lxcapi_migrate;
        c->console_log = lxcapi_console_log;
+       c->mount = lxcapi_mount;
 
        return c;
 
index 7bbac2f06c7b97ff09ca32332d14d68f6f61fcc5..c61a1b840d2bc53b4bab82a878a19c6614d50639 100644 (file)
@@ -42,6 +42,7 @@ extern "C" {
 #define LXC_CLONE_MAXFLAGS        (1 << 5) /*!< Number of \c LXC_CLONE_* flags */
 #define LXC_CREATE_QUIET          (1 << 0) /*!< Redirect \c stdin to \c /dev/zero and \c stdout and \c stderr to \c /dev/null */
 #define LXC_CREATE_MAXFLAGS       (1 << 1) /*!< Number of \c LXC_CREATE* flags */
+#define LXC_MOUNT_API_V1                  1
 
 struct bdev_specs;
 
@@ -53,6 +54,10 @@ struct migrate_opts;
 
 struct lxc_console_log;
 
+struct lxc_mount {
+       int version;
+};
+
 /*!
  * An LXC container.
  *
@@ -846,6 +851,14 @@ struct lxc_container {
         * \return \c true if the container was rebooted successfully, else \c false.
         */
        bool (*reboot2)(struct lxc_container *c, int timeout);
+
+       /*!
+        * \brief Mount the host's path `source` onto the container's path `target`.
+        */
+       int (*mount)(struct lxc_container *c,
+                                const char *source, const char *target,
+                                const char *filesystemtype, unsigned long mountflags,
+                                const void *data, struct lxc_mount *mnt);
 };
 
 /*!