Re: [PATCH v2 1/4] overlay: Add tests for nesting private xattrs

Zorro Lang
2023-12-10T13:35:35Z

On Mon, Dec 04, 2023 at 08:58:56PM +0200, Amir Goldstein wrote:
> If overlayfs xattr escaping is supported, ensure:
> * We can create "overlay.*" xattrs on a file in the overlayfs
> * We can create an xwhiteout file in the overlayfs
>
> We check for nesting support by trying to getattr an "overlay.*" xattr
> in an overlayfs mount, which will return ENOSUPP in older kernels.
>
> Signed-off-by: Alexander Larsson <alexl@redhat.com>
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> ---

Hi Amir,

This test passed with below kernel configuration at first:
CONFIG_OVERLAY_FS=m
# CONFIG_OVERLAY_FS_REDIRECT_DIR is not set
CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y
# CONFIG_OVERLAY_FS_INDEX is not set
# CONFIG_OVERLAY_FS_XINO_AUTO is not set
# CONFIG_OVERLAY_FS_METACOPY is not set

But then I found it fails if I enabled below configurations:
CONFIG_OVERLAY_FS_REDIRECT_DIR=y
CONFIG_OVERLAY_FS_INDEX=y
CONFIG_OVERLAY_FS_XINO_AUTO=y
CONFIG_OVERLAY_FS_METACOPY=y

Without these configures, this test passed. But with them, it fails as [1].
The underlying fs is xfs (with default mkfs options), there're not specific
MOUNT_OPTIONS and MKFS_OPTIONS to use.

I'll delay merging this patchset temporarily, please check.

Thanks,
Zorro

[1]
QA output created by 084

== Check xattr escape trusted ==
# file: SCRATCH_MNT/layer2/dir
trusted.overlay.opaque="y"
user.overlay.opaque="y"

# file: SCRATCH_DEV/mid/layer2/dir
trusted.overlay.overlay.opaque="y"
user.overlay.opaque="y"

mount: /mnt/fstests/SCRATCH_DIR/ovl-mnt: mount(2) system call failed: Stale file handle.
getfattr: /mnt/fstests/SCRATCH_DIR/ovl-mnt/layer2/dir: No such file or directory
nested xattr mount with trusted.overlay
mount: /mnt/fstests/SCRATCH_DIR/nested: special device overlayfs does not exist.
stat: cannot statx 'SCRATCH_DEV/nested/dir/file': No such file or directory
umount: /mnt/fstests/SCRATCH_DIR/nested: not mounted.
nested xattr mount with user.overlay
mount: /mnt/fstests/SCRATCH_DIR/nested: special device overlayfs does not exist.
stat: cannot statx 'SCRATCH_DEV/nested/dir/file': No such file or directory
umount: /mnt/fstests/SCRATCH_DIR/nested: not mounted.
copy-up of escaped xattrs
touch: cannot touch '/mnt/fstests/SCRATCH_DIR/ovl-mnt/layer2/dir/other_file': No such file or directory
getfattr: /mnt/fstests/SCRATCH_DIR/upper/layer2/dir: No such file or directory
umount: /mnt/fstests/SCRATCH_DIR/ovl-mnt: not mounted.

== Check xattr escape user ==
# file: SCRATCH_MNT/layer2/dir
trusted.overlay.opaque="y"
user.overlay.opaque="y"

# file: SCRATCH_DEV/mid/layer2/dir
trusted.overlay.opaque="y"
user.overlay.overlay.opaque="y"

mount: /mnt/fstests/SCRATCH_DIR/ovl-mnt: mount(2) system call failed: Stale file handle.
getfattr: /mnt/fstests/SCRATCH_DIR/ovl-mnt/layer2/dir: No such file or directory
nested xattr mount with trusted.overlay
mount: /mnt/fstests/SCRATCH_DIR/nested: special device overlayfs does not exist.
stat: cannot statx 'SCRATCH_DEV/nested/dir/file': No such file or directory
umount: /mnt/fstests/SCRATCH_DIR/nested: not mounted.
nested xattr mount with user.overlay
mount: /mnt/fstests/SCRATCH_DIR/nested: special device overlayfs does not exist.
stat: cannot statx 'SCRATCH_DEV/nested/dir/file': No such file or directory
umount: /mnt/fstests/SCRATCH_DIR/nested: not mounted.
copy-up of escaped xattrs
touch: cannot touch '/mnt/fstests/SCRATCH_DIR/ovl-mnt/layer2/dir/other_file': No such file or directory
getfattr: /mnt/fstests/SCRATCH_DIR/upper/layer2/dir: No such file or directory
umount: /mnt/fstests/SCRATCH_DIR/ovl-mnt: not mounted.

== Check xwhiteout trusted ==
regular
stat: cannot statx 'SCRATCH_MNT/hidden': No such file or directory

== Check xwhiteout user ==
regular
stat: cannot statx 'SCRATCH_MNT/hidden': No such file or directory

== Check escaped xwhiteout trusted ==
regular
stat: cannot statx 'SCRATCH_MNT/hidden': No such file or directory

== Check escaped xwhiteout user ==
regular
stat: cannot statx 'SCRATCH_MNT/hidden': No such file or directory

> tests/overlay/084 | 169 ++++++++++++++++++++++++++++++++++++++++++
> tests/overlay/084.out | 61 +++++++++++++++
> 2 files changed, 230 insertions(+)
> create mode 100755 tests/overlay/084
> create mode 100644 tests/overlay/084.out
>
> diff --git a/tests/overlay/084 b/tests/overlay/084
> new file mode 100755
> index 00000000..ff451f38
> --- /dev/null
> +++ b/tests/overlay/084
> @@ -0,0 +1,169 @@
> +#! /bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +# Copyright (C) 2023 Red Hat, Inc. All Rights Reserved.
> +# Copyright (C) 2023 CTERA Networks. All Rights Reserved.
> +#
> +# FS QA Test No. 084
> +#
> +# Test advanded nesting functionallity
> +#
> +. ./common/preamble
> +_begin_fstest auto quick nested
> +
> +# Override the default cleanup function.
> +_cleanup()
> +{
> + cd /
> + # Unmount nested mounts if things fail
> + $UMOUNT_PROG $OVL_BASE_SCRATCH_MNT/nested 2>/dev/null
> + rm -rf $tmp
> +}
> +
> +# Import common functions.
> +. ./common/filter
> +. ./common/attr
> +
> +# real QA test starts here
> +_supported_fs overlay
> +# We use non-default scratch underlying overlay dirs, we need to check
> +# them explicity after test.
> +_require_scratch_nocheck
> +_require_scratch_overlay_xattr_escapes
> +
> +# remove all files from previous tests
> +_scratch_mkfs
> +
> +lowerdir=$OVL_BASE_SCRATCH_MNT/lower
> +middir=$OVL_BASE_SCRATCH_MNT/mid
> +upperdir=$OVL_BASE_SCRATCH_MNT/upper
> +workdir=$OVL_BASE_SCRATCH_MNT/workdir
> +nesteddir=$OVL_BASE_SCRATCH_MNT/nested
> +
> +umount_overlay()
> +{
> + $UMOUNT_PROG $SCRATCH_MNT
> +}
> +
> +test_escape()
> +{
> + local prefix=$1
> +
> + echo -e "\n== Check xattr escape $prefix =="
> +
> + local extra_options=""
> + if [ "$prefix" == "user" ]; then
> + extra_options="-o userxattr"
> + fi
> +
> + _scratch_mkfs
> + mkdir -p $lowerdir $middir $upperdir $workdir $nesteddir
> +
> + _overlay_scratch_mount_dirs $lowerdir $middir $workdir $extra_options
> +
> + mkdir -p $SCRATCH_MNT/layer1/dir/ $SCRATCH_MNT/layer2/dir
> +
> + touch $SCRATCH_MNT/layer1/dir/file
> +
> + # Make layer2/dir an opaque file
> + # Only one of these will be escaped, but both should succeed
> + setfattr -n user.overlay.opaque -v "y" $SCRATCH_MNT/layer2/dir
> + setfattr -n trusted.overlay.opaque -v "y" $SCRATCH_MNT/layer2/dir
> +
> + getfattr -m "overlay\\." --absolute-names -d $SCRATCH_MNT/layer2/dir | _filter_scratch
> +
> + umount_overlay
> +
> + getfattr -m "overlay\\." --absolute-names -d $middir/layer2/dir | _filter_scratch
> +
> + # Remount as lower and try again
> + _overlay_scratch_mount_dirs $middir:$lowerdir $upperdir $workdir $extra_options
> +
> + getfattr -m "overlay\\." --absolute-names -d $SCRATCH_MNT/layer2/dir | _filter_scratch
> +
> + # Recursively mount and ensure the opaque dir is working with both trusted and user xattrs
> + echo "nested xattr mount with trusted.overlay"
> + _overlay_mount_dirs $SCRATCH_MNT/layer2:$SCRATCH_MNT/layer1 - - overlayfs $nesteddir
> + stat $nesteddir/dir/file 2>&1 | _filter_scratch
> + $UMOUNT_PROG $nesteddir
> +
> + echo "nested xattr mount with user.overlay"
> + _overlay_mount_dirs $SCRATCH_MNT/layer2:$SCRATCH_MNT/layer1 - - -o userxattr overlayfs $nesteddir
> + stat $nesteddir/dir/file 2>&1 | _filter_scratch
> + $UMOUNT_PROG $nesteddir
> +
> + # Also ensure propagate the escaped xattr when we copy-up layer2/dir
> + echo "copy-up of escaped xattrs"
> + touch $SCRATCH_MNT/layer2/dir/other_file
> + getfattr -m "$prefix.overlay\\.overlay" --absolute-names -d $upperdir/layer2/dir | _filter_scratch
> +
> + umount_overlay
> +}
> +
> +test_escape trusted
> +test_escape user
> +
> +do_test_xwhiteout()
> +{
> + local prefix=$1
> + local basedir=$2
> +
> + local extra_options=""
> + if [ "$prefix" == "user" ]; then
> + extra_options="-o userxattr"
> + fi
> +
> + mkdir -p $basedir/lower $basedir/upper $basedir/work
> + touch $basedir/lower/regular $basedir/lower/hidden $basedir/upper/hidden
> + setfattr -n $prefix.overlay.whiteouts -v "y" $basedir/upper
> + setfattr -n $prefix.overlay.whiteout -v "y" $basedir/upper/hidden
> +
> + # Test the hidden is invisible
> + _overlay_scratch_mount_dirs $basedir/upper:$basedir/lower - - $extra_options
> + ls $SCRATCH_MNT
> + stat $SCRATCH_MNT/hidden 2>&1 | _filter_scratch
> + umount_overlay
> +}
> +
> +# Validate that xwhiteouts work like whiteouts
> +test_xwhiteout()
> +{
> + local prefix=$1
> +
> + echo -e "\n== Check xwhiteout $prefix =="
> +
> + _scratch_mkfs
> +
> + do_test_xwhiteout $prefix $OVL_BASE_SCRATCH_MNT
> +}
> +
> +test_xwhiteout trusted
> +test_xwhiteout user
> +
> +# Validate that (escaped) xwhiteouts work inside a nested overlayfs mount
> +test_escaped_xwhiteout()
> +{
> + local prefix=$1
> +
> + echo -e "\n== Check escaped xwhiteout $prefix =="
> +
> + local extra_options=""
> + if [ "$prefix" == "user" ]; then
> + extra_options="-o userxattr"
> + fi
> +
> + _scratch_mkfs
> + mkdir -p $lowerdir $upperdir $workdir $nesteddir
> +
> + _overlay_mount_dirs $lowerdir $upperdir $workdir $extra_options overlayfs $nesteddir
> +
> + do_test_xwhiteout $prefix $nesteddir
> +
> + $UMOUNT_PROG $nesteddir
> +}
> +
> +test_escaped_xwhiteout trusted
> +test_escaped_xwhiteout user
> +
> +# success, all done
> +status=0
> +exit
> diff --git a/tests/overlay/084.out b/tests/overlay/084.out
> new file mode 100644
> index 00000000..54b890de
> --- /dev/null
> +++ b/tests/overlay/084.out
> @@ -0,0 +1,61 @@
> +QA output created by 084
> +
> +== Check xattr escape trusted ==
> +# file: SCRATCH_MNT/layer2/dir
> +trusted.overlay.opaque="y"
> +user.overlay.opaque="y"
> +
> +# file: SCRATCH_DEV/mid/layer2/dir
> +trusted.overlay.overlay.opaque="y"
> +user.overlay.opaque="y"
> +
> +# file: SCRATCH_MNT/layer2/dir
> +trusted.overlay.opaque="y"
> +user.overlay.opaque="y"
> +
> +nested xattr mount with trusted.overlay
> +stat: cannot statx 'SCRATCH_DEV/nested/dir/file': No such file or directory
> +nested xattr mount with user.overlay
> +stat: cannot statx 'SCRATCH_DEV/nested/dir/file': No such file or directory
> +copy-up of escaped xattrs
> +# file: SCRATCH_DEV/upper/layer2/dir
> +trusted.overlay.overlay.opaque="y"
> +
> +
> +== Check xattr escape user ==
> +# file: SCRATCH_MNT/layer2/dir
> +trusted.overlay.opaque="y"
> +user.overlay.opaque="y"
> +
> +# file: SCRATCH_DEV/mid/layer2/dir
> +trusted.overlay.opaque="y"
> +user.overlay.overlay.opaque="y"
> +
> +# file: SCRATCH_MNT/layer2/dir
> +trusted.overlay.opaque="y"
> +user.overlay.opaque="y"
> +
> +nested xattr mount with trusted.overlay
> +stat: cannot statx 'SCRATCH_DEV/nested/dir/file': No such file or directory
> +nested xattr mount with user.overlay
> +stat: cannot statx 'SCRATCH_DEV/nested/dir/file': No such file or directory
> +copy-up of escaped xattrs
> +# file: SCRATCH_DEV/upper/layer2/dir
> +user.overlay.overlay.opaque="y"
> +
> +
> +== Check xwhiteout trusted ==
> +regular
> +stat: cannot statx 'SCRATCH_MNT/hidden': No such file or directory
> +
> +== Check xwhiteout user ==
> +regular
> +stat: cannot statx 'SCRATCH_MNT/hidden': No such file or directory
> +
> +== Check escaped xwhiteout trusted ==
> +regular
> +stat: cannot statx 'SCRATCH_MNT/hidden': No such file or directory
> +
> +== Check escaped xwhiteout user ==
> +regular
> +stat: cannot statx 'SCRATCH_MNT/hidden': No such file or directory
> --
> 2.34.1
>