1# SPDX-License-Identifier: BSD-2-Clause 2# 3# Copyright (c) 2024 Axcient 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS DOCUMENTATION IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 26# Not Tested 27# * Allocation length, because sg3_utils 1.48 does not provide a way to set it. 28# * RCTD bit, because CTL does not support it. 29 30. $(atf_get_srcdir)/ctl.subr 31 32require_sg_opcodes_version() 33{ 34 WANT=$1 35 HAVE=$(sg_opcodes -V 2>&1 | cut -w -f 3) 36 if [ `echo "$HAVE >= $WANT" | bc -l` = 0 ]; then 37 atf_skip "This test requires sg_opcodes $WANT or greater" 38 fi 39} 40 41# Query all supported opcodes. 42# NB: the fixture here may need to change frequently, any time CTL gains 43# support for new opcodes or service actions. 44atf_test_case all_opcodes cleanup 45all_opcodes_head() 46{ 47 atf_set "descr" "REPORT SUPPORTED OPCODES can report all supported opcodes" 48 atf_set "require.user" "root" 49 atf_set "require.progs" sg_opcodes ctladm 50} 51all_opcodes_body() 52{ 53 create_ramdisk 54 55 atf_check -o file:$(atf_get_srcdir)/all-supported-opcodes.txt sg_opcodes -p disk -nH /dev/$dev 56} 57all_opcodes_cleanup() 58{ 59 cleanup 60} 61 62# Query support for a single opcode. The REPORTING OPTIONS field will be 1 and 63# REQUESTED SERVICE ACTION will be zero. 64atf_test_case basic cleanup 65basic_head() 66{ 67 atf_set "descr" "REPORT SUPPORTED OPCODES can report a single supported opcode" 68 atf_set "require.user" "root" 69 atf_set "require.progs" sg_opcodes ctladm 70} 71basic_body() 72{ 73 create_ramdisk 74 75 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 76} 77basic_cleanup() 78{ 79 cleanup 80} 81 82atf_test_case invalid_rep_opts cleanup 83invalid_rep_opts_head() 84{ 85 atf_set "descr" "REPORT SUPPORTED OPCODES will fail gracefully if the REPORTING OPTIONS field is set to an invalid value" 86 atf_set "require.user" "root" 87 atf_set "require.progs" sg_opcodes ctladm 88} 89invalid_rep_opts_body() 90{ 91 require_sg_opcodes_version 1.03 92 create_ramdisk 93 94 atf_check -o ignore -e ignore -s exit:5 sg_opcodes -o 0x28 -p disk -n --rep-opts=4 /dev/$dev 95} 96invalid_rep_opts_cleanup() 97{ 98 cleanup 99} 100 101# Try to query support for an opcode that needs a service action, but without 102# specifying a service action. 103atf_test_case missing_service_action cleanup 104missing_service_action_head() 105{ 106 atf_set "descr" "REPORT SUPPORTED OPCODES fails gracefully if the service action is omitted" 107 atf_set "require.user" "root" 108 atf_set "require.progs" sg_opcodes ctladm 109} 110missing_service_action_body() 111{ 112 create_ramdisk 113 114 atf_check -e ignore -s exit:5 sg_opcodes -o 0x3c -p disk -n /dev/$dev 115} 116missing_service_action_cleanup() 117{ 118 cleanup 119} 120 121# Regression test for CVE-2024-42416 122atf_test_case out_of_bounds_service_action cleanup 123out_of_bounds_service_action_head() 124{ 125 atf_set "descr" "REPORT SUPPORTED OPCODES fails gracefully if the requested service action is out of bounds" 126 atf_set "require.user" "root" 127 atf_set "require.progs" sg_opcodes ctladm 128} 129out_of_bounds_service_action_body() 130{ 131 require_sg_opcodes_version 1.03 132 create_ramdisk 133 134 # opcode 0 (Test Unit Ready) does not take service actions 135 # opcode 0x3c (Read Buffer(10)) does take service actions 136 for opcode in 0 0x3c; do 137 for ro in 2 3; do 138 for sa in 32 100 255 256 10000 65535; do 139 atf_check -s exit:5 -o ignore -e ignore sg_opcodes --rep-opts=$ro -o $opcode -s $sa -p disk -nH /dev/$dev 140 done 141 done 142 done 143} 144out_of_bounds_service_action_cleanup() 145{ 146 cleanup 147} 148 149# Query support for an opcode that needs a service action 150atf_test_case service_action cleanup 151service_action_head() 152{ 153 atf_set "descr" "REPORT SUPPORTED OPCODES can query an opcode that needs a service action" 154 atf_set "require.user" "root" 155 atf_set "require.progs" sg_opcodes ctladm 156} 157service_action_body() 158{ 159 create_ramdisk 160 161 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 162} 163service_action_cleanup() 164{ 165 cleanup 166} 167 168# Try to query support for an opcode that does not need a service action, but 169# provide one anyway. 170atf_test_case unexpected_service_action cleanup 171unexpected_service_action_head() 172{ 173 atf_set "descr" "REPORT SUPPORTED OPCODES fails gracefully if an extraneous service action is provided" 174 atf_set "require.user" "root" 175 atf_set "require.progs" sg_opcodes ctladm 176} 177unexpected_service_action_body() 178{ 179 create_ramdisk 180 181 atf_check -e ignore -s exit:5 sg_opcodes -o 0x28 -s 1 -p disk -n /dev/$dev 182} 183unexpected_service_action_cleanup() 184{ 185 cleanup 186} 187 188# Try to query support for an opcode that does not need a service action, but 189# provide one anyway. Set REPORTING OPTIONS to 3. This requests that the 190# command be reported as unsupported, but REQUEST SUPPORTED OPCODES will return 191# successfully. 192atf_test_case unexpected_service_action_ro3 cleanup 193unexpected_service_action_ro3_head() 194{ 195 atf_set "descr" "REPORT SUPPORTED OPCODES fails gracefully if an extraneous service action is provided, using REPORTING OPTIONS 3" 196 atf_set "require.user" "root" 197 atf_set "require.progs" sg_opcodes ctladm 198} 199unexpected_service_action_ro3_body() 200{ 201 require_sg_opcodes_version 1.03 202 create_ramdisk 203 204 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 205} 206unexpected_service_action_ro3_cleanup() 207{ 208 cleanup 209} 210 211atf_test_case unsupported_opcode cleanup 212unsupported_opcode_head() 213{ 214 atf_set "descr" "REPORT SUPPORTED OPCODES can report a single unsupported opcode" 215 atf_set "require.user" "root" 216 atf_set "require.progs" sg_opcodes ctladm 217} 218unsupported_opcode_body() 219{ 220 create_ramdisk 221 222 atf_check -o inline:" 00 00 01 00 00\n" sg_opcodes -o 1 -p disk -nH /dev/$dev 223} 224unsupported_opcode_cleanup() 225{ 226 cleanup 227} 228 229 230atf_init_test_cases() 231{ 232 atf_add_test_case all_opcodes 233 atf_add_test_case basic 234 atf_add_test_case invalid_rep_opts 235 atf_add_test_case missing_service_action 236 atf_add_test_case out_of_bounds_service_action 237 atf_add_test_case service_action 238 atf_add_test_case unsupported_opcode 239 atf_add_test_case unexpected_service_action 240 atf_add_test_case unexpected_service_action_ro3 241} 242