[Devel] [RFC PATCH RH7] fs: autofs4: find_autofs_mount overmounted parent support
Alexander Mikhalitsyn
alexander.mikhalitsyn at virtuozzo.com
Mon Mar 1 16:05:10 MSK 2021
It was discovered that find_autofs_mount() function
in autofs4 not support cases when autofs mount
parent is overmounted. In this case this function will
always return -ENOENT.
Real-life reproducer is fairly simple.
Consider the following mounts on root mntns:
--
35 24 0:36 / /proc/sys/fs/binfmt_misc rw,relatime shared:16 - autofs systemd-1 ...
654 35 0:57 / /proc/sys/fs/binfmt_misc rw,nosuid,nodev,noexec,relatime shared:322 - binfmt_misc ...
--
and some process "some_process" which calls ioctl(AUTOFS_DEV_IOCTL_OPENMOUNT)
Due to "mount-proc" /proc will be overmounted and ioctl() will fail with -ENOENT
https://jira.sw.ru/browse/PSBM-125911
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn at virtuozzo.com>
---
fs/autofs4/dev-ioctl.c | 68 ++++++++++++++++++++++++++++++++++++------
1 file changed, 59 insertions(+), 9 deletions(-)
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index 86be02910116..5a387acd0705 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -24,6 +24,8 @@
#include <linux/uaccess.h>
#include <linux/slab.h>
+#include "../mount.h"
+
#include "autofs_i.h"
/*
@@ -198,26 +200,74 @@ static int find_autofs_mount(const char *pathname,
int test(const struct path *path, void *data),
void *data)
{
+ struct mnt_namespace *mnt_ns = current->nsproxy->mnt_ns;
struct path path;
+ char *fpathname;
+ char *fpathbuf = NULL, *pathbuf = NULL;
+ struct mount *mnt;
int err;
err = kern_path_mountpoint(AT_FDCWD, pathname, &path, 0);
if (err)
return err;
+
+ fpathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!fpathbuf) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ /*
+ * We have pathname from user but it may be relative, we need to
+ * have full path because we want to compare it with mountpoints
+ * paths later.
+ */
+ fpathname = d_path(&path, fpathbuf, PATH_MAX);
+ if (IS_ERR(fpathname)) {
+ err = PTR_ERR(fpathname);
+ goto err;
+ }
+
+ pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!pathbuf) {
+ err = -ENOMEM;
+ goto err;
+ }
+
err = -ENOENT;
- while (path.dentry == path.mnt->mnt_root) {
- if (path.dentry->d_sb->s_magic == AUTOFS_SUPER_MAGIC) {
- if (test(&path, data)) {
- path_get(&path);
- *res = path;
- err = 0;
- break;
- }
+ down_read(&namespace_sem);
+ list_for_each_entry(mnt, &mnt_ns->list, mnt_list) {
+ char *name;
+ struct path tmppath;
+
+ if (mnt->mnt.mnt_sb->s_magic != AUTOFS_SUPER_MAGIC)
+ continue;
+
+ tmppath.dentry = mnt->mnt.mnt_root;
+ tmppath.mnt = &mnt->mnt;
+
+ name = d_path(&tmppath, pathbuf, PATH_MAX);
+ if (IS_ERR(name)) {
+ err = PTR_ERR(name);
+ break;
}
- if (!follow_up(&path))
+
+ if (strncmp(fpathname, name, PATH_MAX))
+ continue;
+
+ if (test(&tmppath, data)) {
+ path_get(&tmppath);
+ *res = tmppath;
+ err = 0;
break;
+ }
}
+ up_read(&namespace_sem);
+
+err:
path_put(&path);
+ kfree(fpathbuf);
+ kfree(pathbuf);
return err;
}
--
2.28.0
More information about the Devel
mailing list