Package: python3-virt-firmware
Version: 24.11-2
Severity: normal
Tags: upstream, patch
X-Debbugs-Cc: [email protected]

There's a bug in virt/firmware/varstore/edk2.py when
reading varstore images, - it uses native endiannes
instead of little-endian.

    def parse_volume(self):
        ...
        (vlen, sig, attr, hlen, csum, xoff, rev, blocks, blksize) = \
            struct.unpack_from("=QLLHHHxBLL", self.filedata, offset + 32)
        logging.debug('vol=%s vlen=0x%x rev=%d blocks=%d*%d (0x%x)',
                      guids.name(guid), vlen, rev,
                      blocks, blksize, blocks * blksize)
        if sig != 0x4856465f:
            logging.error('%s: not a firmware volume', self.filename)
            sys.exit(1)

When reading AAVMF_VARS.fd, on a little-endian system, this results in:

 DEBUG:root:vol=guid:NvData vlen=0xc0000 rev=2 blocks=3*262144 (0xc0000)

The same code and input, when run on s390x, results in:

 DEBUG:root:vol=guid:NvData vlen=0xc0000000000 rev=2 blocks=50331648*1024 
(0xc00000000)
 ERROR:root:AAVMF_VARS.fd: not a firmware volume

The unpack_from() call should have "<" (little-endian) as the first symbol
instead of "=" (native-endian), since it is reading an image defined as
having little-endian characteristics.

See two edk2 debci runs, on amd64 (sucessful) and on s390x (failed):
https://ci.debian.net/packages/e/edk2/testing/amd64/66712410/
https://ci.debian.net/packages/e/edk2/testing/s390x/66711962/

There are other places in this file where the same "=" (native) conversion
is used, - these should probably be fixed too.

Attached is a small patch (untested yet) which should fix this.

Thanks,

/mjt

diff --git a/virt/firmware/varstore/edk2.py b/virt/firmware/varstore/edk2.py
index 33b2738..54db6e1 100644
--- a/virt/firmware/varstore/edk2.py
+++ b/virt/firmware/varstore/edk2.py
@@ -62,5 +62,5 @@ class Edk2VarStore:
         guid = guids.parse_bin(self.filedata, offset + 16)
         (vlen, sig, attr, hlen, csum, xoff, rev, blocks, blksize) = \
-            struct.unpack_from("=QLLHHHxBLL", self.filedata, offset + 32)
+            struct.unpack_from("<QLLHHHxBLL", self.filedata, offset + 32)
         logging.debug('vol=%s vlen=0x%x rev=%d blocks=%d*%d (0x%x)',
                       guids.name(guid), vlen, rev,
@@ -76,5 +76,5 @@ class Edk2VarStore:
     def parse_varstore(self, start):
         guid = guids.parse_bin(self.filedata, start)
-        (size, storefmt, state) = struct.unpack_from("=LBB", self.filedata, 
start + 16)
+        (size, storefmt, state) = struct.unpack_from("<LBB", self.filedata, 
start + 16)
         logging.debug('varstore=%s size=0x%x format=0x%x state=0x%x',
                       guids.name(guid), size, storefmt, state)
@@ -97,8 +97,8 @@ class Edk2VarStore:
         varlist = efivar.EfiVarList()
         while pos < self.end:
-            (magic, state, attr, count) = struct.unpack_from("=HBxLQ", 
self.filedata, pos)
+            (magic, state, attr, count) = struct.unpack_from("<HBxLQ", 
self.filedata, pos)
             if magic != 0x55aa:
                 break
-            (pk, nsize, dsize) = struct.unpack_from("=LLL", self.filedata, pos 
+ 32)
+            (pk, nsize, dsize) = struct.unpack_from("<LLL", self.filedata, pos 
+ 32)
 
             if state == 0x3f:

Reply via email to