Commit 7758b206 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull tracefs fixes from Steven Rostedt:
 "Fix tracefs mount options.

  Commit 78ff6408 ("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
parents b226d019 8b55572e
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -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)
+4 −0
Original line number Diff line number Diff line
@@ -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"
+101 −0
Original line number Diff line number Diff line
#!/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
+3 −13
Original line number Diff line number Diff line
#!/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`
+25 −0
Original line number Diff line number Diff line
@@ -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"
}
 No newline at end of file