Re: [PATCH v3 00/12] man2: document "new" mount API

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


(追記) (追記ここまで)



I just sent to fsdevel fix for that RESOLVE_NO_XDEV bug.
Aleksa Sarai <cyphar@xxxxxxxxxx>:
> No, LOOKUP_AUTOMOUNT affects all components. I double-checked this with
> Christian.
No. I just tested this. See tests (and miniconfig) in the end of this message.
statx always follows automounts in non-final components no matter what.
I tested this. And it follows automounts in final component depending on
AT_NO_AUTOMOUNT. I tested this too. Also, absolutely all other syscalls always
follow automounts in non-final components no matter what. With sole exception
for openat2 with RESOLVE_NO_XDEV. I didn't test this, but I conclude this
by reading code.
First of all, LOOKUP_PARENT's doc in kernel currently is wrong:
https://elixir.bootlin.com/linux/v6.17-rc1/source/include/linux/namei.h#L31
We see there:
#define LOOKUP_PARENT BIT(10) /* Looking up final parent in path */
This is not true. LOOKUP_PARENT means that we are resolving any non-final
component. LOOKUP_PARENT is set when we enter link_path_walk, which
is used for resolving everything except for final component.
And LOOKUP_PARENT is cleared when we leave link_path_walk.
Now let's look here:
https://elixir.bootlin.com/linux/v6.17-rc1/source/fs/namei.c#L1447
	if (!(lookup_flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
			 LOOKUP_OPEN | LOOKUP_CREATE | LOOKUP_AUTOMOUNT)) &&
We never return -EISDIR in this "if" if we are in non-final component
thanks to LOOKUP_PARENT here. We fall to finish_automount instead.
Again: if this is non-final component, then LOOKUP_PARENT is set, and thus
LOOKUP_AUTOMOUNT is ignored. If this is final component, then LOOKUP_AUTOMOUNT
may affect things.
Code below tests that:
- statx always follows non-final automounts
- statx follow final automounts depending on options
The code doesn't test other syscalls, they can be added if needed.
The code was tested in Qemu on Linux 6.17-rc1.
I'm not trying to insult you in any way.
Again: thank you a lot for your work! For openat2 and for these mans.
Askar Safin
====
miniconfig:
CONFIG_64BIT=y
CONFIG_EXPERT=y
CONFIG_PRINTK=y
CONFIG_PRINTK_TIME=y
CONFIG_TTY=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_PROC_FS=y
CONFIG_DEVTMPFS=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_DEBUG_FS=y
CONFIG_USER_EVENTS=y
CONFIG_FTRACE=y
CONFIG_MULTIUSER=y
CONFIG_NAMESPACES=y
CONFIG_USER_NS=y
CONFIG_PID_NS=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_RD_GZIP=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_SCRIPT=y
CONFIG_TRACEFS_AUTOMOUNT_DEPRECATED=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
====
/*
Author: Askar Safin
Public domain
Make sure your kernel is compiled with CONFIG_TRACEFS_AUTOMOUNT_DEPRECATED=y
If all tests pass, the program
should print "All tests passed".
Any other output means that something gone wrong.
This program requires root in initial user namespace
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sched.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/syscall.h>
#include <linux/openat2.h>
#define MY_ASSERT(cond) do { \
 if (!(cond)) { \
 fprintf (stderr, "%s: assertion failed\n", #cond); \
 exit (1); \
 } \
} while (0)
bool
tracing_mounted (void)
{
 struct statx tracing;
 if (statx (AT_FDCWD, "/tmp/debugfs/tracing", AT_NO_AUTOMOUNT, 0, &tracing) != 0)
 {
 perror ("statx tracing");
 exit (1);
 }
 if (!(tracing.stx_attributes_mask & STATX_ATTR_MOUNT_ROOT))
 {
 fprintf (stderr, "???\n");
 exit (1);
 }
 return tracing.stx_attributes & STATX_ATTR_MOUNT_ROOT;
}
void
mount_debugfs (void)
{
 if (mount (NULL, "/tmp/debugfs", "debugfs", 0, NULL) != 0)
 {
 perror ("mount debugfs");
 exit (1);
 }
 MY_ASSERT (!tracing_mounted ());
}
void
umount_debugfs (void)
{
 umount ("/tmp/debugfs/tracing"); // Ignore errors
 if (umount ("/tmp/debugfs") != 0)
 {
 perror ("umount debugfs");
 exit (1);
 }
}
int
main (void)
{
 // Init
 {
 if (chdir ("/") != 0)
 {
 perror ("chdir /");
 exit (1);
 }
 if (unshare (CLONE_NEWNS) != 0)
 {
 perror ("unshare");
 exit (1);
 }
 if (mount (NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0)
 {
 perror ("mount(NULL, /, NULL, MS_REC | MS_PRIVATE, NULL)");
 exit (1);
 }
 if (mount (NULL, "/tmp", "tmpfs", 0, NULL) != 0)
 {
 perror ("mount tmpfs");
 exit (1);
 }
 }
 if (mkdir ("/tmp/debugfs", 0777) != 0)
 {
 perror ("mkdir(/tmp/debugfs)");
 exit (1);
 }
 // statx always follows automounts in non-final components. With AT_NO_AUTOMOUNT and without AT_NO_AUTOMOUNT
 {
 mount_debugfs();
 {
 struct statx readme;
 if (statx (AT_FDCWD, "/tmp/debugfs/tracing/README", 0, 0, &readme) != 0)
 {
 perror ("statx");
 exit (1);
 }
 }
 MY_ASSERT (tracing_mounted ());
 umount_debugfs();
 mount_debugfs();
 {
 struct statx readme;
 if (statx (AT_FDCWD, "/tmp/debugfs/tracing/README", AT_NO_AUTOMOUNT, 0, &readme) != 0)
 {
 perror ("statx");
 exit (1);
 }
 }
 MY_ASSERT (tracing_mounted ());
 umount_debugfs();
 }
 // statx follows automounts in final components if AT_NO_AUTOMOUNT is not specified
 {
 mount_debugfs();
 {
 struct statx tracing;
 if (statx (AT_FDCWD, "/tmp/debugfs/tracing", 0, 0, &tracing) != 0)
 {
 perror ("statx");
 exit (1);
 }
 if (!(tracing.stx_attributes_mask & STATX_ATTR_MOUNT_ROOT))
 {
 fprintf (stderr, "???\n");
 exit (1);
 }
 // Checking that this is new mount, not automount point itself
 MY_ASSERT (tracing.stx_attributes & STATX_ATTR_MOUNT_ROOT);
 }
 MY_ASSERT (tracing_mounted ());
 umount_debugfs ();
 mount_debugfs();
 {
 struct statx tracing;
 if (statx (AT_FDCWD, "/tmp/debugfs/tracing", AT_NO_AUTOMOUNT, 0, &tracing) != 0)
 {
 perror ("statx");
 exit (1);
 }
 if (!(tracing.stx_attributes_mask & STATX_ATTR_MOUNT_ROOT))
 {
 fprintf (stderr, "???\n");
 exit (1);
 }
 MY_ASSERT (!(tracing.stx_attributes & STATX_ATTR_MOUNT_ROOT));
 }
 MY_ASSERT (!tracing_mounted ());
 umount_debugfs ();
 }
 printf ("All tests passed\n");
 exit (0);
}

[Index of Archives] [Linux USB Devel] [Video for Linux] [Linux Audio Users] [Yosemite News] [Linux Kernel] [Linux SCSI]

(追記) (追記ここまで)
Powered by Linux

AltStyle によって変換されたページ (->オリジナル) /