[prev in list] [next in list] [prev in thread] [next in thread] 

List:       lxc-devel
Subject:    [lxc-devel] Fwd: Re: [PATCH 2/2 v2] Update absolute paths for overlay and aufs mounts
From:       Christian Brauner <christianvanbrauner () gmail ! com>
Date:       2015-10-30 15:30:55
Message-ID: CALNVzyAvm72S3wkoGb6ROHUjQSXpgn-XYnbk2WmPukY=gG8e7g () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


---------- Forwarded message ----------
From: "Christian Brauner" <christianvanbrauner@gmail.com>
Date: Oct 30, 2015 4:27 PM
Subject: Re: [PATCH 2/2 v2] Update absolute paths for overlay and aufs
mounts
To: "Serge E. Hallyn" <serge.hallyn@ubuntu.com>
Cc: "lxc-dev" <lxc-devel@lists.linuxcontainers.org>

>
> On Oct 30, 2015 4:22 PM, "Serge Hallyn" <serge.hallyn@ubuntu.com> wrote:
> >
> > Quoting Christian Brauner (christianvanbrauner@gmail.com):
> > > When using overlay and aufs mounts with lxc.mount.entry users have to
specify
> > > absolute paths for upperdir and workdir which will then get created
> > > automatically by mount_entry_create_overlay_dirs() and
> > > mount_entry_create_aufs_dirs() in conf.c. When we clone a container
with
> > > overlay or aufs lxc.mount.entry entries we need to update these
absolute paths.
> > > In order to do this we add the function
update_union_mount_entry_paths() in
> > > lxccontainer.c. The function updates the mounts in two locations:
> > >
> > >         1) lxc_conf->mount_list
> > >
> > > and
> > >
> > >         2) lxc_conf->unexpanded_config (by calling
clone_update_unexp_ovl_dir())
> > >
> > > If we were to only update 2) we would end up with wrong upperdir and
workdir
> > > mounts as the absolute paths would still point to the container that
serves as
> > > the base for the clone. If we were to only update 1) we would end up
with wrong
> > > upperdir and workdir lxc.mount.entry entries in the clone's config as
the
> > > absolute paths in upperdir and workdir would still point to the
container that
> > > serves as the base for the clone. Updating both will get the job done.
> > >
> > > NOTE: This function does not sanitize paths apart from removing
trailing
> > > slashes. (So when a user specifies //home//someone/// it will be
cleaned to
> > > //home//someone. This is the minimal path cleansing which is also
done by
> > > lxc_container_new().) But the mount_entry_create_overlay_dirs() and
> > > mount_entry_create_aufs_dirs() functions both try to be extremely
strict about
> > > when to create upperdirs and workdirs. They will only accept
sanitized paths,
> > > i.e. they require /home/someone. I think this is a (safety) virtue
and we
> > > should consider sanitizing paths in general. In short:
> > > update_union_mount_entry_paths() does update all absolute paths to
the new
> > > container but mount_entry_create_overlay_dirs() and
> > > mount_entry_create_aufs_dirs() will still refuse to create upperdir
and workdir
> > > when the updated path is unclean. This happens easily when e.g. a
user calls
> > > lxc-clone -o OLD -n NEW -P //home//chb///.
> > >
> > > Signed-off-by: Christian Brauner <christianvanbrauner@gmail.com>
> >
> > Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
> >
> > > ---
> > >  src/lxc/lxccontainer.c | 97
++++++++++++++++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 97 insertions(+)
> > >
> > > diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> > > index 42e23e7..8edf6a2 100644
> > > --- a/src/lxc/lxccontainer.c
> > > +++ b/src/lxc/lxccontainer.c
> > > @@ -2894,6 +2894,99 @@ static int create_file_dirname(char *path,
struct lxc_conf *conf)
> > >       return ret;
> > >  }
> > >
> > > +/* When we clone a container with overlay or aufs lxc.mount.entry
entries we
> > > +*  need to update these absolute paths. In order to do this we add
the function
> > > +*  update_union_mount_entry_paths() in lxccontainer.c. The function
operates on
> > > +*  c->lxc_conf->unexpanded_config instead of the intuitively
plausible
> > > +*  c->lxc_conf->mount_list because the latter also contains mounts
from other
> > > +*  files as well as generic mounts. */
> > > +static int update_union_mount_entry_paths(struct lxc_conf *lxc_conf,
> > > +                                       const char *lxc_path,
> > > +                                       const char *lxc_name,
> > > +                                       const char *newpath,
> > > +                                       const char *newname)
> > > +{
> > > +     char new_upper[MAXPATHLEN];
> > > +     char new_work[MAXPATHLEN];
> > > +     char old_upper[MAXPATHLEN];
> > > +     char old_work[MAXPATHLEN];
> > > +     char *cleanpath = NULL;
> > > +     int i;
> > > +     int fret = -1;
> > > +     int ret = 0;
> > > +     struct lxc_list *iterator;
> > > +     const char *ovl_dirs[] = {"br", "upperdir", "workdir"};
> > > +
> > > +     cleanpath = strdup(newpath);
> > > +     if (!cleanpath)
> > > +             goto err;
> > > +
> > > +     remove_trailing_slashes(cleanpath);
> > > +
> >
> > Would be wortha comment here saying "we have to update the unexpanded
> > configuration separately from the expanded one."

I can insert it, add your Acked-by line to the cover letter and leave a
short reminder in the cover letter that I only inserted a comment per your
request so you know what's going on. Ok?

> >
> > > +     for (i = 0; i < sizeof(ovl_dirs) / sizeof(ovl_dirs[0]); i++) {
> > > +             if (!clone_update_unexp_ovl_dir(lxc_conf, lxc_path,
newpath,
> > > +                                             lxc_name, newname,
ovl_dirs[i]))
> > > +                     goto err;
> > > +     }
> > > +
> > > +     ret = snprintf(old_work, MAXPATHLEN, "workdir=%s/%s", lxc_path,
lxc_name);
> > > +     if (ret < 0 || ret >= MAXPATHLEN)
> > > +             goto err;
> > > +
> > > +     ret = snprintf(new_work, MAXPATHLEN, "workdir=%s/%s",
cleanpath, newname);
> > > +     if (ret < 0 || ret >= MAXPATHLEN)
> > > +             goto err;
> > > +
> > > +     lxc_list_for_each(iterator, &lxc_conf->mount_list) {
> > > +             char *mnt_entry = NULL;
> > > +             char *new_mnt_entry = NULL;
> > > +             char *tmp = NULL;
> > > +             char *tmp_mnt_entry = NULL;
> > > +             mnt_entry = iterator->elem;
> > > +
> > > +             if (strstr(mnt_entry, "overlay"))
> > > +                     tmp = "upperdir";
> > > +             else if (strstr(mnt_entry, "aufs"))
> > > +                     tmp = "br";
> > > +
> > > +             if (!tmp)
> > > +                     continue;
> > > +
> > > +                     ret = snprintf(old_upper, MAXPATHLEN,
"%s=%s/%s", tmp, lxc_path, lxc_name);
> > > +                     if (ret < 0 || ret >= MAXPATHLEN)
> > > +                             goto err;
> > > +
> > > +                     ret = snprintf(new_upper, MAXPATHLEN,
"%s=%s/%s", tmp, cleanpath, newname);
> > > +                     if (ret < 0 || ret >= MAXPATHLEN)
> > > +                             goto err;
> > > +
> > > +                     if (strstr(mnt_entry, old_upper)) {
> > > +                             tmp_mnt_entry =
lxc_string_replace(old_upper, new_upper, mnt_entry);
> > > +                     }
> > > +
> > > +                     if (strstr(mnt_entry, old_work)) {
> > > +                             if (tmp_mnt_entry)
> > > +                                     new_mnt_entry =
lxc_string_replace(old_work, new_work, tmp_mnt_entry);
> > > +                     }
> > > +
> > > +                     if (new_mnt_entry) {
> > > +                             free(iterator->elem);
> > > +                             iterator->elem = strdup(new_mnt_entry);
> > > +                     } else if (tmp_mnt_entry) {
> > > +                             free(iterator->elem);
> > > +                             iterator->elem = strdup(tmp_mnt_entry);
> > > +                     }
> > > +
> > > +                     free(new_mnt_entry);
> > > +                     free(tmp_mnt_entry);
> > > +     }
> > > +
> > > +     fret = 0;
> > > +err:
> > > +     free(cleanpath);
> > > +     return fret;
> > > +}
> > > +
> > >  static struct lxc_container *do_lxcapi_clone(struct lxc_container
*c, const char *newname,
> > >               const char *lxcpath, int flags,
> > >               const char *bdevtype, const char *bdevdata, uint64_t
newsize,
> > > @@ -3009,6 +3102,10 @@ static struct lxc_container
*do_lxcapi_clone(struct lxc_container *c, const char
> > >               }
> > >       }
> > >
> > > +     // update absolute paths for union mount directories
> > > +     if (update_union_mount_entry_paths(c2->lxc_conf,
c->config_path, c->name, lxcpath, newname) < 0)
> > > +             goto out;
> > > +
> > >       // We've now successfully created c2's storage, so clear it out
if we
> > >       // fail after this
> > >       storage_copied = 1;
> > > --
> > > 2.6.2
> > >

[Attachment #5 (text/html)]

<p dir="ltr"><br>
---------- Forwarded message ----------<br>
From: &quot;Christian Brauner&quot; &lt;<a \
                href="mailto:christianvanbrauner@gmail.com">christianvanbrauner@gmail.com</a>&gt;<br>
                
Date: Oct 30, 2015 4:27 PM<br>
Subject: Re: [PATCH 2/2 v2] Update absolute paths for overlay and aufs mounts<br>
To: &quot;Serge E. Hallyn&quot; &lt;<a \
                href="mailto:serge.hallyn@ubuntu.com">serge.hallyn@ubuntu.com</a>&gt;<br>
                
Cc: &quot;lxc-dev&quot; &lt;<a \
href="mailto:lxc-devel@lists.linuxcontainers.org">lxc-devel@lists.linuxcontainers.org</a>&gt;</p>
 <p dir="ltr">&gt;<br>
&gt; On Oct 30, 2015 4:22 PM, &quot;Serge Hallyn&quot; &lt;<a \
href="mailto:serge.hallyn@ubuntu.com">serge.hallyn@ubuntu.com</a>&gt; wrote:<br> &gt; \
&gt;<br> &gt; &gt; Quoting Christian Brauner (<a \
href="mailto:christianvanbrauner@gmail.com">christianvanbrauner@gmail.com</a>):<br> \
&gt; &gt; &gt; When using overlay and aufs mounts with lxc.mount.entry users have to \
specify<br> &gt; &gt; &gt; absolute paths for upperdir and workdir which will then \
get created<br> &gt; &gt; &gt; automatically by mount_entry_create_overlay_dirs() \
and<br> &gt; &gt; &gt; mount_entry_create_aufs_dirs() in conf.c. When we clone a \
container with<br> &gt; &gt; &gt; overlay or aufs lxc.mount.entry entries we need to \
update these absolute paths.<br> &gt; &gt; &gt; In order to do this we add the \
function update_union_mount_entry_paths() in<br> &gt; &gt; &gt; lxccontainer.c. The \
function updates the mounts in two locations:<br> &gt; &gt; &gt;<br>
&gt; &gt; &gt;              1) lxc_conf-&gt;mount_list<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; and<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;              2) lxc_conf-&gt;unexpanded_config (by calling \
clone_update_unexp_ovl_dir())<br> &gt; &gt; &gt;<br>
&gt; &gt; &gt; If we were to only update 2) we would end up with wrong upperdir and \
workdir<br> &gt; &gt; &gt; mounts as the absolute paths would still point to the \
container that serves as<br> &gt; &gt; &gt; the base for the clone. If we were to \
only update 1) we would end up with wrong<br> &gt; &gt; &gt; upperdir and workdir \
lxc.mount.entry entries in the clone&#39;s config as the<br> &gt; &gt; &gt; absolute \
paths in upperdir and workdir would still point to the container that<br> &gt; &gt; \
&gt; serves as the base for the clone. Updating both will get the job done.<br> &gt; \
&gt; &gt;<br> &gt; &gt; &gt; NOTE: This function does not sanitize paths apart from \
removing trailing<br> &gt; &gt; &gt; slashes. (So when a user specifies \
//home//someone/// it will be cleaned to<br> &gt; &gt; &gt; //home//someone. This is \
the minimal path cleansing which is also done by<br> &gt; &gt; &gt; \
lxc_container_new().) But the mount_entry_create_overlay_dirs() and<br> &gt; &gt; \
&gt; mount_entry_create_aufs_dirs() functions both try to be extremely strict \
about<br> &gt; &gt; &gt; when to create upperdirs and workdirs. They will only accept \
sanitized paths,<br> &gt; &gt; &gt; i.e. they require /home/someone. I think this is \
a (safety) virtue and we<br> &gt; &gt; &gt; should consider sanitizing paths in \
general. In short:<br> &gt; &gt; &gt; update_union_mount_entry_paths() does update \
all absolute paths to the new<br> &gt; &gt; &gt; container but \
mount_entry_create_overlay_dirs() and<br> &gt; &gt; &gt; \
mount_entry_create_aufs_dirs() will still refuse to create upperdir and workdir<br> \
&gt; &gt; &gt; when the updated path is unclean. This happens easily when e.g. a user \
calls<br> &gt; &gt; &gt; lxc-clone -o OLD -n NEW -P //home//chb///.<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; Signed-off-by: Christian Brauner &lt;<a \
href="mailto:christianvanbrauner@gmail.com">christianvanbrauner@gmail.com</a>&gt;<br> \
&gt; &gt;<br> &gt; &gt; Acked-by: Serge E. Hallyn &lt;<a \
href="mailto:serge.hallyn@ubuntu.com">serge.hallyn@ubuntu.com</a>&gt;<br> &gt; \
&gt;<br> &gt; &gt; &gt; ---<br>
&gt; &gt; &gt;   src/lxc/lxccontainer.c | 97 \
++++++++++++++++++++++++++++++++++++++++++++++++++<br> &gt; &gt; &gt;   1 file \
changed, 97 insertions(+)<br> &gt; &gt; &gt;<br>
&gt; &gt; &gt; diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c<br>
&gt; &gt; &gt; index 42e23e7..8edf6a2 100644<br>
&gt; &gt; &gt; --- a/src/lxc/lxccontainer.c<br>
&gt; &gt; &gt; +++ b/src/lxc/lxccontainer.c<br>
&gt; &gt; &gt; @@ -2894,6 +2894,99 @@ static int create_file_dirname(char *path, \
struct lxc_conf *conf)<br> &gt; &gt; &gt;           return ret;<br>
&gt; &gt; &gt;   }<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; +/* When we clone a container with overlay or aufs lxc.mount.entry \
entries we<br> &gt; &gt; &gt; +*   need to update these absolute paths. In order to \
do this we add the function<br> &gt; &gt; &gt; +*   update_union_mount_entry_paths() \
in lxccontainer.c. The function operates on<br> &gt; &gt; &gt; +*   \
c-&gt;lxc_conf-&gt;unexpanded_config instead of the intuitively plausible<br> &gt; \
&gt; &gt; +*   c-&gt;lxc_conf-&gt;mount_list because the latter also contains mounts \
from other<br> &gt; &gt; &gt; +*   files as well as generic mounts. */<br>
&gt; &gt; &gt; +static int update_union_mount_entry_paths(struct lxc_conf \
*lxc_conf,<br> &gt; &gt; &gt; +                                                       \
const char *lxc_path,<br> &gt; &gt; &gt; +                                            \
const char *lxc_name,<br> &gt; &gt; &gt; +                                            \
const char *newpath,<br> &gt; &gt; &gt; +                                             \
const char *newname)<br> &gt; &gt; &gt; +{<br>
&gt; &gt; &gt; +        char new_upper[MAXPATHLEN];<br>
&gt; &gt; &gt; +        char new_work[MAXPATHLEN];<br>
&gt; &gt; &gt; +        char old_upper[MAXPATHLEN];<br>
&gt; &gt; &gt; +        char old_work[MAXPATHLEN];<br>
&gt; &gt; &gt; +        char *cleanpath = NULL;<br>
&gt; &gt; &gt; +        int i;<br>
&gt; &gt; &gt; +        int fret = -1;<br>
&gt; &gt; &gt; +        int ret = 0;<br>
&gt; &gt; &gt; +        struct lxc_list *iterator;<br>
&gt; &gt; &gt; +        const char *ovl_dirs[] = {&quot;br&quot;, \
&quot;upperdir&quot;, &quot;workdir&quot;};<br> &gt; &gt; &gt; +<br>
&gt; &gt; &gt; +        cleanpath = strdup(newpath);<br>
&gt; &gt; &gt; +        if (!cleanpath)<br>
&gt; &gt; &gt; +                    goto err;<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +        remove_trailing_slashes(cleanpath);<br>
&gt; &gt; &gt; +<br>
&gt; &gt;<br>
&gt; &gt; Would be wortha comment here saying &quot;we have to update the \
unexpanded<br> &gt; &gt; configuration separately from the expanded one.&quot;</p>
<p dir="ltr">I can insert it, add your Acked-by line to the cover letter and leave a \
short reminder in the cover letter that I only inserted a comment per your request so \
you know what&#39;s going on. Ok?</p> <p dir="ltr">&gt; &gt;<br>
&gt; &gt; &gt; +        for (i = 0; i &lt; sizeof(ovl_dirs) / sizeof(ovl_dirs[0]); \
i++) {<br> &gt; &gt; &gt; +                    if \
(!clone_update_unexp_ovl_dir(lxc_conf, lxc_path, newpath,<br> &gt; &gt; &gt; +        \
lxc_name, newname, ovl_dirs[i]))<br> &gt; &gt; &gt; +                                \
goto err;<br> &gt; &gt; &gt; +        }<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +        ret = snprintf(old_work, MAXPATHLEN, \
&quot;workdir=%s/%s&quot;, lxc_path, lxc_name);<br> &gt; &gt; &gt; +        if (ret \
&lt; 0 || ret &gt;= MAXPATHLEN)<br> &gt; &gt; &gt; +                    goto err;<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +        ret = snprintf(new_work, MAXPATHLEN, \
&quot;workdir=%s/%s&quot;, cleanpath, newname);<br> &gt; &gt; &gt; +        if (ret \
&lt; 0 || ret &gt;= MAXPATHLEN)<br> &gt; &gt; &gt; +                    goto err;<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +        lxc_list_for_each(iterator, &amp;lxc_conf-&gt;mount_list) \
{<br> &gt; &gt; &gt; +                    char *mnt_entry = NULL;<br>
&gt; &gt; &gt; +                    char *new_mnt_entry = NULL;<br>
&gt; &gt; &gt; +                    char *tmp = NULL;<br>
&gt; &gt; &gt; +                    char *tmp_mnt_entry = NULL;<br>
&gt; &gt; &gt; +                    mnt_entry = iterator-&gt;elem;<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +                    if (strstr(mnt_entry, &quot;overlay&quot;))<br>
&gt; &gt; &gt; +                                tmp = &quot;upperdir&quot;;<br>
&gt; &gt; &gt; +                    else if (strstr(mnt_entry, &quot;aufs&quot;))<br>
&gt; &gt; &gt; +                                tmp = &quot;br&quot;;<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +                    if (!tmp)<br>
&gt; &gt; &gt; +                                continue;<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +                                ret = snprintf(old_upper, MAXPATHLEN, \
&quot;%s=%s/%s&quot;, tmp, lxc_path, lxc_name);<br> &gt; &gt; &gt; +                  \
if (ret &lt; 0 || ret &gt;= MAXPATHLEN)<br> &gt; &gt; &gt; +                          \
goto err;<br> &gt; &gt; &gt; +<br>
&gt; &gt; &gt; +                                ret = snprintf(new_upper, MAXPATHLEN, \
&quot;%s=%s/%s&quot;, tmp, cleanpath, newname);<br> &gt; &gt; &gt; +                  \
if (ret &lt; 0 || ret &gt;= MAXPATHLEN)<br> &gt; &gt; &gt; +                          \
goto err;<br> &gt; &gt; &gt; +<br>
&gt; &gt; &gt; +                                if (strstr(mnt_entry, old_upper)) \
{<br> &gt; &gt; &gt; +                                            tmp_mnt_entry = \
lxc_string_replace(old_upper, new_upper, mnt_entry);<br> &gt; &gt; &gt; +             \
}<br> &gt; &gt; &gt; +<br>
&gt; &gt; &gt; +                                if (strstr(mnt_entry, old_work)) \
{<br> &gt; &gt; &gt; +                                            if \
(tmp_mnt_entry)<br> &gt; &gt; &gt; +                                                  \
new_mnt_entry = lxc_string_replace(old_work, new_work, tmp_mnt_entry);<br> &gt; &gt; \
&gt; +                                }<br> &gt; &gt; &gt; +<br>
&gt; &gt; &gt; +                                if (new_mnt_entry) {<br>
&gt; &gt; &gt; +                                            \
free(iterator-&gt;elem);<br> &gt; &gt; &gt; +                                         \
iterator-&gt;elem = strdup(new_mnt_entry);<br> &gt; &gt; &gt; +                       \
} else if (tmp_mnt_entry) {<br> &gt; &gt; &gt; +                                      \
free(iterator-&gt;elem);<br> &gt; &gt; &gt; +                                         \
iterator-&gt;elem = strdup(tmp_mnt_entry);<br> &gt; &gt; &gt; +                       \
}<br> &gt; &gt; &gt; +<br>
&gt; &gt; &gt; +                                free(new_mnt_entry);<br>
&gt; &gt; &gt; +                                free(tmp_mnt_entry);<br>
&gt; &gt; &gt; +        }<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +        fret = 0;<br>
&gt; &gt; &gt; +err:<br>
&gt; &gt; &gt; +        free(cleanpath);<br>
&gt; &gt; &gt; +        return fret;<br>
&gt; &gt; &gt; +}<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt;   static struct lxc_container *do_lxcapi_clone(struct lxc_container \
*c, const char *newname,<br> &gt; &gt; &gt;                       const char \
*lxcpath, int flags,<br> &gt; &gt; &gt;                       const char *bdevtype, \
const char *bdevdata, uint64_t newsize,<br> &gt; &gt; &gt; @@ -3009,6 +3102,10 @@ \
static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char<br> \
&gt; &gt; &gt;                       }<br> &gt; &gt; &gt;           }<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; +        // update absolute paths for union mount directories<br>
&gt; &gt; &gt; +        if (update_union_mount_entry_paths(c2-&gt;lxc_conf, \
c-&gt;config_path, c-&gt;name, lxcpath, newname) &lt; 0)<br> &gt; &gt; &gt; +         \
goto out;<br> &gt; &gt; &gt; +<br>
&gt; &gt; &gt;           // We&#39;ve now successfully created c2&#39;s storage, so \
clear it out if we<br> &gt; &gt; &gt;           // fail after this<br>
&gt; &gt; &gt;           storage_copied = 1;<br>
&gt; &gt; &gt; --<br>
&gt; &gt; &gt; 2.6.2<br>
&gt; &gt; &gt;<br>
</p>


[Attachment #6 (text/plain)]

_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic