Skip to content

Commit 060ac36

Browse files
committed
collect: capture the iSCSI transport class for replay
/sys/class/iscsi_transport/<name>/handle is the address of the registering driver's static struct iscsi_transport (CVE-2021-27363), and sysfs_iscsi_transport_handle reads it by enumerating the class. Nothing captured it, so no fixture could reach that leak and the component was exercised only by its unit test. grab_tree cannot capture it: /sys/class/<class>/<name> is a symlink into /sys/devices, and the walk does not follow links — pointed at /sys/class/net it finds no files at all where a link-following walk finds 389. Add grab_class_attr, which resolves each class member and materialises the named attributes as plain files, the shape the replay layer opens. Teaching grab_tree to follow links instead would change what the device-tree and firmware-memmap captures pull in, where a link- following walk risks large or cyclic expansions. The class directory is recorded even when it holds no members: a registered transport class with nothing in it is a different state from an absent one, and the component distinguishes them. Bump version to 2.
1 parent d177fee commit 060ac36

1 file changed

Lines changed: 35 additions & 1 deletion

File tree

extra/collect

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
set -u
2626

2727
PROG=$(basename "$0")
28-
COLLECT_VERSION=1
28+
COLLECT_VERSION=2
2929

3030
die() { echo "$PROG: $*" >&2; exit 2; }
3131
need_val() { [ "$1" -ge 2 ] || die "$2 requires a value"; }
@@ -174,6 +174,34 @@ grab() {
174174
fi
175175
}
176176

177+
# Capture named attributes of every member of a sysfs class. grab_tree cannot:
178+
# /sys/class/<class>/<name> is a symlink into /sys/devices and its walk does not
179+
# follow links. Materialising the attributes as plain files is what the replay
180+
# layer opens, and it keeps the capture to what the analysis reads rather than a
181+
# whole device subtree.
182+
grab_class_attr() {
183+
cls=$1
184+
shift
185+
[ -d "/sys/class/$cls" ] || { echo "absent: /sys/class/$cls" >> "$NOTES"; return 0; }
186+
# Record the class directory even when empty: "registered but no members" is
187+
# a different state from "class absent", and both are worth replaying.
188+
mkdir -p "$OUT/sysroot/sys/class/$cls"
189+
for e in "/sys/class/$cls"/*; do
190+
[ -e "$e" ] || continue
191+
n=$(basename "$e")
192+
for a in "$@"; do
193+
[ -r "$e/$a" ] || continue
194+
mkdir -p "$OUT/sysroot/sys/class/$cls/$n"
195+
if cat "$e/$a" > "$OUT/sysroot/sys/class/$cls/$n/$a" 2>/dev/null; then
196+
:
197+
else
198+
echo "unreadable: /sys/class/$cls/$n/$a" >> "$NOTES"
199+
rm -f "$OUT/sysroot/sys/class/$cls/$n/$a"
200+
fi
201+
done
202+
done
203+
}
204+
177205
# grab_tree DIR — copy a (small) directory subtree into the mirror.
178206
grab_tree() {
179207
d=$1
@@ -242,6 +270,12 @@ do
242270
done
243271

244272
grab_tree /sys/firmware/memmap
273+
274+
# iSCSI transports: `handle` is the address of the registering driver's static
275+
# struct iscsi_transport (CVE-2021-27363), one per transport the host has
276+
# loaded. Read by sysfs_iscsi_transport_handle, which enumerates the class.
277+
grab_class_attr iscsi_transport handle
278+
245279
# Device tree is exposed at both paths depending on arch/kernel; capture both.
246280
grab_tree /proc/device-tree/chosen
247281
grab_tree /proc/device-tree/rtas

0 commit comments

Comments
 (0)