'virStorageFileGetEncryptionPayloadOffset' expects payloadOffset + 4 to
be in buffer bounds which isn't checked anywhere.

For example malicious actor may provide LUKS header with just magic and
version like: '4c554b53 babe 0001'. This example successefully passes
'virStorageFileHasEncryptionFormat' and leads to OOB read of 4 bytes.

So the fix is to add bounds checks.

Fixes: b7d44f450c06803df7df3ad380f7a5c97425c1e6
Closes: https://gitlab.com/libvirt/libvirt/-/work_items/906

Signed-off-by: Sergey Zhidkih <[email protected]>
---
 src/storage_file/storage_file_probe.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/storage_file/storage_file_probe.c 
b/src/storage_file/storage_file_probe.c
index cc5854d360..3ac90d698c 100644
--- a/src/storage_file/storage_file_probe.c
+++ b/src/storage_file/storage_file_probe.c
@@ -938,11 +938,13 @@ virStorageFileHasEncryptionFormat(const struct 
FileEncryptionInfo *info,
 
 static int
 virStorageFileGetEncryptionPayloadOffset(const struct FileEncryptionInfo *info,
-                                         char *buf)
+                                         char *buf,
+                                         size_t len)
 {
     int payload_offset = -1;
 
-    if (info->payloadOffset != -1) {
+    if (info->payloadOffset != -1 &&
+        len >= info->payloadOffset + sizeof(uint32_t)) {
         if (info->endian == LV_LITTLE_ENDIAN)
             payload_offset = virReadBufInt32LE(buf + info->payloadOffset);
         else
@@ -999,7 +1001,7 @@ virStorageFileProbeGetMetadata(virStorageSource *meta,
                     }
                 }
                 meta->encryption->payload_offset =
-                    
virStorageFileGetEncryptionPayloadOffset(&fileTypeInfo[meta->format].cryptInfo[i],
 buf);
+                    
virStorageFileGetEncryptionPayloadOffset(&fileTypeInfo[meta->format].cryptInfo[i],
 buf, len);
             }
         }
     }
-- 
2.50.1

Reply via email to