Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e5ce067b authored by Matthew R. Ochs's avatar Matthew R. Ochs Committed by James Bottomley
Browse files

cxlflash: Fix AFU version access/storage and add check



The AFU version is stored as a non-terminated string of bytes within
a 64-bit little-endian register. Presently the value is read directly
(no MMIO accessor) and is stored in a buffer that is not big enough
to contain a NULL terminator. Additionally the version obtained is not
evaluated against a known value to prevent usage with unsupported AFUs.
All of these deficiencies can lead to a variety of problems.

To remedy, use the correct MMIO accessor to read the version value into
a null-terminated buffer and add a check to prevent an incompatible AFU
from being used with this driver.

Signed-off-by: default avatarMatthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: default avatarManoj N. Kumar <manoj@linux.vnet.ibm.com>
Reviewed-by: default avatarBrian King <brking@linux.vnet.ibm.com>
Reviewed-by: default avatarDaniel Axtens <dja@axtens.net>
Reviewed-by: default avatarTomas Henzl <thenzl@redhat.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Odin.com>
parent 964497b3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -179,7 +179,7 @@ struct afu {
	u32 cmd_couts;		/* Number of command checkouts */
	u32 internal_lun;	/* User-desired LUN mode for this AFU */

	char version[8];
	char version[16];
	u64 interface_version;

	struct cxlflash_cfg *parent; /* Pointer back to parent cxlflash_cfg */
+12 −6
Original line number Diff line number Diff line
@@ -1751,12 +1751,18 @@ static int init_afu(struct cxlflash_cfg *cfg)
		goto err1;
	}

	/* don't byte reverse on reading afu_version, else the string form */
	/*     will be backwards */
	reg = afu->afu_map->global.regs.afu_version;
	memcpy(afu->version, &reg, 8);
	/* No byte reverse on reading afu_version or string will be backwards */
	reg = readq(&afu->afu_map->global.regs.afu_version);
	memcpy(afu->version, &reg, sizeof(reg));
	afu->interface_version =
	    readq_be(&afu->afu_map->global.regs.interface_version);
	if ((afu->interface_version + 1) == 0) {
		pr_err("Back level AFU, please upgrade. AFU version %s "
		       "interface version 0x%llx\n", afu->version,
		       afu->interface_version);
		rc = -EINVAL;
		goto err1;
	} else
		pr_debug("%s: afu version %s, interface version 0x%llX\n",
			 __func__, afu->version, afu->interface_version);

+1 −1
Original line number Diff line number Diff line
@@ -340,7 +340,7 @@ struct sisl_global_regs {
#define SISL_AFUCONF_MBOX_CLR_READ     0x0010ULL
	__be64 afu_config;
	__be64 rsvd[0xf8];
	__be64 afu_version;
	__le64 afu_version;
	__be64 interface_version;
};