[lxc-devel] [PATCH] aufs: support multiple lower layers
Christian Brauner
christianvanbrauner at gmail.com
Tue Jan 26 20:07:18 UTC 2016
On Tue, Jan 26, 2016 at 06:51:04PM +0000, Serge Hallyn wrote:
> Quoting Christian Brauner (christianvanbrauner at gmail.com):
> > Do it in a safe way by using strstr() to check for the substring ":/" should
> > ':' be part of a pathname.
> >
> > Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
>
> Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>
>
> > ---
> > src/lxc/bdev/lxcaufs.c | 14 ++++++++++----
> > 1 file changed, 10 insertions(+), 4 deletions(-)
> >
> > diff --git a/src/lxc/bdev/lxcaufs.c b/src/lxc/bdev/lxcaufs.c
> > index a5c34aa..408f6a3 100644
> > --- a/src/lxc/bdev/lxcaufs.c
> > +++ b/src/lxc/bdev/lxcaufs.c
> > @@ -234,7 +234,7 @@ int aufs_detect(const char *path)
> >
> > int aufs_mount(struct bdev *bdev)
> > {
> > - char *options, *dup, *lower, *upper;
> > + char *tmp, *options, *dup, *lower, *upper;
> > int len;
> > unsigned long mntflags;
> > char *mntdata;
> > @@ -250,9 +250,15 @@ int aufs_mount(struct bdev *bdev)
> > // mount -t aufs -obr=${upper}=rw:${lower}=ro lower dest
> > dup = alloca(strlen(bdev->src)+1);
> > strcpy(dup, bdev->src);
> > - if (!(lower = strchr(dup, ':')))
> > - return -22;
> > - if (!(upper = strchr(++lower, ':')))
> > + /* support multiple lower layers */
> > + if (!(lower = strstr(dup, ":/")))
> > + return -22;
> > + lower++;
> > + upper = lower;
> > + while ((tmp = strstr(++upper, ":/"))) {
> > + upper = tmp;
> > + }
> > + if (--upper == lower)
> > return -22;
>
> Hm, so if lower = /some/path:/other/path, strstr will result in upper =
> ':', then you check --upper and up with upper pointing to the last 'h'
> in /some/path. Then you set that to \0. I'm probably off since this
> would've failed for you immediately, but why am I wrong?
Hm, here is how I understood it:
**Case A: "Everything as expected"**
lxc.rootfs = aufs:/lower1:/lower2:/upper
if (!(lower = strchr(dup, ':')))
return -22;
now we have
// lower = :/lower1:/lower2:/upper
we do
lower++;
to move forward and not have strstr() do the work from the beginning again.
Now we have
// lower = /lower1:/lower2:/upper
we set
upper = lower;
and have
// upper = lower = /lower1:/lower2:/upper
we do
while ((tmp = strstr(++upper, ":/"))) {
upper = tmp;
}
and end up with:
// upper = /upper
now we do
if (--upper == lower)
return -22;
and as you correctly noticed we compare
// :/upper
with
// /lower1:/lower2
But that is by design: For a case where we find at least two path entries this
test really does not serve any purpose at all. Moving back or forth one byte
does not alter the fact that we found two different entries. It becomes import
for a case where we fail to find a second path entry.
Now we set:
*upper = '\0';
which is at
// :/upper
and hence "split" the rootfs string
// aufs:/lower1:/lower2:/upper
into
// aufs:/lower1:/lower2\0/upper
Now
lower
points to
// /lower1:/lower2\0
and upper moves one final byte forward
upper++;
and we get
// /upper
voila.
**Case B: "Missing upper or lower"**
But now imagine doing the same stuff when we have:
lxc.rootfs = aufs:/a
abbreviating a bit we have:
if (!(lower = strchr(dup, ':')))
return -22;
// lower = :/a
lower++;
// lower = /a
upper = lower;
// upper = lower = /a
while ((tmp = strstr(++upper, ":/"))) {
upper = tmp;
}
// upper = a
but now we do
if (--upper == lower)
return -22;
and now we compare
// /a
correctly with
// /a
and error out.
More information about the lxc-devel
mailing list