[LTP] [PATCH 1/2] ioctl_sg01: Skip USB devices

Martin Doucha mdoucha@suse.cz
Wed Oct 22 11:57:37 CEST 2025


Some USB devices write hardware info and flags to the ioctl(SG_IO)
response buffer which results in test failure. But the info is constant
and doesn't represent any security risk. Skip USB devices to prevent
false positives.

Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---

I've tested this patch on kernels v4.4 through v6.16. Non-USB generic SCSI
block devices get correctly found and used, USB block device get skipped.

 testcases/kernel/syscalls/ioctl/ioctl_sg01.c | 55 +++++++++++++++-----
 1 file changed, 42 insertions(+), 13 deletions(-)

diff --git a/testcases/kernel/syscalls/ioctl/ioctl_sg01.c b/testcases/kernel/syscalls/ioctl/ioctl_sg01.c
index fba3816c3..66ff980ce 100644
--- a/testcases/kernel/syscalls/ioctl/ioctl_sg01.c
+++ b/testcases/kernel/syscalls/ioctl/ioctl_sg01.c
@@ -29,6 +29,9 @@
 #include "tst_test.h"
 #include "tst_memutils.h"
 
+#define SYSDIR "/sys/block"
+#define BLOCKDIR "/sys/block/%s/device"
+
 #define BUF_SIZE (128 * 4096)
 #define CMD_SIZE 6
 
@@ -38,42 +41,68 @@ static unsigned char command[CMD_SIZE];
 static struct sg_io_hdr query;
 
 /* TODO: split this off to a separate SCSI library? */
-static const char *find_generic_scsi_device(int access_flags)
+static const char *find_generic_scsi_device(int access_flags, int skip_usb)
 {
-	DIR *devdir;
+	DIR *sysdir;
 	struct dirent *ent;
 	int tmpfd;
-	static char devpath[PATH_MAX];
+	ssize_t length;
+	char *filename;
+	static char devpath[PATH_MAX], syspath[PATH_MAX];
 
-	errno = 0;
-	devdir = opendir("/dev");
+	sysdir = opendir(SYSDIR);
 
-	if (!devdir)
+	if (!sysdir)
 		return NULL;
 
-	while ((ent = SAFE_READDIR(devdir))) {
-		/* The bug is most likely reproducible only on /dev/sg* */
-		if (strncmp(ent->d_name, "sg", 2) || !isdigit(ent->d_name[2]))
+	/* Scan block devices */
+	while ((ent = SAFE_READDIR(sysdir))) {
+		if (ent->d_name[0] == '.')
+			continue;
+
+		snprintf(syspath, PATH_MAX, BLOCKDIR, ent->d_name);
+		syspath[PATH_MAX - 1] = '\0';
+
+		/* Real device path matches the physical HW bus path */
+		if (!realpath(syspath, devpath))
+			continue;
+
+		strncat(devpath, "/generic", PATH_MAX - strlen(devpath) - 1);
+		devpath[PATH_MAX - 1] = '\0';
+		length = readlink(devpath, syspath, PATH_MAX - 1);
+
+		if (length < 0)
+			continue;
+
+		syspath[length] = '\0';
+		filename = basename(syspath);
+
+		/* USB devices often return HW info in SG_IO response buffer */
+		if (skip_usb && strstr(devpath, "/usb")) {
+			tst_res(TINFO, "Skipping USB device %s", filename);
 			continue;
+		}
 
-		snprintf(devpath, PATH_MAX, "/dev/%s", ent->d_name);
+		snprintf(devpath, PATH_MAX, "/dev/%s", filename);
 		/* access() makes incorrect assumptions about block devices */
 		tmpfd = open(devpath, access_flags);
 
 		if (tmpfd >= 0) {
 			SAFE_CLOSE(tmpfd);
-			SAFE_CLOSEDIR(devdir);
+			SAFE_CLOSEDIR(sysdir);
 			return devpath;
 		}
+
+		tst_res(TINFO | TERRNO, "Cannot open device %s", devpath);
 	}
 
-	SAFE_CLOSEDIR(devdir);
+	SAFE_CLOSEDIR(sysdir);
 	return NULL;
 }
 
 static void setup(void)
 {
-	const char *devpath = find_generic_scsi_device(O_RDONLY);
+	const char *devpath = find_generic_scsi_device(O_RDONLY, 1);
 
 	if (!devpath)
 		tst_brk(TCONF, "Could not find any usable SCSI device");
-- 
2.51.0



More information about the ltp mailing list