git: 6dd86310e54d - main - CTL: add ATF tests for REPORT SUPPORTED OPCODES
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 14 Apr 2026 17:37:23 UTC
The branch main has been updated by asomers:
URL: https://cgit.FreeBSD.org/src/commit/?id=6dd86310e54d3f2dd9f688670913b9176176246c
commit 6dd86310e54d3f2dd9f688670913b9176176246c
Author: Alan Somers <asomers@FreeBSD.org>
AuthorDate: 2026-04-14 17:35:54 +0000
Commit: Alan Somers <asomers@FreeBSD.org>
CommitDate: 2026-04-14 17:36:07 +0000
CTL: add ATF tests for REPORT SUPPORTED OPCODES
This includes a regression test for CVE-2024-42416
MFC after: 2 weeks
Sponsored by: ConnectWise
Reviewed by: emaste
Differential Revision: https://reviews.freebsd.org/D46613
---
tests/sys/cam/ctl/Makefile | 2 +
tests/sys/cam/ctl/all-supported-opcodes.txt | 39 +++++
tests/sys/cam/ctl/opcodes.sh | 241 ++++++++++++++++++++++++++++
3 files changed, 282 insertions(+)
diff --git a/tests/sys/cam/ctl/Makefile b/tests/sys/cam/ctl/Makefile
index 05f0831fc8b0..4707a2f4b357 100644
--- a/tests/sys/cam/ctl/Makefile
+++ b/tests/sys/cam/ctl/Makefile
@@ -3,8 +3,10 @@ PACKAGE= tests
TESTSDIR= ${TESTSBASE}/sys/cam/ctl
BINDIR=${TESTSDIR}
+${PACKAGE}FILES+= all-supported-opcodes.txt
${PACKAGE}FILES+= ctl.subr
+ATF_TESTS_SH+= opcodes
ATF_TESTS_SH+= persist
ATF_TESTS_SH+= prevent
ATF_TESTS_SH+= read_buffer
diff --git a/tests/sys/cam/ctl/all-supported-opcodes.txt b/tests/sys/cam/ctl/all-supported-opcodes.txt
new file mode 100644
index 000000000000..d1725b5a7c80
--- /dev/null
+++ b/tests/sys/cam/ctl/all-supported-opcodes.txt
@@ -0,0 +1,39 @@
+ 00 00 00 02 60 00 00 00 00 00 00 00 06 03 00 00 00
+ 10 00 00 00 06 04 00 00 00 00 00 00 06 08 00 00 00
+ 20 00 00 00 06 0a 00 00 00 00 00 00 06 12 00 00 00
+ 30 00 00 00 06 15 00 00 00 00 00 00 06 16 00 00 00
+ 40 00 00 00 06 17 00 00 00 00 00 00 06 1a 00 00 00
+ 50 00 00 00 06 1b 00 00 00 00 00 00 06 1e 00 00 00
+ 60 00 00 00 06 25 00 00 00 00 00 00 0a 28 00 00 00
+ 70 00 00 00 0a 2a 00 00 00 00 00 00 0a 2e 00 00 00
+ 80 00 00 00 0a 2f 00 00 00 00 00 00 0a 35 00 00 00
+ 90 00 00 00 0a 37 00 00 00 00 00 00 0a 3b 00 00 02
+ a0 00 01 00 0a 3c 00 00 02 00 01 00 0a 3c 00 00 03
+ b0 00 01 00 0a 3c 00 00 0b 00 01 00 0a 41 00 00 00
+ c0 00 00 00 0a 42 00 00 00 00 00 00 0a 4d 00 00 00
+ d0 00 00 00 0a 55 00 00 00 00 00 00 0a 56 00 00 00
+ e0 00 00 00 0a 57 00 00 00 00 00 00 0a 5a 00 00 00
+ f0 00 00 00 0a 5e 00 00 00 00 01 00 0a 5e 00 00 01
+ 100 00 01 00 0a 5e 00 00 02 00 01 00 0a 5e 00 00 03
+ 110 00 01 00 0a 5f 00 00 00 00 01 00 0a 5f 00 00 01
+ 120 00 01 00 0a 5f 00 00 02 00 01 00 0a 5f 00 00 03
+ 130 00 01 00 0a 5f 00 00 04 00 01 00 0a 5f 00 00 05
+ 140 00 01 00 0a 5f 00 00 06 00 01 00 0a 83 00 00 00
+ 150 00 01 00 10 83 00 00 01 00 01 00 10 83 00 00 10
+ 160 00 01 00 10 83 00 00 11 00 01 00 10 83 00 00 1c
+ 170 00 01 00 10 84 00 00 00 00 01 00 10 84 00 00 03
+ 180 00 01 00 10 84 00 00 04 00 01 00 10 84 00 00 05
+ 190 00 01 00 10 84 00 00 07 00 01 00 10 84 00 00 08
+ 1a0 00 01 00 10 88 00 00 00 00 00 00 10 89 00 00 00
+ 1b0 00 00 00 10 8a 00 00 00 00 00 00 10 8e 00 00 00
+ 1c0 00 00 00 10 8f 00 00 00 00 00 00 10 91 00 00 00
+ 1d0 00 00 00 10 93 00 00 00 00 00 00 10 9b 00 00 02
+ 1e0 00 01 00 10 9b 00 00 03 00 01 00 10 9b 00 00 0b
+ 1f0 00 01 00 10 9c 00 00 00 00 00 00 10 9e 00 00 10
+ 200 00 01 00 10 9e 00 00 12 00 01 00 10 a0 00 00 00
+ 210 00 00 00 0c a3 00 00 05 00 01 00 0c a3 00 00 0a
+ 220 00 01 00 0c a3 00 00 0c 00 01 00 0c a3 00 00 0d
+ 230 00 01 00 0c a3 00 00 0f 00 01 00 0c a8 00 00 00
+ 240 00 00 00 0c aa 00 00 00 00 00 00 0c ae 00 00 00
+ 250 00 00 00 0c af 00 00 00 00 00 00 0c b7 00 00 00
+ 260 00 00 00 0c
diff --git a/tests/sys/cam/ctl/opcodes.sh b/tests/sys/cam/ctl/opcodes.sh
new file mode 100644
index 000000000000..1d558a1095a0
--- /dev/null
+++ b/tests/sys/cam/ctl/opcodes.sh
@@ -0,0 +1,241 @@
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2024 Axcient
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS DOCUMENTATION IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Not Tested
+# * Allocation length, because sg3_utils 1.48 does not provide a way to set it.
+# * RCTD bit, because CTL does not support it.
+
+. $(atf_get_srcdir)/ctl.subr
+
+require_sg_opcodes_version()
+{
+ WANT=$1
+ HAVE=$(sg_opcodes -V 2>&1 | cut -w -f 3)
+ if [ `echo "$HAVE >= $WANT" | bc -l` = 0 ]; then
+ atf_skip "This test requires sg_opcodes $WANT or greater"
+ fi
+}
+
+# Query all supported opcodes.
+# NB: the fixture here may need to change frequently, any time CTL gains
+# support for new opcodes or service actions.
+atf_test_case all_opcodes cleanup
+all_opcodes_head()
+{
+ atf_set "descr" "REPORT SUPPORTED OPCODES can report all supported opcodes"
+ atf_set "require.user" "root"
+ atf_set "require.progs" sg_opcodes
+}
+all_opcodes_body()
+{
+ create_ramdisk
+
+ atf_check -o file:$(atf_get_srcdir)/all-supported-opcodes.txt sg_opcodes -p disk -nH /dev/$dev
+}
+all_opcodes_cleanup()
+{
+ cleanup
+}
+
+# Query support for a single opcode. The REPORTING OPTIONS field will be 1 and
+# REQUESTED SERVICE ACTION will be zero.
+atf_test_case basic cleanup
+basic_head()
+{
+ atf_set "descr" "REPORT SUPPORTED OPCODES can report a single supported opcode"
+ atf_set "require.user" "root"
+ atf_set "require.progs" sg_opcodes
+}
+basic_body()
+{
+ create_ramdisk
+
+ atf_check -o inline:" 00 00 03 00 0a 28 1a ff ff ff ff 00 ff ff 07\n" sg_opcodes -o 0x28 -p disk -nH /dev/$dev
+}
+basic_cleanup()
+{
+ cleanup
+}
+
+atf_test_case invalid_rep_opts cleanup
+invalid_rep_opts_head()
+{
+ atf_set "descr" "REPORT SUPPORTED OPCODES will fail gracefully if the REPORTING OPTIONS field is set to an invalid value"
+ atf_set "require.user" "root"
+ atf_set "require.progs" sg_opcodes
+}
+invalid_rep_opts_body()
+{
+ require_sg_opcodes_version 1.03
+ create_ramdisk
+
+ atf_check -o ignore -e ignore -s exit:5 sg_opcodes -o 0x28 -p disk -n --rep-opts=4 /dev/$dev
+}
+invalid_rep_opts_cleanup()
+{
+ cleanup
+}
+
+# Try to query support for an opcode that needs a service action, but without
+# specifying a service action.
+atf_test_case missing_service_action cleanup
+missing_service_action_head()
+{
+ atf_set "descr" "REPORT SUPPORTED OPCODES fails gracefully if the service action is omitted"
+ atf_set "require.user" "root"
+ atf_set "require.progs" sg_opcodes
+}
+missing_service_action_body()
+{
+ create_ramdisk
+
+ atf_check -e ignore -s exit:5 sg_opcodes -o 0x3c -p disk -n /dev/$dev
+}
+missing_service_action_cleanup()
+{
+ cleanup
+}
+
+# Regression test for CVE-2024-42416
+atf_test_case out_of_bounds_service_action cleanup
+out_of_bounds_service_action_head()
+{
+ atf_set "descr" "REPORT SUPPORTED OPCODES fails gracefully if the requested service action is out of bounds"
+ atf_set "require.user" "root"
+ atf_set "require.progs" sg_opcodes
+}
+out_of_bounds_service_action_body()
+{
+ require_sg_opcodes_version 1.03
+ create_ramdisk
+
+ # opcode 0 (Test Unit Ready) does not take service actions
+ # opcode 0x3c (Read Buffer(10)) does take service actions
+ for opcode in 0 0x3c; do
+ for ro in 2 3; do
+ for sa in 32 100 255 256 10000 65535; do
+ atf_check -s exit:5 -o ignore -e ignore sg_opcodes --rep-opts=$ro -o $opcode -s $sa -p disk -nH /dev/$dev
+ done
+ done
+ done
+}
+out_of_bounds_service_action_cleanup()
+{
+ cleanup
+}
+
+# Query support for an opcode that needs a service action
+atf_test_case service_action cleanup
+service_action_head()
+{
+ atf_set "descr" "REPORT SUPPORTED OPCODES can query an opcode that needs a service action"
+ atf_set "require.user" "root"
+ atf_set "require.progs" sg_opcodes
+}
+service_action_body()
+{
+ create_ramdisk
+
+ atf_check -o inline:" 00 00 03 00 0a 3c 02 00 ff ff ff ff ff ff 07\n" sg_opcodes -o 0x3c -s 2 -p disk -nH /dev/$dev
+}
+service_action_cleanup()
+{
+ cleanup
+}
+
+# Try to query support for an opcode that does not need a service action, but
+# provide one anyway.
+atf_test_case unexpected_service_action cleanup
+unexpected_service_action_head()
+{
+ atf_set "descr" "REPORT SUPPORTED OPCODES fails gracefully if an extraneous service action is provided"
+ atf_set "require.user" "root"
+ atf_set "require.progs" sg_opcodes
+}
+unexpected_service_action_body()
+{
+ create_ramdisk
+
+ atf_check -e ignore -s exit:5 sg_opcodes -o 0x28 -s 1 -p disk -n /dev/$dev
+}
+unexpected_service_action_cleanup()
+{
+ cleanup
+}
+
+# Try to query support for an opcode that does not need a service action, but
+# provide one anyway. Set REPORTING OPTIONS to 3. This requests that the
+# command be reported as unsupported, but REQUEST SUPPORTED OPCODES will return
+# successfully.
+atf_test_case unexpected_service_action_ro3 cleanup
+unexpected_service_action_ro3_head()
+{
+ atf_set "descr" "REPORT SUPPORTED OPCODES fails gracefully if an extraneous service action is provided, using REPORTING OPTIONS 3"
+ atf_set "require.user" "root"
+ atf_set "require.progs" sg_opcodes
+}
+unexpected_service_action_ro3_body()
+{
+ require_sg_opcodes_version 1.03
+ create_ramdisk
+
+ atf_check -e ignore -o inline:" 00 00 01 00 00\n" sg_opcodes --rep-opts=3 -o 0xb7 -s 1 -p disk -nH /dev/$dev
+}
+unexpected_service_action_ro3_cleanup()
+{
+ cleanup
+}
+
+atf_test_case unsupported_opcode cleanup
+unsupported_opcode_head()
+{
+ atf_set "descr" "REPORT SUPPORTED OPCODES can report a single unsupported opcode"
+ atf_set "require.user" "root"
+ atf_set "require.progs" sg_opcodes
+}
+unsupported_opcode_body()
+{
+ create_ramdisk
+
+ atf_check -o inline:" 00 00 01 00 00\n" sg_opcodes -o 1 -p disk -nH /dev/$dev
+}
+unsupported_opcode_cleanup()
+{
+ cleanup
+}
+
+
+atf_init_test_cases()
+{
+ atf_add_test_case all_opcodes
+ atf_add_test_case basic
+ atf_add_test_case invalid_rep_opts
+ atf_add_test_case missing_service_action
+ atf_add_test_case out_of_bounds_service_action
+ atf_add_test_case service_action
+ atf_add_test_case unsupported_opcode
+ atf_add_test_case unexpected_service_action
+ atf_add_test_case unexpected_service_action_ro3
+}