blob: 31a7b6c38db66daa3b92f6fa57b430f59f3dba28 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
|
#!/hint/bash
# Copyright © Tavian Barnes <tavianator@tavianator.com>
# SPDX-License-Identifier: 0BSD
## Utility functions
# Portable realpath(1)
_realpath() (
cd "$(dirname -- "$1")"
echo "$PWD/$(basename -- "$1")"
)
# Globals
TESTS=$(_realpath "$TESTS")
if [ "${BUILDDIR-}" ]; then
BIN=$(_realpath "$BUILDDIR/bin")
else
BIN=$(_realpath "$TESTS/../bin")
fi
MKSOCK="$BIN/tests/mksock"
XTOUCH="$BIN/tests/xtouch"
UNAME=$(uname)
# Standardize the environment
stdenv() {
export LC_ALL=C
export TZ=UTC0
local SAN_OPTIONS="halt_on_error=1:log_to_syslog=0"
export ASAN_OPTIONS="$SAN_OPTIONS"
export LSAN_OPTIONS="$SAN_OPTIONS"
export MSAN_OPTIONS="$SAN_OPTIONS"
export TSAN_OPTIONS="$SAN_OPTIONS"
export UBSAN_OPTIONS="$SAN_OPTIONS"
export LS_COLORS=""
unset BFS_COLORS
if [ "$UNAME" = Darwin ]; then
# ASan on macOS likes to report
#
# malloc: nano zone abandoned due to inability to preallocate reserved vm space.
#
# to syslog, which as a side effect opens a socket which might take the
# place of one of the standard streams if the process is launched with
# it closed. This environment variable avoids the message.
export MallocNanoZone=0
fi
# Close non-standard inherited fds
if [ -d /proc/self/fd ]; then
local fds=/proc/self/fd
else
local fds=/dev/fd
fi
for fd in "$fds"/*; do
if [ ! -e "$fd" ]; then
continue
fi
local fd="${fd##*/}"
if ((fd > 2)); then
eval "exec ${fd}<&-"
fi
done
# Close stdin so bfs doesn't think we're interactive
# dup() the standard fds for logging even when redirected
exec </dev/null 3>&1 4>&2
}
# Drop root priviliges or bail
drop_root() {
if command -v capsh &>/dev/null; then
if capsh --has-p=cap_dac_override &>/dev/null || capsh --has-p=cap_dac_read_search &>/dev/null; then
if [ -n "${BFS_TRIED_DROP:-}" ]; then
color cat >&2 <<EOF
${RED}error:${RST} Failed to drop capabilities.
EOF
exit 1
fi
color cat >&2 <<EOF
${YLW}warning:${RST} Running as ${BLD}$(id -un)${RST} is not recommended. Dropping ${BLD}cap_dac_override${RST} and
${BLD}cap_dac_read_search${RST}.
EOF
BFS_TRIED_DROP=y exec capsh \
--drop=cap_dac_override,cap_dac_read_search \
--caps=cap_dac_override,cap_dac_read_search-eip \
-- "$0" "$@"
fi
elif ((EUID == 0)); then
UNLESS=
if [ "$UNAME" = "Linux" ]; then
UNLESS=" unless ${GRN}capsh${RST} is installed"
fi
color cat >&2 <<EOF
${RED}error:${RST} These tests expect filesystem permissions to be enforced, and therefore
will not work when run as ${BLD}$(id -un)${RST}${UNLESS}.
EOF
exit 1
fi
}
## Debugging
# Get the bash call stack
callers() {
local frame=0
while caller $frame; do
((++frame))
done
}
# Print a message including path, line number, and command
debug() {
local file="${1/#*\/tests\//tests\/}"
set -- "$file" "${@:2}"
color printf "${BLD}%s:%d:${RST} %s\n %s\n" "$@"
}
## Deferred cleanup
# Quote a command safely for eval
quote() {
printf '%q' "$1"
shift
if (($# > 0)); then
printf ' %q' "$@"
fi
}
# Run a command when this (sub)shell exits
defer() {
# Refresh trap state before trap -p
# See https://unix.stackexchange.com/a/556888/56202
trap -- KILL
# Check if the EXIT trap is already set
if ! trap -p EXIT | grep -q pop_defers; then
DEFER_CMDS=()
DEFER_LINES=()
DEFER_FILES=()
trap pop_defers EXIT
fi
DEFER_CMDS+=("$(quote "$@")")
local line file
read -r line file < <(caller)
DEFER_LINES+=("$line")
DEFER_FILES+=("$file")
}
# Pop a single command from the defer stack and run it
pop_defer() {
local i=$((${#DEFER_CMDS[@]} - 1))
local cmd="${DEFER_CMDS[$i]}"
local file="${DEFER_FILES[$i]}"
local line="${DEFER_LINES[$i]}"
unset "DEFER_CMDS[$i]"
unset "DEFER_FILES[$i]"
unset "DEFER_LINES[$i]"
local ret=0
eval "$cmd" || ret=$?
if ((ret != 0)); then
debug "$file" $line "${RED}error $ret${RST}" "defer $cmd" >&4
fi
return $ret
}
# Run all deferred commands
pop_defers() {
local ret=0
while ((${#DEFER_CMDS[@]} > 0)); do
pop_defer || ret=$?
done
return $ret
}
|