On Mon, Nov 02, 2015 at 03:12:02PM +0000, Serge Hallyn wrote:
> Quoting Christian Brauner (christianvanbrau...@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_ovl_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_ovl_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 <christianvanbrau...@gmail.com>
> > ---
> >  src/lxc/lxccontainer.c | 98 
> > ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 98 insertions(+)
> > 
> > diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> > index 42e23e7..7150103 100644
> > --- a/src/lxc/lxccontainer.c
> > +++ b/src/lxc/lxccontainer.c
> > @@ -2894,6 +2894,100 @@ static int create_file_dirname(char *path, struct 
> > lxc_conf *conf)
> >     return ret;
> >  }
> >  
> > +/* When we clone a container with overlay lxc.mount.entry entries we need 
> > to
> > +*  update absolute paths for upper- and workdir. This update is done in two
> > +*  locations: lxc_conf->unexpanded_config and lxc_conf->mount_list. Both 
> > updates
> > +*  are done independent of each other since lxc_conf->mountlist may 
> > container
> > +*  more mount entries (e.g. from other included files) than
> > +*  lxc_conf->unexpanded_config . */
> > +static int update_ovl_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);
> > +
> > +   /* We have to update lxc_conf->unexpanded_config separately from
> > +   *  lxc_conf->mount_list. */
> > +   for (i = 0; i < sizeof(ovl_dirs) / sizeof(ovl_dirs[0]); i++) {
> > +           if (!clone_update_unexp_ovl_paths(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;
> > +
> 
> The rest of this block needs to be un-indented by one level.
> 
> > +                   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);
> 
> Don't you want old_work replaced even if old_upper wasn't found?
> 
> (or are we requiring limitations on the old upper that guarantee that
> won't happen?)
I don't think we currently are. We should:

        if (strstr(mnt_entry, old_work)) {
                if (tmp_mnt_entry)
                        new_mnt_entry = lxc_string_replace(old_work, new_work, 
tmp_mnt_entry);
                else (tmp_mnt_entry)
                        new_mnt_entry = lxc_string_replace(old_work, new_work, 
mnt_entry);
        }
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to