From 4618c3c6fe1759777db7598ed0f54884967e64a2 Mon Sep 17 00:00:00 2001
From: zuohsh <zuohongsheng@kylinos.cn>
Date: Mon, 27 Jul 2026 10:53:37 +0800
Subject: [PATCH] tests: chgrp: test --preserve-root within a chroot env

* tests/local.mk: reference the new test.
* tests/chgrp/preserve-root.sh: the new file.
---
 tests/chgrp/preserve-root.sh | 84 ++++++++++++++++++++++++++++++++++++
 tests/local.mk               |  1 +
 2 files changed, 85 insertions(+)
 create mode 100755 tests/chgrp/preserve-root.sh

diff --git a/tests/chgrp/preserve-root.sh b/tests/chgrp/preserve-root.sh
new file mode 100755
index 000000000..6cf5798ce
--- /dev/null
+++ b/tests/chgrp/preserve-root.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+# Test --preserve-root and --no-preserve-root options
+
+# Copyright (C) 2026 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+srcdir=$PWD
+. "${srcdir}/tests/init.sh"; path_prepend_ ./src
+print_ver_ chgrp
+require_root_
+
+# Create a safe chroot environment for testing
+chroot_dir="$PWD/chroot_test"
+mkdir -p "$chroot_dir"/{bin,lib,lib64,etc,dev,tmp} || framework_failure_
+# Copy essential files for chroot to work
+cp /bin/sh "$chroot_dir/bin/" 2>/dev/null || \
+  cp /usr/bin/sh "$chroot_dir/bin/sh" 2>/dev/null || framework_failure_
+
+# Copy required libraries if any
+ldd $chroot_dir/bin/sh 2>/dev/null | grep -o '/lib[^ ]*' | while read lib; do
+  test -f "$lib" && cp "$lib" "$chroot_dir/lib/" 2>/dev/null
+done
+
+pwd
+# Copy chgrp binary to chroot
+cp ${srcdir}/src/chgrp "$chroot_dir/bin/chgrp" || framework_failure_
+
+# Copy chgrp's required libraries
+ldd $chroot_dir/bin/chgrp | grep -o '/lib[^ ]*' | while read lib; do
+  test -f "$lib" && cp "$lib" "$chroot_dir/lib/" 2>/dev/null
+  test -f "$lib" && cp "$lib" "$chroot_dir/lib64/" 2>/dev/null
+done
+
+# Create minimal device nodes
+mknod "$chroot_dir/dev/null" c 1 3 2>/dev/null || true
+chmod 666 "$chroot_dir/dev/null" 2>/dev/null || true
+
+# Test 1: --preserve-root should refuse recursive operation on /
+echo "=== Test 1: preserve-root on / ===" >&2
+chroot "$chroot_dir" /bin/chgrp -R --preserve-root 1 / 2>out && fail=1
+echo "=== Test 1 output ===" >&2
+cat out >&2
+echo "=== End Test 1 output ===" >&2
+grep "it is dangerous to operate recursively.*'/'" out >/dev/null || fail=1
+
+# Test 2: --no-preserve-root should allow the operation
+chroot "$chroot_dir" /bin/chgrp -R --no-preserve-root 1 / 2>out
+grep "it is dangerous to operate recursively" out >/dev/null && fail=1
+
+# Test 3: Default behavior should be --no-preserve-root
+chroot "$chroot_dir" /bin/chgrp -R 1 / 2>out
+grep "it is dangerous to operate recursively" out >/dev/null && fail=1
+
+# Test 4: Verify preserve-root works correctly
+chroot "$chroot_dir" /bin/chgrp -R --preserve-root 1 / 2>out && fail=1
+grep "it is dangerous to operate recursively.*'/'" out >/dev/null || fail=1
+
+# Test 5: Verify --no-preserve-root with symlink options
+# Re-create directory structure in case it was modified by previous tests
+rm -rf "$chroot_dir/dir_link"
+mkdir -p "$chroot_dir/dir_link" || framework_failure_
+ln -s / "$chroot_dir/dir_link/sym_link" || framework_failure_
+
+chroot "$chroot_dir" /bin/chgrp -R -H --no-preserve-root 1 /dir_link/sym_link 2>out
+grep "it is dangerous to operate recursively" out >/dev/null && fail=1
+
+chroot "$chroot_dir" /bin/chgrp -R -L --no-preserve-root 1 /dir_link/ 2>out
+grep "it is dangerous to operate recursively" out >/dev/null && fail=1
+
+# the group of files within chroot should be daemon or bin
+ls -l "$chroot_dir/"
+
+Exit $fail
diff --git a/tests/local.mk b/tests/local.mk
index 9414dbf9d..0e0ca3fa5 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -108,6 +108,7 @@ EXTRA_DIST +=			\
 all_root_tests =				\
   tests/chown/basic.sh				\
   tests/chgrp/from.sh				\
+  tests/chgrp/preserve-root.sh			\
   tests/cp/cp-a-selinux.sh			\
   tests/cp/preserve-gid.sh			\
   tests/cp/special-bits.sh			\
-- 
2.43.0

