⬢ DragonFlyBSD Kernel Audit
DF-5458 / fix.diff
← back to finding ↓ download raw
--- a/sys/bus/smbus/ichsmb/ichsmb_var.h	2026-10-05 20:08:40.196220622 +0000
+++ b/sys/bus/smbus/ichsmb/ichsmb_var.h	2026-10-05 20:17:56.009094812 +0000
@@ -63,6 +63,7 @@
 	u_char			block_write;	/* 0=read, 1=write */
 	u_char			block_data[32];	/* block read/write data */
 	struct lock		mutex;		/* device mutex */
+	struct lock		xfer_lock;	/* serializes whole transactions */
 };
 typedef struct ichsmb_softc *sc_p;
 
--- a/sys/bus/smbus/ichsmb/ichsmb.c	2026-10-05 20:08:40.192220672 +0000
+++ b/sys/bus/smbus/ichsmb/ichsmb.c	2026-10-05 20:18:26.980697730 +0000
@@ -109,6 +109,7 @@
 
 	/* Create mutex */
 	lockinit(&sc->mutex, "ichsmb", 0, LK_CANRECURSE);
+	lockinit(&sc->xfer_lock, "ichsmbx", 0, 0);
 
 	/* Add child: an instance of the "smbus" device */
 	if ((sc->smb = device_add_child(dev, DRIVER_SMBUS, -1)) == NULL) {
@@ -137,6 +138,7 @@
 	return (0);
 
 fail:
+	lockuninit(&sc->xfer_lock);
 	lockuninit(&sc->mutex);
 	return (error);
 }
@@ -171,6 +173,7 @@
 	int smb_error;
 
 	DBG("slave=0x%02x how=%d\n", slave, how);
+	lockmgr(&sc->xfer_lock, LK_EXCLUSIVE);
 	KASSERT(sc->ich_cmd == -1,
 	    ("%s: ich_cmd=%d", __func__ , sc->ich_cmd));
 	switch (how) {
@@ -189,6 +192,7 @@
 	default:
 		smb_error = SMB_ENOTSUPP;
 	}
+	lockmgr(&sc->xfer_lock, LK_RELEASE);
 	DBG("smb_error=%d\n", smb_error);
 	return (smb_error);
 }
@@ -200,6 +204,7 @@
 	int smb_error;
 
 	DBG("slave=0x%02x byte=0x%02x\n", slave, (u_char)byte);
+	lockmgr(&sc->xfer_lock, LK_EXCLUSIVE);
 	KASSERT(sc->ich_cmd == -1,
 	    ("%s: ich_cmd=%d", __func__ , sc->ich_cmd));
 	lockmgr(&sc->mutex, LK_EXCLUSIVE);
@@ -211,6 +216,7 @@
 	    ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
 	smb_error = ichsmb_wait(sc);
 	lockmgr(&sc->mutex, LK_RELEASE);
+	lockmgr(&sc->xfer_lock, LK_RELEASE);
 	DBG("smb_error=%d\n", smb_error);
 	return (smb_error);
 }
@@ -222,6 +228,7 @@
 	int smb_error;
 
 	DBG("slave=0x%02x\n", slave);
+	lockmgr(&sc->xfer_lock, LK_EXCLUSIVE);
 	KASSERT(sc->ich_cmd == -1,
 	    ("%s: ich_cmd=%d", __func__ , sc->ich_cmd));
 	lockmgr(&sc->mutex, LK_EXCLUSIVE);
@@ -233,6 +240,7 @@
 	if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR)
 		*byte = bus_read_1(sc->io_res, ICH_D0);
 	lockmgr(&sc->mutex, LK_RELEASE);
+	lockmgr(&sc->xfer_lock, LK_RELEASE);
 	DBG("smb_error=%d byte=0x%02x\n", smb_error, (u_char)*byte);
 	return (smb_error);
 }
@@ -245,6 +253,7 @@
 
 	DBG("slave=0x%02x cmd=0x%02x byte=0x%02x\n",
 	    slave, (u_char)cmd, (u_char)byte);
+	lockmgr(&sc->xfer_lock, LK_EXCLUSIVE);
 	KASSERT(sc->ich_cmd == -1,
 	    ("%s: ich_cmd=%d", __func__ , sc->ich_cmd));
 	lockmgr(&sc->mutex, LK_EXCLUSIVE);
@@ -257,6 +266,7 @@
 	    ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
 	smb_error = ichsmb_wait(sc);
 	lockmgr(&sc->mutex, LK_RELEASE);
+	lockmgr(&sc->xfer_lock, LK_RELEASE);
 	DBG("smb_error=%d\n", smb_error);
 	return (smb_error);
 }
@@ -269,6 +279,7 @@
 
 	DBG("slave=0x%02x cmd=0x%02x word=0x%04x\n",
 	    slave, (u_char)cmd, (u_int16_t)word);
+	lockmgr(&sc->xfer_lock, LK_EXCLUSIVE);
 	KASSERT(sc->ich_cmd == -1,
 	    ("%s: ich_cmd=%d", __func__ , sc->ich_cmd));
 	lockmgr(&sc->mutex, LK_EXCLUSIVE);
@@ -282,6 +293,7 @@
 	    ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
 	smb_error = ichsmb_wait(sc);
 	lockmgr(&sc->mutex, LK_RELEASE);
+	lockmgr(&sc->xfer_lock, LK_RELEASE);
 	DBG("smb_error=%d\n", smb_error);
 	return (smb_error);
 }
@@ -293,6 +305,7 @@
 	int smb_error;
 
 	DBG("slave=0x%02x cmd=0x%02x\n", slave, (u_char)cmd);
+	lockmgr(&sc->xfer_lock, LK_EXCLUSIVE);
 	KASSERT(sc->ich_cmd == -1,
 	    ("%s: ich_cmd=%d", __func__ , sc->ich_cmd));
 	lockmgr(&sc->mutex, LK_EXCLUSIVE);
@@ -305,6 +318,7 @@
 	if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR)
 		*byte = bus_read_1(sc->io_res, ICH_D0);
 	lockmgr(&sc->mutex, LK_RELEASE);
+	lockmgr(&sc->xfer_lock, LK_RELEASE);
 	DBG("smb_error=%d byte=0x%02x\n", smb_error, (u_char)*byte);
 	return (smb_error);
 }
@@ -316,6 +330,7 @@
 	int smb_error;
 
 	DBG("slave=0x%02x cmd=0x%02x\n", slave, (u_char)cmd);
+	lockmgr(&sc->xfer_lock, LK_EXCLUSIVE);
 	KASSERT(sc->ich_cmd == -1,
 	    ("%s: ich_cmd=%d", __func__ , sc->ich_cmd));
 	lockmgr(&sc->mutex, LK_EXCLUSIVE);
@@ -332,6 +347,7 @@
 			ICH_D1) << 8);
 	}
 	lockmgr(&sc->mutex, LK_RELEASE);
+	lockmgr(&sc->xfer_lock, LK_RELEASE);
 	DBG("smb_error=%d word=0x%04x\n", smb_error, (u_int16_t)*word);
 	return (smb_error);
 }
@@ -344,6 +360,7 @@
 
 	DBG("slave=0x%02x cmd=0x%02x sdata=0x%04x\n",
 	    slave, (u_char)cmd, (u_int16_t)sdata);
+	lockmgr(&sc->xfer_lock, LK_EXCLUSIVE);
 	KASSERT(sc->ich_cmd == -1,
 	    ("%s: ich_cmd=%d", __func__ , sc->ich_cmd));
 	lockmgr(&sc->mutex, LK_EXCLUSIVE);
@@ -362,6 +379,7 @@
 			ICH_D1) << 8);
 	}
 	lockmgr(&sc->mutex, LK_RELEASE);
+	lockmgr(&sc->xfer_lock, LK_RELEASE);
 	DBG("smb_error=%d rdata=0x%04x\n", smb_error, (u_int16_t)*rdata);
 	return (smb_error);
 }
@@ -388,10 +406,13 @@
 	}
 #undef DISP
 #endif
+	lockmgr(&sc->xfer_lock, LK_EXCLUSIVE);
 	KASSERT(sc->ich_cmd == -1,
 	    ("%s: ich_cmd=%d", __func__ , sc->ich_cmd));
-	if (count < 1 || count > 32)
+	if (count < 1 || count > 32) {
+		lockmgr(&sc->xfer_lock, LK_RELEASE);
 		return (SMB_EINVAL);
+	}
 	bcopy(buf, sc->block_data, count);
 	sc->block_count = count;
 	sc->block_index = 1;
@@ -408,6 +429,7 @@
 	    ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
 	smb_error = ichsmb_wait(sc);
 	lockmgr(&sc->mutex, LK_RELEASE);
+	lockmgr(&sc->xfer_lock, LK_RELEASE);
 	DBG("smb_error=%d\n", smb_error);
 	return (smb_error);
 }
@@ -416,13 +438,13 @@
 ichsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
 {
 	const sc_p sc = device_get_softc(dev);
+	const u_char expect = (*count >= 1 && *count <= 32) ? *count : 32;
 	int smb_error;
 
 	DBG("slave=0x%02x cmd=0x%02x count=%d\n", slave, (u_char)cmd, count);
+	lockmgr(&sc->xfer_lock, LK_EXCLUSIVE);
 	KASSERT(sc->ich_cmd == -1,
 	    ("%s: ich_cmd=%d", __func__ , sc->ich_cmd));
-	if (*count < 1 || *count > 32)
-		return (SMB_EINVAL);
 	bzero(sc->block_data, sizeof(sc->block_data));
 	sc->block_count = 0;
 	sc->block_index = 0;
@@ -433,14 +455,15 @@
 	bus_write_1(sc->io_res, ICH_XMIT_SLVA,
 	    slave | ICH_XMIT_SLVA_READ);
 	bus_write_1(sc->io_res, ICH_HST_CMD, cmd);
-	bus_write_1(sc->io_res, ICH_D0, *count); /* XXX? */
+	bus_write_1(sc->io_res, ICH_D0, expect);
 	bus_write_1(sc->io_res, ICH_HST_CNT,
 	    ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
 	if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR) {
-		bcopy(sc->block_data, buf, min(sc->block_count, *count));
-		*count = sc->block_count;
+		bcopy(sc->block_data, buf, min(sc->block_count, (int)expect));
+		*count = min(sc->block_count, 32);
 	}
 	lockmgr(&sc->mutex, LK_RELEASE);
+	lockmgr(&sc->xfer_lock, LK_RELEASE);
 	DBG("smb_error=%d\n", smb_error);
 #if ICHSMB_DEBUG
 #define DISP(ch)	(((ch) < 0x20 || (ch) >= 0x7e) ? '.' : (ch))
@@ -688,6 +711,7 @@
 		return (error);
 	device_delete_child(dev, sc->smb);
 	ichsmb_release_resources(sc);
+	lockuninit(&sc->xfer_lock);
 	lockuninit(&sc->mutex);
 
 	return 0;
--- a/sys/dev/smbus/smb/smb.c	2026-10-05 20:08:40.196220622 +0000
+++ b/sys/dev/smbus/smb/smb.c	2026-10-05 20:17:56.017094709 +0000
@@ -214,7 +214,7 @@
 	device_t smbdev = SMB_DEVICE(minor(dev));
 	int error;
 	int unit;
-	u_char bcount;
+	u_char bcount = 32;	/* in/out: the controller driver rewrites it */
 
 	if (sc == NULL)
 		return (ENXIO);