diff mbox series

[069/120] MIPS: PS2: IOP: Module version compatibility verification

Message ID 83c5eb267a56f26ff166ece6c8d9fbf56f0b875f.1567326213.git.noring@nocrew.org (mailing list archive)
State RFC
Headers show
Series Linux for the PlayStation 2 | expand

Commit Message

Fredrik Noring Sept. 1, 2019, 4:11 p.m. UTC
IOP module link requests are only permitted if the major versions match
and the module version is at least of the same minor as the requested
version.

The IOP module version is read from the special .iopmod section.

Signed-off-by: Fredrik Noring <noring@nocrew.org>
---
 drivers/ps2/iop-module.c | 44 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)
diff mbox series

Patch

diff --git a/drivers/ps2/iop-module.c b/drivers/ps2/iop-module.c
index d332a7d1af60..532b3cce91c0 100644
--- a/drivers/ps2/iop-module.c
+++ b/drivers/ps2/iop-module.c
@@ -12,6 +12,10 @@ 
  * (ELF). All valid IOP modules have a special `.iopmod` section containing
  * the module name, version, etc.
  *
+ * IOP module link requests are only permitted if the major versions match
+ * and the module version is at least of the same minor as the requested
+ * version.
+ *
  * When the IOP is reset, a set of modules are automatically linked from
  * read-only memory (ROM). Non-ROM modules are handled as firmware by the
  * IOP module linker.
@@ -226,6 +230,34 @@  static unsigned int minor_version(unsigned int version)
 	return bcd2bin(version & 0xff);
 }
 
+/**
+ * version_compatible - is the version compatible with the requested version?
+ * @version: version to check
+ * @version_request: requested version
+ *
+ * Return: %true if the major versions match and the version to check is at
+ * 	least of the same minor as the requested version, otherwise %false
+ */
+static bool version_compatible(int version, int requested_version)
+{
+	return major_version(version) == major_version(requested_version) &&
+	       minor_version(version) >= minor_version(requested_version);
+}
+
+/**
+ * irx_version_compatible - is the module compatible with the requested version?
+ * @ehdr: ELF header of module to check
+ * @requested_version: request version
+ *
+ * Return: %true if the major versions match and the module version is at
+ * 	least of the same minor as the requested version, otherwise %false
+ */
+static bool irx_version_compatible(const struct elf32_hdr *ehdr,
+	int requested_version)
+{
+	return version_compatible(irx_iopmod(ehdr)->version, requested_version);
+}
+
 /**
  * irx_identify - does the buffer contain an IRX object?
  * @buffer: pointer to data to identify
@@ -344,8 +376,20 @@  static int iop_module_request_firmware(
 
 	ehdr = (const struct elf32_hdr *)fw->data;
 
+	if (!irx_version_compatible(ehdr, version)) {
+		pr_err("iop-module: %s module version %u.%u is incompatible with requested version %u.%u\n",
+			filepath,
+			major_version(irx_iopmod(ehdr)->version),
+			minor_version(irx_iopmod(ehdr)->version),
+			major_version(version),
+			minor_version(version));
+		err = -ENOEXEC;
+		goto err_incompatible;
+	}
+
 	err = iop_module_link_buffer(fw->data, fw->size, arg);
 
+err_incompatible:
 err_identify:
 err_request:
 err_name: