Fix tracefs mount options:

The commit 78ff640819 ("vfs: Convert tracefs to use the new mount API")
 broke the gid setting when set by fstab or other mount utility.
 It is ignored when it is set. Fix the code so that it recognises the
 option again and will honor the settings on mount at boot up.
 
 Update the internal documentation and create a selftest to make sure
 it doesn't break again in the future.
 -----BEGIN PGP SIGNATURE-----
 
 iIoEABYIADIWIQRRSw7ePDh/lE+zeZMp5XQQmuv6qgUCZyuidRQccm9zdGVkdEBn
 b29kbWlzLm9yZwAKCRAp5XQQmuv6qsgQAQDuV0x4RLpCrrowDS/ITQw/eb/WjhR7
 lhkXVROLN6RK6wD+JWmbaCP82q2S4A2Vx0Rjc72gUMmTzDb1HQflhQiLhwU=
 =0dZF
 -----END PGP SIGNATURE-----

Merge tag 'tracefs-v6.12-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull tracefs fixes from Steven Rostedt:
 "Fix tracefs mount options.

  Commit 78ff640819 ("vfs: Convert tracefs to use the new mount API")
  broke the gid setting when set by fstab or other mount utility. It is
  ignored when it is set. Fix the code so that it recognises the option
  again and will honor the settings on mount at boot up.

  Update the internal documentation and create a selftest to make sure
  it doesn't break again in the future"

* tag 'tracefs-v6.12-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
  tracing/selftests: Add tracefs mount options test
  tracing: Document tracefs gid mount option
  tracing: Fix tracefs mount options
This commit is contained in:
Linus Torvalds 2024-11-06 08:08:39 -10:00
commit 7758b20611
5 changed files with 142 additions and 16 deletions

View File

@ -392,6 +392,9 @@ static int tracefs_reconfigure(struct fs_context *fc)
struct tracefs_fs_info *sb_opts = sb->s_fs_info;
struct tracefs_fs_info *new_opts = fc->s_fs_info;
if (!new_opts)
return 0;
sync_filesystem(sb);
/* structure copy of new mount options to sb */
*sb_opts = *new_opts;
@ -478,14 +481,17 @@ static int tracefs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_op = &tracefs_super_operations;
sb->s_d_op = &tracefs_dentry_operations;
tracefs_apply_options(sb, false);
return 0;
}
static int tracefs_get_tree(struct fs_context *fc)
{
return get_tree_single(fc, tracefs_fill_super);
int err = get_tree_single(fc, tracefs_fill_super);
if (err)
return err;
return tracefs_reconfigure(fc);
}
static void tracefs_free_fc(struct fs_context *fc)

View File

@ -5501,6 +5501,10 @@ static const struct file_operations tracing_iter_fops = {
static const char readme_msg[] =
"tracing mini-HOWTO:\n\n"
"By default tracefs removes all OTH file permission bits.\n"
"When mounting tracefs an optional group id can be specified\n"
"which adds the group to every directory and file in tracefs:\n\n"
"\t e.g. mount -t tracefs [-o [gid=<gid>]] nodev /sys/kernel/tracing\n\n"
"# echo 0 > tracing_on : quick way to disable tracing\n"
"# echo 1 > tracing_on : quick way to re-enable tracing\n\n"
" Important files:\n"

View File

@ -0,0 +1,101 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Test tracefs GID mount option
# requires: "[gid=<gid>]":README
fail() {
local msg="$1"
echo "FAILED: $msg"
exit_fail
}
find_alternate_gid() {
local original_gid="$1"
tac /etc/group | grep -v ":$original_gid:" | head -1 | cut -d: -f3
}
mount_tracefs_with_options() {
local mount_point="$1"
local options="$2"
mount -t tracefs -o "$options" nodev "$mount_point"
setup
}
unmount_tracefs() {
local mount_point="$1"
# Need to make sure the mount isn't busy so that we can umount it
(cd $mount_point; finish_ftrace;)
cleanup
}
create_instance() {
local mount_point="$1"
local instance="$mount_point/instances/$(mktemp -u test-XXXXXX)"
mkdir "$instance"
echo "$instance"
}
remove_instance() {
local instance="$1"
rmdir "$instance"
}
check_gid() {
local mount_point="$1"
local expected_gid="$2"
echo "Checking permission group ..."
cd "$mount_point"
for file in "." "events" "events/sched" "events/sched/sched_switch" "events/sched/sched_switch/enable"; do
local gid=`stat -c "%g" $file`
if [ "$gid" -ne "$expected_gid" ]; then
cd - # Return to the previous working directory (tracefs root)
fail "$(realpath $file): Expected group $expected_gid; Got group $gid"
fi
done
cd - # Return to the previous working directory (tracefs root)
}
test_gid_mount_option() {
local mount_point=$(get_mount_point)
local mount_options=$(get_mnt_options "$mount_point")
local original_group=$(stat -c "%g" .)
local other_group=$(find_alternate_gid "$original_group")
# Set up mount options with new GID for testing
local new_options=`echo "$mount_options" | sed -e "s/gid=[0-9]*/gid=$other_group/"`
if [ "$new_options" = "$mount_options" ]; then
new_options="$mount_options,gid=$other_group"
mount_options="$mount_options,gid=$original_group"
fi
# Unmount existing tracefs instance and mount with new GID
unmount_tracefs "$mount_point"
mount_tracefs_with_options "$mount_point" "$new_options"
check_gid "$mount_point" "$other_group"
# Check that files created after the mount inherit the GID
local instance=$(create_instance "$mount_point")
check_gid "$instance" "$other_group"
remove_instance "$instance"
# Unmount and remount with the original GID
unmount_tracefs "$mount_point"
mount_tracefs_with_options "$mount_point" "$mount_options"
check_gid "$mount_point" "$original_group"
}
test_gid_mount_option
exit 0

View File

@ -1,24 +1,14 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Test file and directory ownership changes for eventfs
# requires: "[gid=<gid>]":README
original_group=`stat -c "%g" .`
original_owner=`stat -c "%u" .`
mount_point=`stat -c '%m' .`
local mount_point=$(get_mount_point)
# If stat -c '%m' does not work (e.g. busybox) or failed, try to use the
# current working directory (which should be a tracefs) as the mount point.
if [ ! -d "$mount_point" ]; then
if mount | grep -qw $PWD ; then
mount_point=$PWD
else
# If PWD doesn't work, that is an environmental problem.
exit_unresolved
fi
fi
mount_options=`mount | grep "$mount_point" | sed -e 's/.*(\(.*\)).*/\1/'`
mount_options=$(get_mnt_options "$mount_point")
# find another owner and group that is not the original
other_group=`tac /etc/group | grep -v ":$original_group:" | head -1 | cut -d: -f3`

View File

@ -193,3 +193,28 @@ ftrace_errlog_check() { # err-prefix command-with-error-pos-by-^ command-file
# " Command: " and "^\n" => 13
test $(expr 13 + $pos) -eq $N
}
# Helper to get the tracefs mount point
get_mount_point() {
local mount_point=`stat -c '%m' .`
# If stat -c '%m' does not work (e.g. busybox) or failed, try to use the
# current working directory (which should be a tracefs) as the mount point.
if [ ! -d "$mount_point" ]; then
if mount | grep -qw "$PWD"; then
mount_point=$PWD
else
# If PWD doesn't work, that is an environmental problem.
exit_unresolved
fi
fi
echo "$mount_point"
}
# Helper function to retrieve mount options for a given mount point
get_mnt_options() {
local mnt_point="$1"
local opts=$(mount | grep -m1 "$mnt_point" | sed -e 's/.*(\(.*\)).*/\1/')
echo "$opts"
}