mntns: rework validation to support non-root shared bind-mounts (v2)

A problem which is solved in this path is that some children can be
unaccessiable (unvisiable) for non-root bind-mounts

root	mount point
-------------------
/	/a (shared:1)
/	/a/x
/	/a/x/y
/	/a/z
/x	/b (shared:1)
/	/b/y

/b is a non-root bind-mount of /a
/y is visiable to both mounts
/z is vidiable only for /a

Before this patch we checked that the set of children is the same for
all mount in a shared group. Now we check that a visiable set of mounts
is the same for all mounts in a shared group.

Now we take the next mount in the shared group, which is wider or equal
to current and compare children between them.

Before this patch validate_shared(m) validates the m->parent mount.
Now it validates the "m" mount. So you can find following lines in the
patch:
-               if (m->parent->shared_id && validate_shared(m))
+               if (m->shared_id && validate_shared(m))

We doesn't support shared mounts with different set of children.
Here is an example of such case can be created:
mount tmpfs a /a
mount --make-shared /a
mkdir /a/b
mount tmpfs b /a/b
mount --bind /a /c

In this case /c doesn't have the /b child. To support such cases,
we need to sort all shared mounts accoding with a set of children.

v2: If root is equal to "/", its len should be zero. We expect that the
last symbol in a path is not "/".

Signed-off-by: Andrey Vagin <avagin@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
mount: Add helper to search for widest shared peer

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Acked-by: Andrew Vagin <avagin@parallels.com>
mount: Add helper for path length calculations

The path lenght is zero for the "/" one and strlen(path)
for all the others. This is done so to make it possible
to use this length to get tail-paths: if path_1 starts
with path_2 and both are absolute, then

   path_1 + path_length(path_2)

would give the tail of the tail of path_1 relative to
path_2 even if the path_2 is just "/".

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Acked-by: Andrew Vagin <avagin@parallels.com>
mount: Rename paths' lengths to reflect whose lengths they are

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Acked-by: Andrew Vagin <avagin@parallels.com>
mount: Move some variables out of search loop

These are constant for given m, so calculate them outside
of the loop. Also rename them to reflect what they are.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Acked-by: Andrew Vagin <avagin@parallels.com>
mount: Use issubpath() when checking for submount visibility

When we check whether a submount of a mount is visible in another
mount (shared peer of the latter), we can and should use the new
issubpath helper.

Should because the used strncmp may scan beyond ct_mpnt_rpath if
its length is smaller (no checks for this in the code).

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Acked-by: Andrew Vagin <avagin@parallels.com>
mount: Use pre-calculated ct->mountpoint + t_mpnt_l value

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Acked-by: Andrew Vagin <avagin@parallels.com>
mount: Sanitize the path recalculation between submounts

Do paths conversions and checks step-by-step and add many comments
what we do in each step and why.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Acked-by: Andrew Vagin <avagin@parallels.com>
mount: Add helper for searching for shared peer

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Acked-by: Andrew Vagin <avagin@parallels.com>
mount: Remove the len variable

And use the expression for it, it's quite short. This
makes the amount of variables in the code fit into brains.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Acked-by: Andrew Vagin <avagin@parallels.com>
mount: add the mnt_roots mount in the mount tree on restore

Currently we connect roots of sub-namespaces to the root of the root
mount namespace. And we get problems, if the root of the root mntns is
shared, because all children of a shared mount must be propagated to
other mounts in this group.

Actually we mount tmpfs in mnt_roots and here is nothing wrong to add it
in a tree.

Signed-off-by: Andrey Vagin <avagin@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
mount: rework can_mount_now() to support bind-mounts of shared mounts

Fedora bind-mounts a part of the root mount to itself. Currently we
don't allow to mount children of a shared mount, if other mount from
this shared group are not mounted.

This patch adds an exclusion for cases, when a child has the same
group. We allow to mount a child, if wider mounts are mounted.

Signed-off-by: Andrey Vagin <avagin@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
zdtm: add a test to check non-root shared bind-mounts

Here is an example from a fedora container:
65 64 252:0 /vz/private/1 / rw,relatime shared:29 - ext4 /dev/mapper/centos_pcs-root rw,data=ordered
77 65 252:0 /vz/private/1/var/tmp/systemd-httpd.service-XLnJPNc/tmp /var/tmp rw,relatime shared:41 - ext4 /dev/mapper/centos_pcs-root rw,data=ordered

We can see non-root shared mount, which is mounted to the root
mount from the same shared group. The test emulates this situation.

Signed-off-by: Andrey Vagin <avagin@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>