mirror of
https://github.com/uutils/coreutils.git
synced 2026-10-28 10:45:25 +08:00
util: factor the shared setup of the check-*.sh scripts into check-common.sh
This commit is contained in:
1 parent
62d40de5ab
commit
e006771dd0
4 files changed
+123
-203
No files matched your search
Executable
+87
@@ -0,0 +1,87 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Shared setup for the util/check-*.sh syscall verification scripts
|
||||
# (check-safe-traversal.sh, check-toctou.sh, check-libc-interposition.sh).
|
||||
#
|
||||
# Source it after setting CHECK_UTILS to the utilities the caller exercises:
|
||||
#
|
||||
# CHECK_UTILS="mkfifo touch head"
|
||||
# . "$(dirname "${BASH_SOURCE[0]}")/check-common.sh"
|
||||
#
|
||||
# It provides $PROJECT_ROOT, a $TEMP_DIR cleaned up on exit, fail_immediately(),
|
||||
# require_command(), and util_cmd()/have_util() to resolve a utility to a
|
||||
# runnable command whether the tree was built as individual binaries or as the
|
||||
# multicall binary.
|
||||
|
||||
: "${PROFILE:=release-small}"
|
||||
export PROFILE
|
||||
|
||||
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
BIN_DIR="$PROJECT_ROOT/target/$PROFILE"
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$TEMP_DIR"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
fail_immediately() {
|
||||
echo "❌ FAILED: $1"
|
||||
# Only the strace-based checks leave logs behind; mention them if they exist.
|
||||
if compgen -G "$TEMP_DIR/strace_*.log" >/dev/null; then
|
||||
echo ""
|
||||
echo "Debug information available in: $TEMP_DIR/strace_*.log"
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
require_command() {
|
||||
if ! command -v "$1" >/dev/null 2>&1; then
|
||||
echo "Error: $1 is required to run these checks"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Prefer individual binaries: they are what CI builds, and tracing them avoids
|
||||
# the multicall dispatch noise. Fall back to the multicall binary otherwise.
|
||||
detect_binaries() {
|
||||
local util
|
||||
for util in $CHECK_UTILS; do
|
||||
if [ -f "$BIN_DIR/$util" ]; then
|
||||
echo "Using individual binaries"
|
||||
USE_MULTICALL=0
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -f "$BIN_DIR/coreutils" ]; then
|
||||
echo "Using multicall binary"
|
||||
USE_MULTICALL=1
|
||||
COREUTILS_BIN="$BIN_DIR/coreutils"
|
||||
MULTICALL_UTILS=$("$COREUTILS_BIN" --list)
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Error: No binaries found. Please build first with 'cargo build --profile=$PROFILE'"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Resolve a utility to a runnable command, or return 1 when it was not built.
|
||||
# A multicall binary built without the unix feature set has no chmod or chown
|
||||
# in it, so ask it what it actually dispatches.
|
||||
util_cmd() {
|
||||
local util="$1"
|
||||
if [ "$USE_MULTICALL" -eq 1 ]; then
|
||||
grep -qx "$util" <<<"$MULTICALL_UTILS" || return 1
|
||||
echo "$COREUTILS_BIN $util"
|
||||
else
|
||||
[ -f "$BIN_DIR/$util" ] || return 1
|
||||
echo "$BIN_DIR/$util"
|
||||
fi
|
||||
}
|
||||
|
||||
have_util() {
|
||||
util_cmd "$1" >/dev/null
|
||||
}
|
||||
|
||||
detect_binaries
|
||||
@@ -13,59 +13,13 @@
|
||||
|
||||
set -e
|
||||
|
||||
: "${PROFILE:=release-small}"
|
||||
export PROFILE
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
|
||||
fail_immediately() {
|
||||
echo "❌ FAILED: $1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$TEMP_DIR"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
echo "=== libc Interposition Verification ==="
|
||||
|
||||
if [ -f "$PROJECT_ROOT/target/${PROFILE}/chmod" ]; then
|
||||
echo "Using individual binaries"
|
||||
USE_MULTICALL=0
|
||||
elif [ -f "$PROJECT_ROOT/target/${PROFILE}/coreutils" ]; then
|
||||
echo "Using multicall binary"
|
||||
USE_MULTICALL=1
|
||||
COREUTILS_BIN="$PROJECT_ROOT/target/${PROFILE}/coreutils"
|
||||
MULTICALL_UTILS=$("$COREUTILS_BIN" --list)
|
||||
else
|
||||
echo "Error: No binaries found. Please build first with 'cargo build --profile=${PROFILE}'"
|
||||
exit 1
|
||||
fi
|
||||
# shellcheck disable=SC2034 # read by check-common.sh once sourced
|
||||
CHECK_UTILS="chmod chown"
|
||||
. "$(dirname "${BASH_SOURCE[0]}")/check-common.sh"
|
||||
|
||||
if ! command -v fakeroot >/dev/null 2>&1; then
|
||||
echo "Error: fakeroot is required to observe libc interposition"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Resolve a utility to a runnable command, or return 1 when it was not built.
|
||||
util_cmd() {
|
||||
local util="$1"
|
||||
if [ "$USE_MULTICALL" -eq 1 ]; then
|
||||
# A multicall binary built without the unix feature set has no chmod or
|
||||
# chown in it, so ask it what it actually dispatches.
|
||||
if ! grep -qx "$util" <<<"$MULTICALL_UTILS"; then
|
||||
return 1
|
||||
fi
|
||||
echo "$COREUTILS_BIN $util"
|
||||
elif [ -f "$PROJECT_ROOT/target/${PROFILE}/$util" ]; then
|
||||
echo "$PROJECT_ROOT/target/${PROFILE}/$util"
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
require_command fakeroot
|
||||
|
||||
# Run a utility under fakeroot and compare what fakeroot's database reports
|
||||
# afterwards against what the utility asked for. A raw syscall leaves the
|
||||
|
||||
@@ -6,41 +6,13 @@
|
||||
|
||||
set -e
|
||||
|
||||
: ${PROFILE:=release-small}
|
||||
export PROFILE
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
|
||||
# Function to exit immediately on error
|
||||
fail_immediately() {
|
||||
echo "❌ FAILED: $1"
|
||||
echo ""
|
||||
echo "Debug information available in: $TEMP_DIR/strace_*.log"
|
||||
exit 1
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$TEMP_DIR"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
echo "=== Safe Traversal Verification ==="
|
||||
|
||||
# Assume binaries are already built (for CI usage)
|
||||
# Prefer individual binaries for more accurate testing
|
||||
if [ -f "$PROJECT_ROOT/target/${PROFILE}/rm" ]; then
|
||||
echo "Using individual binaries"
|
||||
USE_MULTICALL=0
|
||||
elif [ -f "$PROJECT_ROOT/target/${PROFILE}/coreutils" ]; then
|
||||
echo "Using multicall binary"
|
||||
USE_MULTICALL=1
|
||||
COREUTILS_BIN="$PROJECT_ROOT/target/${PROFILE}/coreutils"
|
||||
else
|
||||
echo "Error: No binaries found. Please build first with 'cargo build --profile=${PROFILE}'"
|
||||
exit 1
|
||||
fi
|
||||
# shellcheck disable=SC2034 # read by check-common.sh once sourced
|
||||
CHECK_UTILS="rm chmod chown chgrp du mv cp chcon split"
|
||||
. "$(dirname "${BASH_SOURCE[0]}")/check-common.sh"
|
||||
|
||||
require_command strace
|
||||
|
||||
cd "$TEMP_DIR"
|
||||
|
||||
@@ -63,20 +35,12 @@ check_utility() {
|
||||
|
||||
local strace_log="strace_${util}_${test_name}.log"
|
||||
|
||||
# Choose binary to use
|
||||
if [ "$USE_MULTICALL" -eq 1 ]; then
|
||||
local util_cmd="$COREUTILS_BIN $util"
|
||||
else
|
||||
local util_path="$PROJECT_ROOT/target/${PROFILE}/$util"
|
||||
if [ ! -f "$util_path" ]; then
|
||||
fail_immediately "$util binary not found at $util_path"
|
||||
fi
|
||||
local util_cmd="$util_path"
|
||||
fi
|
||||
local cmd
|
||||
cmd=$(util_cmd "$util") || fail_immediately "$util binary not found in $BIN_DIR"
|
||||
|
||||
# Run utility under strace
|
||||
strace -f -e trace="$trace_syscalls" -o "$strace_log" \
|
||||
$util_cmd $test_args 2>/dev/null || true
|
||||
$cmd $test_args 2>/dev/null || true
|
||||
cat $strace_log
|
||||
# Check for expected safe syscalls
|
||||
local found_safe=0
|
||||
@@ -186,20 +150,8 @@ assert_descent_nofollow() {
|
||||
echo "✓ $util descent opens use O_NOFOLLOW"
|
||||
}
|
||||
|
||||
# Get list of available utilities
|
||||
if [ "$USE_MULTICALL" -eq 1 ]; then
|
||||
AVAILABLE_UTILS=$($COREUTILS_BIN --list)
|
||||
else
|
||||
AVAILABLE_UTILS=""
|
||||
for util in rm chmod chown chgrp du mv cp chcon split; do
|
||||
if [ -f "$PROJECT_ROOT/target/${PROFILE}/$util" ]; then
|
||||
AVAILABLE_UTILS="$AVAILABLE_UTILS $util"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Test rm - should use openat, unlinkat, newfstatat
|
||||
if echo "$AVAILABLE_UTILS" | grep -q "rm"; then
|
||||
if have_util rm; then
|
||||
cp -r test_dir test_rm
|
||||
check_utility "rm" "openat,unlinkat,newfstatat,unlink,rmdir" "openat" "-rf test_rm" "recursive_remove"
|
||||
|
||||
@@ -214,7 +166,7 @@ if echo "$AVAILABLE_UTILS" | grep -q "rm"; then
|
||||
fi
|
||||
|
||||
# Test chmod - should use openat, fchmodat, newfstatat
|
||||
if echo "$AVAILABLE_UTILS" | grep -q "chmod"; then
|
||||
if have_util chmod; then
|
||||
cp -r test_dir test_chmod
|
||||
check_utility "chmod" "openat,fchmodat,fchmodat2,newfstatat,chmod" "openat fchmodat" "-R 755 test_chmod" "recursive_chmod"
|
||||
|
||||
@@ -226,7 +178,7 @@ if echo "$AVAILABLE_UTILS" | grep -q "chmod"; then
|
||||
fi
|
||||
|
||||
# Test chown - should use openat, fchownat, newfstatat
|
||||
if echo "$AVAILABLE_UTILS" | grep -q "chown"; then
|
||||
if have_util chown; then
|
||||
cp -r test_dir test_chown
|
||||
USER_ID=$(id -u)
|
||||
GROUP_ID=$(id -g)
|
||||
@@ -235,7 +187,7 @@ if echo "$AVAILABLE_UTILS" | grep -q "chown"; then
|
||||
fi
|
||||
|
||||
# Test chgrp - should use openat, fchownat, newfstatat
|
||||
if echo "$AVAILABLE_UTILS" | grep -q "chgrp"; then
|
||||
if have_util chgrp; then
|
||||
cp -r test_dir test_chgrp
|
||||
check_utility "chgrp" "openat,fchownat,newfstatat,chown,lchown" "openat fchownat" "-R $GROUP_ID test_chgrp" "recursive_chgrp"
|
||||
assert_descent_nofollow "chgrp" strace_chgrp_recursive_chgrp.log
|
||||
@@ -247,12 +199,8 @@ fi
|
||||
# rename/symlink race could redirect a privileged recursive relabel off-tree
|
||||
# (issue #11402). This holds even without SELinux: the fd-anchored open happens
|
||||
# before the SELinux get/set, so the syscalls are observable regardless.
|
||||
if echo "$AVAILABLE_UTILS" | grep -q "chcon"; then
|
||||
if [ "$USE_MULTICALL" -eq 1 ]; then
|
||||
chcon_cmd="$COREUTILS_BIN chcon"
|
||||
else
|
||||
chcon_cmd="$PROJECT_ROOT/target/${PROFILE}/chcon"
|
||||
fi
|
||||
if have_util chcon; then
|
||||
chcon_cmd=$(util_cmd chcon)
|
||||
|
||||
mkdir -p chcon_tree/sub
|
||||
echo a > chcon_tree/file
|
||||
@@ -286,13 +234,13 @@ if echo "$AVAILABLE_UTILS" | grep -q "chcon"; then
|
||||
fi
|
||||
|
||||
# Test du - should use openat, newfstatat
|
||||
if echo "$AVAILABLE_UTILS" | grep -q "du"; then
|
||||
if have_util du; then
|
||||
cp -r test_dir test_du
|
||||
check_utility "du" "openat,newfstatat,stat,lstat" "openat" "-a test_du" "directory_usage"
|
||||
fi
|
||||
|
||||
# Test mv - should use openat, renameat for directory moves
|
||||
if echo "$AVAILABLE_UTILS" | grep -q "mv"; then
|
||||
if have_util mv; then
|
||||
mkdir -p test_mv_src/sub
|
||||
echo "test" > test_mv_src/file.txt
|
||||
echo "test" > test_mv_src/sub/file2.txt
|
||||
@@ -302,12 +250,8 @@ fi
|
||||
# cp invariant checks. Both #10011 (restrictive 0600 destination mode) and
|
||||
# #10017 (O_NOFOLLOW on the -P source) need to hold; verify each on its own
|
||||
# strace.
|
||||
if echo "$AVAILABLE_UTILS" | grep -q "cp"; then
|
||||
if [ "$USE_MULTICALL" -eq 1 ]; then
|
||||
cp_cmd="$COREUTILS_BIN cp"
|
||||
else
|
||||
cp_cmd="$PROJECT_ROOT/target/${PROFILE}/cp"
|
||||
fi
|
||||
if have_util cp; then
|
||||
cp_cmd=$(util_cmd cp)
|
||||
|
||||
# #10011: destination created with mode 0600 so other users cannot open
|
||||
# the file through its umask-derived initial mode before cp narrows it.
|
||||
@@ -343,12 +287,8 @@ fi
|
||||
# O_CREAT|O_EXCL and only ever truncates via ftruncate after an fd-based check
|
||||
# that the opened output is not the input -- so a split that would overwrite its
|
||||
# own input is refused.
|
||||
if echo "$AVAILABLE_UTILS" | grep -q "split"; then
|
||||
if [ "$USE_MULTICALL" -eq 1 ]; then
|
||||
split_cmd="$COREUTILS_BIN split"
|
||||
else
|
||||
split_cmd="$PROJECT_ROOT/target/${PROFILE}/split"
|
||||
fi
|
||||
if have_util split; then
|
||||
split_cmd=$(util_cmd split)
|
||||
|
||||
printf '0123456789abcdef' > split_input
|
||||
strace -f -e trace=openat -o strace_split_output_open.log \
|
||||
@@ -380,7 +320,7 @@ if echo "$AVAILABLE_UTILS" | grep -q "split"; then
|
||||
fi
|
||||
|
||||
# mv cross-device (EXDEV) must use fd-based *xattr ops (issue #10014).
|
||||
if echo "$AVAILABLE_UTILS" | grep -q "mv" && [ -d /dev/shm ]; then
|
||||
if have_util mv && [ -d /dev/shm ]; then
|
||||
# Need different filesystems for the EXDEV fallback to fire.
|
||||
temp_fs_id=$(stat -f -c %i "$TEMP_DIR" 2>/dev/null || echo "")
|
||||
shm_fs_id=$(stat -f -c %i /dev/shm 2>/dev/null || echo "")
|
||||
@@ -394,11 +334,7 @@ if echo "$AVAILABLE_UTILS" | grep -q "mv" && [ -d /dev/shm ]; then
|
||||
cross_dst=$(mktemp -u -p /dev/shm cross_dst.XXXXXX)
|
||||
echo "cross-device payload" > "$cross_src"
|
||||
if setfattr -n user.tag -v pinned "$cross_src" 2>/dev/null; then
|
||||
if [ "$USE_MULTICALL" -eq 1 ]; then
|
||||
mv_cmd="$COREUTILS_BIN mv"
|
||||
else
|
||||
mv_cmd="$PROJECT_ROOT/target/${PROFILE}/mv"
|
||||
fi
|
||||
mv_cmd=$(util_cmd mv)
|
||||
strace -f -e trace='%file,fgetxattr,fsetxattr,flistxattr,getxattr,setxattr,listxattr' \
|
||||
-o strace_mv_xattr.log \
|
||||
$mv_cmd "$cross_src" "$cross_dst" 2>/dev/null || true
|
||||
@@ -431,7 +367,7 @@ fi
|
||||
# attacker racing in a planted symlink would otherwise let the copy write
|
||||
# through to the symlink's target. rustix may emit either open(2) or
|
||||
# openat(2) depending on the path, so the check accepts both.
|
||||
if echo "$AVAILABLE_UTILS" | grep -q "mv" && [ -d /dev/shm ]; then
|
||||
if have_util mv && [ -d /dev/shm ]; then
|
||||
temp_fs_id=$(stat -f -c %i "$TEMP_DIR" 2>/dev/null || echo "")
|
||||
shm_fs_id=$(stat -f -c %i /dev/shm 2>/dev/null || echo "")
|
||||
if [ -z "$temp_fs_id" ] || [ -z "$shm_fs_id" ] || [ "$temp_fs_id" = "$shm_fs_id" ]; then
|
||||
@@ -442,11 +378,7 @@ if echo "$AVAILABLE_UTILS" | grep -q "mv" && [ -d /dev/shm ]; then
|
||||
echo "payload" > "$nofollow_src"
|
||||
echo "existing" > "$nofollow_dst"
|
||||
|
||||
if [ "$USE_MULTICALL" -eq 1 ]; then
|
||||
mv_cmd="$COREUTILS_BIN mv"
|
||||
else
|
||||
mv_cmd="$PROJECT_ROOT/target/${PROFILE}/mv"
|
||||
fi
|
||||
mv_cmd=$(util_cmd mv)
|
||||
strace -f -e trace=open,openat,openat2 -o strace_mv_nofollow.log \
|
||||
$mv_cmd -f "$nofollow_src" "$nofollow_dst" 2>/dev/null || true
|
||||
|
||||
@@ -473,7 +405,7 @@ fi
|
||||
# of the parent directory cannot redirect the temp-and-rename dance, and
|
||||
# the temp name must come from /dev/urandom rather than a guessable
|
||||
# pid+nanos pattern.
|
||||
if echo "$AVAILABLE_UTILS" | grep -q "mv" && [ -d /dev/shm ]; then
|
||||
if have_util mv && [ -d /dev/shm ]; then
|
||||
temp_fs_id=$(stat -f -c %i "$TEMP_DIR" 2>/dev/null || echo "")
|
||||
shm_fs_id=$(stat -f -c %i /dev/shm 2>/dev/null || echo "")
|
||||
if [ -z "$temp_fs_id" ] || [ -z "$shm_fs_id" ] || [ "$temp_fs_id" = "$shm_fs_id" ]; then
|
||||
@@ -485,11 +417,7 @@ if echo "$AVAILABLE_UTILS" | grep -q "mv" && [ -d /dev/shm ]; then
|
||||
# Pre-existing dest forces the EEXIST branch into create_symlink_replace.
|
||||
ln -s /elsewhere "$sym_dst"
|
||||
|
||||
if [ "$USE_MULTICALL" -eq 1 ]; then
|
||||
mv_cmd="$COREUTILS_BIN mv"
|
||||
else
|
||||
mv_cmd="$PROJECT_ROOT/target/${PROFILE}/mv"
|
||||
fi
|
||||
mv_cmd=$(util_cmd mv)
|
||||
strace -f -e trace=openat,symlink,symlinkat,rename,renameat,renameat2,unlink,unlinkat,read \
|
||||
-o strace_mv_symlink_replace.log \
|
||||
$mv_cmd "$sym_src" "$sym_dst" 2>/dev/null || true
|
||||
|
||||
+6
-55
@@ -14,67 +14,20 @@
|
||||
|
||||
set -e
|
||||
|
||||
: ${PROFILE:=release-small}
|
||||
export PROFILE
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
|
||||
fail_immediately() {
|
||||
echo "❌ FAILED: $1"
|
||||
echo ""
|
||||
echo "Debug information available in: $TEMP_DIR/strace_*.log"
|
||||
exit 1
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$TEMP_DIR"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
echo "=== TOCTOU Verification ==="
|
||||
|
||||
if [ -f "$PROJECT_ROOT/target/${PROFILE}/coreutils" ]; then
|
||||
echo "Using multicall binary"
|
||||
USE_MULTICALL=1
|
||||
COREUTILS_BIN="$PROJECT_ROOT/target/${PROFILE}/coreutils"
|
||||
elif [ -f "$PROJECT_ROOT/target/${PROFILE}/mkfifo" ]; then
|
||||
echo "Using individual binaries"
|
||||
USE_MULTICALL=0
|
||||
else
|
||||
echo "Error: No binaries found. Build first with 'cargo build --profile=${PROFILE}'"
|
||||
exit 1
|
||||
fi
|
||||
# shellcheck disable=SC2034 # read by check-common.sh once sourced
|
||||
CHECK_UTILS="mkfifo touch head"
|
||||
. "$(dirname "${BASH_SOURCE[0]}")/check-common.sh"
|
||||
|
||||
cd "$TEMP_DIR"
|
||||
|
||||
util_cmd() {
|
||||
if [ "$USE_MULTICALL" -eq 1 ]; then
|
||||
echo "$COREUTILS_BIN $1"
|
||||
else
|
||||
echo "$PROJECT_ROOT/target/${PROFILE}/$1"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$USE_MULTICALL" -eq 1 ]; then
|
||||
AVAILABLE_UTILS=$($COREUTILS_BIN --list)
|
||||
else
|
||||
AVAILABLE_UTILS=""
|
||||
for util in mkfifo touch head; do
|
||||
if [ -f "$PROJECT_ROOT/target/${PROFILE}/$util" ]; then
|
||||
AVAILABLE_UTILS="$AVAILABLE_UTILS $util"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# mkfifo must not call a path-based chmod after creating the FIFO: the
|
||||
# second syscall would re-resolve the path and could be redirected by an
|
||||
# attacker who swaps the FIFO for a symlink in between (issue #10020).
|
||||
# After the fix, the kernel applies the requested mode atomically via
|
||||
# mkfifo with cleared umask.
|
||||
if echo "$AVAILABLE_UTILS" | grep -q "mkfifo"; then
|
||||
mkfifo_cmd=$(util_cmd mkfifo)
|
||||
if mkfifo_cmd=$(util_cmd mkfifo); then
|
||||
rm -f test_fifo
|
||||
# mkfifo(3)/mkfifoat(3) are libc wrappers; the underlying syscall
|
||||
# is mknodat (or mknod on older kernels). Trace those plus any
|
||||
@@ -106,10 +59,9 @@ fi
|
||||
# Test touch - creating a file must use O_CREAT but never O_TRUNC, so that a
|
||||
# symlink planted in the metadata-check/open race window (#10019) is not
|
||||
# truncated. This observes the flags directly, which integration tests cannot.
|
||||
if echo "$AVAILABLE_UTILS" | grep -q "touch"; then
|
||||
if touch_cmd=$(util_cmd touch); then
|
||||
echo ""
|
||||
echo "Testing touch (create_no_truncate)..."
|
||||
touch_cmd=$(util_cmd touch)
|
||||
strace -f -e trace=openat -o strace_touch_create.log $touch_cmd test_touch_new 2>/dev/null || true
|
||||
cat strace_touch_create.log
|
||||
if ! grep -q 'openat(.*test_touch_new.*O_CREAT' strace_touch_create.log; then
|
||||
@@ -126,10 +78,9 @@ fi
|
||||
# descriptor (fstat/statx on the fd), not from a separate path-based stat
|
||||
# performed before the open. A path stat followed by an open is a TOCTOU
|
||||
# window (#11972): the object named by the path can be swapped in between.
|
||||
if echo "$AVAILABLE_UTILS" | grep -q "head"; then
|
||||
if head_cmd=$(util_cmd head); then
|
||||
echo ""
|
||||
echo "Testing head (fstat_after_open)..."
|
||||
head_cmd=$(util_cmd head)
|
||||
echo "headtest" > test_head_file.txt
|
||||
strace -f -e trace=openat,fstat,newfstatat,statx,stat,lstat \
|
||||
-o strace_head_metadata.log $head_cmd -c 4 test_head_file.txt 2>/dev/null || true
|
||||
|
||||
Reference in new issue
Block a user