diff mbox series

[v10,1/6] generic/631: add test for detached mount propagation

Message ID 20210322134522.916512-2-brauner@kernel.org (mailing list archive)
State New, archived
Headers show
Series fstests: add idmapped mounts tests | expand

Commit Message

Christian Brauner March 22, 2021, 1:45 p.m. UTC
From: Christian Brauner <christian.brauner@ubuntu.com>

Regression test to verify that creating a series of detached mounts,
attaching them to the filesystem, and unmounting them does not trigger an
integer overflow in ns->mounts causing the kernel to block any new mounts in
count_mounts() and returning ENOSPC because it falsely assumes that the
maximum number of mounts in the mount namespace has been reached, i.e. it
thinks it can't fit the new mounts into the mount namespace anymore.

The test is written in a way that it will leave the host's mount
namespace intact so we are sure to never make the host's mount namespace
unuseable!

Link: https://git.kernel.org/torvalds/c/ee2e3f50629f17b0752b55b2566c15ce8dafb557
Cc: Eryu Guan <guan@eryu.me>
Cc: David Howells <dhowells@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
---
/* v1 - v8 */
patch not present

/* v9 */
- Christian Brauner <christian.brauner@ubuntu.com>:
  - Rebased on current master.

/* v10 */
- Eryu Guan <guan@eryu.me>:
  - Add missing checks whether test is supported.
  - Move status=$? assignment up.
---
 .gitignore                        |   1 +
 src/Makefile                      |   3 +-
 src/detached_mounts_propagation.c | 252 ++++++++++++++++++++++++++++++
 tests/generic/631                 |  43 +++++
 tests/generic/631.out             |   2 +
 tests/generic/group               |   1 +
 6 files changed, 301 insertions(+), 1 deletion(-)
 create mode 100644 src/detached_mounts_propagation.c
 create mode 100644 tests/generic/631
 create mode 100644 tests/generic/631.out

Comments

Amir Goldstein March 24, 2021, 7:40 a.m. UTC | #1
On Mon, Mar 22, 2021 at 3:46 PM Christian Brauner <brauner@kernel.org> wrote:
>
> From: Christian Brauner <christian.brauner@ubuntu.com>
>
> Regression test to verify that creating a series of detached mounts,
> attaching them to the filesystem, and unmounting them does not trigger an
> integer overflow in ns->mounts causing the kernel to block any new mounts in
> count_mounts() and returning ENOSPC because it falsely assumes that the
> maximum number of mounts in the mount namespace has been reached, i.e. it
> thinks it can't fit the new mounts into the mount namespace anymore.
>
> The test is written in a way that it will leave the host's mount
> namespace intact so we are sure to never make the host's mount namespace
> unuseable!
>
> Link: https://git.kernel.org/torvalds/c/ee2e3f50629f17b0752b55b2566c15ce8dafb557
> Cc: Eryu Guan <guan@eryu.me>
> Cc: David Howells <dhowells@redhat.com>
> Reviewed-by: Christoph Hellwig <hch@lst.de>
> Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
> ---
> /* v1 - v8 */
> patch not present
>
> /* v9 */
> - Christian Brauner <christian.brauner@ubuntu.com>:
>   - Rebased on current master.
>
> /* v10 */
> - Eryu Guan <guan@eryu.me>:
>   - Add missing checks whether test is supported.
>   - Move status=$? assignment up.
> ---

Technical nit: why did you add this extra --- line?
It causes all the patch changelog to appear in the commit message.
I don't think that was your intention? and I don't think it adds valuable
into to git log.

Thanks,
Amir.
Christian Brauner March 24, 2021, 7:50 a.m. UTC | #2
On Wed, Mar 24, 2021 at 09:40:50AM +0200, Amir Goldstein wrote:
> On Mon, Mar 22, 2021 at 3:46 PM Christian Brauner <brauner@kernel.org> wrote:
> >
> > From: Christian Brauner <christian.brauner@ubuntu.com>
> >
> > Regression test to verify that creating a series of detached mounts,
> > attaching them to the filesystem, and unmounting them does not trigger an
> > integer overflow in ns->mounts causing the kernel to block any new mounts in
> > count_mounts() and returning ENOSPC because it falsely assumes that the
> > maximum number of mounts in the mount namespace has been reached, i.e. it
> > thinks it can't fit the new mounts into the mount namespace anymore.
> >
> > The test is written in a way that it will leave the host's mount
> > namespace intact so we are sure to never make the host's mount namespace
> > unuseable!
> >
> > Link: https://git.kernel.org/torvalds/c/ee2e3f50629f17b0752b55b2566c15ce8dafb557
> > Cc: Eryu Guan <guan@eryu.me>
> > Cc: David Howells <dhowells@redhat.com>
> > Reviewed-by: Christoph Hellwig <hch@lst.de>
> > Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
> > ---
> > /* v1 - v8 */
> > patch not present
> >
> > /* v9 */
> > - Christian Brauner <christian.brauner@ubuntu.com>:
> >   - Rebased on current master.
> >
> > /* v10 */
> > - Eryu Guan <guan@eryu.me>:
> >   - Add missing checks whether test is supported.
> >   - Move status=$? assignment up.
> > ---
> 
> Technical nit: why did you add this extra --- line?
> It causes all the patch changelog to appear in the commit message.
> I don't think that was your intention? and I don't think it adds valuable
> into to git log.

I've not done that in any of the other patches or on any other patches I
ever wrote so I think this was just a copy-paste error when I updated
the changelog.

Thanks for pointing this out.
Christian
Amir Goldstein March 24, 2021, 8:04 a.m. UTC | #3
On Wed, Mar 24, 2021 at 9:50 AM Christian Brauner
<christian.brauner@ubuntu.com> wrote:
>
> On Wed, Mar 24, 2021 at 09:40:50AM +0200, Amir Goldstein wrote:
> > On Mon, Mar 22, 2021 at 3:46 PM Christian Brauner <brauner@kernel.org> wrote:
> > >
> > > From: Christian Brauner <christian.brauner@ubuntu.com>
> > >
> > > Regression test to verify that creating a series of detached mounts,
> > > attaching them to the filesystem, and unmounting them does not trigger an
> > > integer overflow in ns->mounts causing the kernel to block any new mounts in
> > > count_mounts() and returning ENOSPC because it falsely assumes that the
> > > maximum number of mounts in the mount namespace has been reached, i.e. it
> > > thinks it can't fit the new mounts into the mount namespace anymore.
> > >
> > > The test is written in a way that it will leave the host's mount
> > > namespace intact so we are sure to never make the host's mount namespace
> > > unuseable!
> > >
> > > Link: https://git.kernel.org/torvalds/c/ee2e3f50629f17b0752b55b2566c15ce8dafb557
> > > Cc: Eryu Guan <guan@eryu.me>
> > > Cc: David Howells <dhowells@redhat.com>
> > > Reviewed-by: Christoph Hellwig <hch@lst.de>
> > > Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
> > > ---
> > > /* v1 - v8 */
> > > patch not present
> > >
> > > /* v9 */
> > > - Christian Brauner <christian.brauner@ubuntu.com>:
> > >   - Rebased on current master.
> > >
> > > /* v10 */
> > > - Eryu Guan <guan@eryu.me>:
> > >   - Add missing checks whether test is supported.
> > >   - Move status=$? assignment up.
> > > ---
> >
> > Technical nit: why did you add this extra --- line?
> > It causes all the patch changelog to appear in the commit message.
> > I don't think that was your intention? and I don't think it adds valuable
> > into to git log.
>
> I've not done that in any of the other patches or on any other patches I
> ever wrote so I think this was just a copy-paste error when I updated
> the changelog.
>

Please note this glitch happened in all the patches in the series...

Thanks,
Amir.
Christian Brauner March 24, 2021, 8:39 a.m. UTC | #4
On Wed, Mar 24, 2021 at 10:04:39AM +0200, Amir Goldstein wrote:
> On Wed, Mar 24, 2021 at 9:50 AM Christian Brauner
> <christian.brauner@ubuntu.com> wrote:
> >
> > On Wed, Mar 24, 2021 at 09:40:50AM +0200, Amir Goldstein wrote:
> > > On Mon, Mar 22, 2021 at 3:46 PM Christian Brauner <brauner@kernel.org> wrote:
> > > >
> > > > From: Christian Brauner <christian.brauner@ubuntu.com>
> > > >
> > > > Regression test to verify that creating a series of detached mounts,
> > > > attaching them to the filesystem, and unmounting them does not trigger an
> > > > integer overflow in ns->mounts causing the kernel to block any new mounts in
> > > > count_mounts() and returning ENOSPC because it falsely assumes that the
> > > > maximum number of mounts in the mount namespace has been reached, i.e. it
> > > > thinks it can't fit the new mounts into the mount namespace anymore.
> > > >
> > > > The test is written in a way that it will leave the host's mount
> > > > namespace intact so we are sure to never make the host's mount namespace
> > > > unuseable!
> > > >
> > > > Link: https://git.kernel.org/torvalds/c/ee2e3f50629f17b0752b55b2566c15ce8dafb557
> > > > Cc: Eryu Guan <guan@eryu.me>
> > > > Cc: David Howells <dhowells@redhat.com>
> > > > Reviewed-by: Christoph Hellwig <hch@lst.de>
> > > > Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
> > > > ---
> > > > /* v1 - v8 */
> > > > patch not present
> > > >
> > > > /* v9 */
> > > > - Christian Brauner <christian.brauner@ubuntu.com>:
> > > >   - Rebased on current master.
> > > >
> > > > /* v10 */
> > > > - Eryu Guan <guan@eryu.me>:
> > > >   - Add missing checks whether test is supported.
> > > >   - Move status=$? assignment up.
> > > > ---
> > >
> > > Technical nit: why did you add this extra --- line?
> > > It causes all the patch changelog to appear in the commit message.
> > > I don't think that was your intention? and I don't think it adds valuable
> > > into to git log.
> >
> > I've not done that in any of the other patches or on any other patches I
> > ever wrote so I think this was just a copy-paste error when I updated
> > the changelog.
> >
> 
> Please note this glitch happened in all the patches in the series...

Oh wait, actually looking at this again I think don't understand just
yet. This is pretty common and when you apply the series git am will cut
after the first
---

And thinking about it so far I've never heard anyone complain about
this. But likely I just misunderstand you and I really borked something.

Fwiw, this format seems documented at
https://www.kernel.org/doc/html/latest/process/submitting-patches.html

"The --- marker line serves the essential purpose of marking for patch
 handling tools where the changelog message ends.

 One good use for the additional comments after the --- marker is for a
 diffstat, to show what files have changed, and the number of inserted
 and deleted lines per file. A diffstat is especially useful on bigger
 patches. Other comments relevant only to the moment or the maintainer,
 not suitable for the permanent changelog, should also go here. A good
 example of such comments might be patch changelogs which describe what
 has changed between the v1 and v2 version of the patch.

 If you are going to include a diffstat after the --- marker, please use
 diffstat options -p 1 -w 70 so that filenames are listed from the top
 of the kernel source tree and don’t use too much horizontal space
 (easily fit in 80 columns, maybe with some indentation). (git generates
 appropriate diffstats by default.)"

And also at
https://www.ozlabs.org/~akpm/stuff/tpp.txt

"g) Non-changelog text:

    Sometimes you want to include text in the email which isn't designed to
    go into the changelog in the git repository.  Things like "this is already
    in Fred's tree" or "this is an updated version of last Friday's patch" or
    whatever.
 
    You should place such text below the "^---" separator so that it is
    auto-removed when being placed into the revision control system."

And there are quite a few examples that do it this way just one random
pick from my inbox:
https://lore.kernel.org/lkml/20210316204252.427806-8-mic@digikod.net

Christian
Amir Goldstein March 24, 2021, 9:45 a.m. UTC | #5
On Wed, Mar 24, 2021 at 10:39 AM Christian Brauner
<christian.brauner@ubuntu.com> wrote:
>
> On Wed, Mar 24, 2021 at 10:04:39AM +0200, Amir Goldstein wrote:
> > On Wed, Mar 24, 2021 at 9:50 AM Christian Brauner
> > <christian.brauner@ubuntu.com> wrote:
> > >
> > > On Wed, Mar 24, 2021 at 09:40:50AM +0200, Amir Goldstein wrote:
> > > > On Mon, Mar 22, 2021 at 3:46 PM Christian Brauner <brauner@kernel.org> wrote:
> > > > >
> > > > > From: Christian Brauner <christian.brauner@ubuntu.com>
> > > > >
> > > > > Regression test to verify that creating a series of detached mounts,
> > > > > attaching them to the filesystem, and unmounting them does not trigger an
> > > > > integer overflow in ns->mounts causing the kernel to block any new mounts in
> > > > > count_mounts() and returning ENOSPC because it falsely assumes that the
> > > > > maximum number of mounts in the mount namespace has been reached, i.e. it
> > > > > thinks it can't fit the new mounts into the mount namespace anymore.
> > > > >
> > > > > The test is written in a way that it will leave the host's mount
> > > > > namespace intact so we are sure to never make the host's mount namespace
> > > > > unuseable!
> > > > >
> > > > > Link: https://git.kernel.org/torvalds/c/ee2e3f50629f17b0752b55b2566c15ce8dafb557
> > > > > Cc: Eryu Guan <guan@eryu.me>
> > > > > Cc: David Howells <dhowells@redhat.com>
> > > > > Reviewed-by: Christoph Hellwig <hch@lst.de>
> > > > > Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
> > > > > ---
> > > > > /* v1 - v8 */
> > > > > patch not present
> > > > >
> > > > > /* v9 */
> > > > > - Christian Brauner <christian.brauner@ubuntu.com>:
> > > > >   - Rebased on current master.
> > > > >
> > > > > /* v10 */
> > > > > - Eryu Guan <guan@eryu.me>:
> > > > >   - Add missing checks whether test is supported.
> > > > >   - Move status=$? assignment up.
> > > > > ---
> > > >
> > > > Technical nit: why did you add this extra --- line?
> > > > It causes all the patch changelog to appear in the commit message.
> > > > I don't think that was your intention? and I don't think it adds valuable
> > > > into to git log.
> > >
> > > I've not done that in any of the other patches or on any other patches I
> > > ever wrote so I think this was just a copy-paste error when I updated
> > > the changelog.
> > >
> >
> > Please note this glitch happened in all the patches in the series...
>
> Oh wait, actually looking at this again I think don't understand just
> yet. This is pretty common and when you apply the series git am will cut
> after the first
> ---
>
> And thinking about it so far I've never heard anyone complain about
> this. But likely I just misunderstand you and I really borked something.
>

I see. The reason I brought this up is because I fetched your branch from
https://github.com/brauner/xfstests/ idmapped_mounts_v2
and it has this changelog visible in git log.

So I am not sure how that came to be.

Thanks,
Amir.
Christian Brauner March 24, 2021, 9:52 a.m. UTC | #6
On Wed, Mar 24, 2021 at 11:45:34AM +0200, Amir Goldstein wrote:
> On Wed, Mar 24, 2021 at 10:39 AM Christian Brauner
> <christian.brauner@ubuntu.com> wrote:
> >
> > On Wed, Mar 24, 2021 at 10:04:39AM +0200, Amir Goldstein wrote:
> > > On Wed, Mar 24, 2021 at 9:50 AM Christian Brauner
> > > <christian.brauner@ubuntu.com> wrote:
> > > >
> > > > On Wed, Mar 24, 2021 at 09:40:50AM +0200, Amir Goldstein wrote:
> > > > > On Mon, Mar 22, 2021 at 3:46 PM Christian Brauner <brauner@kernel.org> wrote:
> > > > > >
> > > > > > From: Christian Brauner <christian.brauner@ubuntu.com>
> > > > > >
> > > > > > Regression test to verify that creating a series of detached mounts,
> > > > > > attaching them to the filesystem, and unmounting them does not trigger an
> > > > > > integer overflow in ns->mounts causing the kernel to block any new mounts in
> > > > > > count_mounts() and returning ENOSPC because it falsely assumes that the
> > > > > > maximum number of mounts in the mount namespace has been reached, i.e. it
> > > > > > thinks it can't fit the new mounts into the mount namespace anymore.
> > > > > >
> > > > > > The test is written in a way that it will leave the host's mount
> > > > > > namespace intact so we are sure to never make the host's mount namespace
> > > > > > unuseable!
> > > > > >
> > > > > > Link: https://git.kernel.org/torvalds/c/ee2e3f50629f17b0752b55b2566c15ce8dafb557
> > > > > > Cc: Eryu Guan <guan@eryu.me>
> > > > > > Cc: David Howells <dhowells@redhat.com>
> > > > > > Reviewed-by: Christoph Hellwig <hch@lst.de>
> > > > > > Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
> > > > > > ---
> > > > > > /* v1 - v8 */
> > > > > > patch not present
> > > > > >
> > > > > > /* v9 */
> > > > > > - Christian Brauner <christian.brauner@ubuntu.com>:
> > > > > >   - Rebased on current master.
> > > > > >
> > > > > > /* v10 */
> > > > > > - Eryu Guan <guan@eryu.me>:
> > > > > >   - Add missing checks whether test is supported.
> > > > > >   - Move status=$? assignment up.
> > > > > > ---
> > > > >
> > > > > Technical nit: why did you add this extra --- line?
> > > > > It causes all the patch changelog to appear in the commit message.
> > > > > I don't think that was your intention? and I don't think it adds valuable
> > > > > into to git log.
> > > >
> > > > I've not done that in any of the other patches or on any other patches I
> > > > ever wrote so I think this was just a copy-paste error when I updated
> > > > the changelog.
> > > >
> > >
> > > Please note this glitch happened in all the patches in the series...
> >
> > Oh wait, actually looking at this again I think don't understand just
> > yet. This is pretty common and when you apply the series git am will cut
> > after the first
> > ---
> >
> > And thinking about it so far I've never heard anyone complain about
> > this. But likely I just misunderstand you and I really borked something.
> >
> 
> I see. The reason I brought this up is because I fetched your branch from
> https://github.com/brauner/xfstests/ idmapped_mounts_v2
> and it has this changelog visible in git log.
> 
> So I am not sure how that came to be.

Oh now I understand you. That's intentional, non-final branches, i.e.
versioned branches of mine or branches where I'm not the one applying
the patches after pulling them via b4 still container the changelogs
because I need to assume I'll cut new version from it and will amend the
changelogs. This also ensures git format-patch will give retain the
changelog.

But the point is will taken. If I provide a branch to pull from I should
strip the changelogs. This is what I done now. You can find this series
(unchanged apart from the stripped changelog) here:
always have the changelog recorded to

https://github.com/brauner/xfstests/ idmapped_mounts

similar for gitlab and kernel.org.

Thanks for pointing that out!
Christian
diff mbox series

Patch

diff --git a/.gitignore b/.gitignore
index f3bc0a4f..72bd40a0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -62,6 +62,7 @@ 
 /src/cloner
 /src/dbtest
 /src/deduperace
+/src/detached_mounts_propagation
 /src/devzero
 /src/dio-interleaved
 /src/dio-invalidate-cache
diff --git a/src/Makefile b/src/Makefile
index 3d729a34..99019e6e 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -29,7 +29,8 @@  LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
 	attr-list-by-handle-cursor-test listxattr dio-interleaved t_dir_type \
 	dio-invalidate-cache stat_test t_encrypted_d_revalidate \
 	attr_replace_test swapon mkswap t_attr_corruption t_open_tmpfiles \
-	fscrypt-crypt-util bulkstat_null_ocount splice-test chprojid_fail
+	fscrypt-crypt-util bulkstat_null_ocount splice-test chprojid_fail \
+	detached_mounts_propagation
 
 SUBDIRS = log-writes perf
 
diff --git a/src/detached_mounts_propagation.c b/src/detached_mounts_propagation.c
new file mode 100644
index 00000000..4a588e46
--- /dev/null
+++ b/src/detached_mounts_propagation.c
@@ -0,0 +1,252 @@ 
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/*
+ * Copyright (c) 2021 Christian Brauner <christian.brauner@ubuntu.com>
+ * All Rights Reserved.
+ *
+ * Regression test to verify that creating a series of detached mounts,
+ * attaching them to the filesystem, and unmounting them does not trigger an
+ * integer overflow in ns->mounts causing the kernel to block any new mounts in
+ * count_mounts() and returning ENOSPC because it falsely assumes that the
+ * maximum number of mounts in the mount namespace has been reached, i.e. it
+ * thinks it can't fit the new mounts into the mount namespace anymore.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <limits.h>
+#include <sched.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/* open_tree() */
+#ifndef OPEN_TREE_CLONE
+#define OPEN_TREE_CLONE 1
+#endif
+
+#ifndef OPEN_TREE_CLOEXEC
+#define OPEN_TREE_CLOEXEC O_CLOEXEC
+#endif
+
+#ifndef __NR_open_tree
+	#if defined __alpha__
+		#define __NR_open_tree 538
+	#elif defined _MIPS_SIM
+		#if _MIPS_SIM == _MIPS_SIM_ABI32	/* o32 */
+			#define __NR_open_tree 4428
+		#endif
+		#if _MIPS_SIM == _MIPS_SIM_NABI32	/* n32 */
+			#define __NR_open_tree 6428
+		#endif
+		#if _MIPS_SIM == _MIPS_SIM_ABI64	/* n64 */
+			#define __NR_open_tree 5428
+		#endif
+	#elif defined __ia64__
+		#define __NR_open_tree (428 + 1024)
+	#else
+		#define __NR_open_tree 428
+	#endif
+#endif
+
+/* move_mount() */
+#ifndef MOVE_MOUNT_F_EMPTY_PATH
+#define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 /* Empty from path permitted */
+#endif
+
+#ifndef __NR_move_mount
+	#if defined __alpha__
+		#define __NR_move_mount 539
+	#elif defined _MIPS_SIM
+		#if _MIPS_SIM == _MIPS_SIM_ABI32	/* o32 */
+			#define __NR_move_mount 4429
+		#endif
+		#if _MIPS_SIM == _MIPS_SIM_NABI32	/* n32 */
+			#define __NR_move_mount 6429
+		#endif
+		#if _MIPS_SIM == _MIPS_SIM_ABI64	/* n64 */
+			#define __NR_move_mount 5429
+		#endif
+	#elif defined __ia64__
+		#define __NR_move_mount (428 + 1024)
+	#else
+		#define __NR_move_mount 429
+	#endif
+#endif
+
+static inline int sys_open_tree(int dfd, const char *filename, unsigned int flags)
+{
+	return syscall(__NR_open_tree, dfd, filename, flags);
+}
+
+static inline int sys_move_mount(int from_dfd, const char *from_pathname, int to_dfd,
+				 const char *to_pathname, unsigned int flags)
+{
+	return syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd, to_pathname, flags);
+}
+
+static bool is_shared_mountpoint(const char *path)
+{
+	bool shared = false;
+	FILE *f = NULL;
+	char *line = NULL;
+	int i;
+	size_t len = 0;
+
+	f = fopen("/proc/self/mountinfo", "re");
+	if (!f)
+		return 0;
+
+	while (getline(&line, &len, f) > 0) {
+		char *slider1, *slider2;
+
+		for (slider1 = line, i = 0; slider1 && i < 4; i++)
+			slider1 = strchr(slider1 + 1, ' ');
+
+		if (!slider1)
+			continue;
+
+		slider2 = strchr(slider1 + 1, ' ');
+		if (!slider2)
+			continue;
+
+		*slider2 = '\0';
+		if (strcmp(slider1 + 1, path) == 0) {
+			/* This is the path. Is it shared? */
+			slider1 = strchr(slider2 + 1, ' ');
+			if (slider1 && strstr(slider1, "shared:")) {
+				shared = true;
+				break;
+			}
+		}
+	}
+	fclose(f);
+	free(line);
+
+	return shared;
+}
+
+static void usage(void)
+{
+	const char *text = "mount-new [--recursive] <base-dir>\n";
+	fprintf(stderr, "%s", text);
+	_exit(EXIT_SUCCESS);
+}
+
+#define exit_usage(format, ...)                              \
+	({                                                   \
+		fprintf(stderr, format "\n", ##__VA_ARGS__); \
+		usage();                                     \
+	})
+
+#define exit_log(format, ...)                                \
+	({                                                   \
+		fprintf(stderr, format "\n", ##__VA_ARGS__); \
+		exit(EXIT_FAILURE);                          \
+	})
+
+static const struct option longopts[] = {
+	{"help",	no_argument,		0,	'a'},
+	{ NULL,		no_argument,		0,	 0 },
+};
+
+int main(int argc, char *argv[])
+{
+	int exit_code = EXIT_SUCCESS, index = 0;
+	int dfd, fd_tree, new_argc, ret;
+	char *base_dir;
+	char *const *new_argv;
+	char target[PATH_MAX];
+
+	while ((ret = getopt_long_only(argc, argv, "", longopts, &index)) != -1) {
+		switch (ret) {
+		case 'a':
+			/* fallthrough */
+		default:
+			usage();
+		}
+	}
+
+	new_argv = &argv[optind];
+	new_argc = argc - optind;
+	if (new_argc < 1)
+		exit_usage("Missing base directory\n");
+	base_dir = new_argv[0];
+
+	if (*base_dir != '/')
+		exit_log("Please specify an absolute path");
+
+	/* Ensure that target is a shared mountpoint. */
+	if (!is_shared_mountpoint(base_dir))
+		exit_log("Please ensure that \"%s\" is a shared mountpoint", base_dir);
+
+	ret = unshare(CLONE_NEWNS);
+	if (ret < 0)
+		exit_log("%m - Failed to create new mount namespace");
+
+	ret = mount(NULL, base_dir, NULL, MS_REC | MS_SHARED, NULL);
+	if (ret < 0)
+		exit_log("%m - Failed to make base_dir shared mountpoint");
+
+	dfd = open(base_dir, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+	if (dfd < 0)
+		exit_log("%m - Failed to open base directory \"%s\"", base_dir);
+
+	ret = mkdirat(dfd, "detached-move-mount", 0755);
+	if (ret < 0)
+		exit_log("%m - Failed to create required temporary directories");
+
+	ret = snprintf(target, sizeof(target), "%s/detached-move-mount", base_dir);
+	if (ret < 0 || (size_t)ret >= sizeof(target))
+		exit_log("%m - Failed to assemble target path");
+
+	/*
+	 * Having a mount table with 10000 mounts is already quite excessive
+	 * and shoult account even for weird test systems.
+	 */
+	for (size_t i = 0; i < 10000; i++) {
+		fd_tree = sys_open_tree(dfd, "detached-move-mount",
+					OPEN_TREE_CLONE |
+					OPEN_TREE_CLOEXEC |
+					AT_EMPTY_PATH);
+		if (fd_tree < 0) {
+			if (errno == ENOSYS) /* New mount API not (fully) supported. */
+				break;
+
+			fprintf(stderr, "%m - Failed to open %d(detached-move-mount)", dfd);
+			exit_code = EXIT_FAILURE;
+			break;
+		}
+
+		ret = sys_move_mount(fd_tree, "", dfd, "detached-move-mount", MOVE_MOUNT_F_EMPTY_PATH);
+		if (ret < 0) {
+			if (errno == ENOSPC)
+				fprintf(stderr, "%m - Buggy mount counting");
+			else if (errno == ENOSYS) /* New mount API not (fully) supported. */
+				break;
+			else
+				fprintf(stderr, "%m - Failed to attach mount to %d(detached-move-mount)", dfd);
+			exit_code = EXIT_FAILURE;
+			break;
+		}
+		close(fd_tree);
+
+		ret = umount2(target, MNT_DETACH);
+		if (ret < 0) {
+			fprintf(stderr, "%m - Failed to unmount %s", target);
+			exit_code = EXIT_FAILURE;
+			break;
+		}
+	}
+
+	(void)unlinkat(dfd, "detached-move-mount", AT_REMOVEDIR);
+	close(dfd);
+
+	exit(exit_code);
+}
diff --git a/tests/generic/631 b/tests/generic/631
new file mode 100644
index 00000000..0b6cac42
--- /dev/null
+++ b/tests/generic/631
@@ -0,0 +1,43 @@ 
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2021 Christian Brauner <christian.brauner@ubuntu.com>
+# All Rights Reserved.
+#
+# FS QA Test No. 631
+#
+# Regression test to verify that creating a series of detached mounts,
+# attaching them to the filesystem, and unmounting them does not trigger an
+# integer overflow in ns->mounts causing the kernel to block any new mounts in
+# count_mounts() and returning ENOSPC because it falsely assumes that the
+# maximum number of mounts in the mount namespace has been reached, i.e. it
+# thinks it can't fit the new mounts into the mount namespace anymore.
+#
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+	cd /
+	rm -f $tmp.*
+}
+
+. ./common/rc
+
+rm -f $seqres.full
+
+_supported_fs generic
+_require_test
+_require_test_program "detached_mounts_propagation"
+
+$here/src/detached_mounts_propagation $TEST_DIR >> $seqres.full
+status=$?
+
+echo silence is golden
+exit
diff --git a/tests/generic/631.out b/tests/generic/631.out
new file mode 100644
index 00000000..ce88f447
--- /dev/null
+++ b/tests/generic/631.out
@@ -0,0 +1,2 @@ 
+QA output created by 631
+silence is golden
diff --git a/tests/generic/group b/tests/generic/group
index 7c7531d1..151f8af2 100644
--- a/tests/generic/group
+++ b/tests/generic/group
@@ -633,3 +633,4 @@ 
 628 auto quick rw clone
 629 auto quick rw copy_range
 630 auto quick rw dedupe clone
+631 auto quick mount