[host] lgmp: account for frame header capacity

This commit is contained in:
Geoffrey McRae
2026-08-24 13:01:37 +10:00
parent f664be88bc
commit 9bbccfdcb9
3 changed files with 43 additions and 8 deletions

View File

@@ -153,10 +153,12 @@ typedef struct CaptureInterface
CaptureResult (*waitFrame )( CaptureResult (*waitFrame )(
unsigned frameBufferIndex, unsigned frameBufferIndex,
CaptureFrame * frame, CaptureFrame * frame,
/* Capacity of FrameBuffer::data, excluding the message and header. */
const size_t maxFrameSize); const size_t maxFrameSize);
CaptureResult (*getFrame )( CaptureResult (*getFrame )(
unsigned frameBufferIndex, unsigned frameBufferIndex,
FrameBuffer * frame, FrameBuffer * frame,
/* Capacity of FrameBuffer::data, excluding the message and header. */
const size_t maxFrameSize, const size_t maxFrameSize,
CaptureFrame * captureFrame); CaptureFrame * captureFrame);
} }

View File

@@ -1526,12 +1526,21 @@ static CaptureResult dxgi_getFrame(
} }
else else
{ {
if (!this->pitch || !this->dataHeight ||
(size_t)this->dataHeight > maxFrameSize / this->pitch ||
(size_t)this->dataHeight * this->pitch > UINT_LEAST32_MAX)
{
result = CAPTURE_RESULT_ERROR;
goto cleanup;
}
const size_t frameSize = (size_t)this->pitch * this->dataHeight;
if (tex->damageRectsCount == 0 || if (tex->damageRectsCount == 0 ||
damage->count < 0 || damage->count < 0 ||
damage->count + tex->damageRectsCount > KVMFR_MAX_DAMAGE_RECTS) damage->count + tex->damageRectsCount > KVMFR_MAX_DAMAGE_RECTS)
{ {
// damage all // damage all
framebuffer_write(frame, tex->map, this->pitch * this->dataHeight); framebuffer_write(frame, tex->map, frameSize);
} }
else else
{ {
@@ -1556,7 +1565,7 @@ static CaptureResult dxgi_getFrame(
this->bpp, frame, this->pitch, this->dataHeight, this->bpp, frame, this->pitch, this->dataHeight,
tex->map, this->pitch)) tex->map, this->pitch))
framebuffer_write(frame, tex->map, framebuffer_write(frame, tex->map,
this->pitch * this->dataHeight); frameSize);
} }
else else
{ {
@@ -1564,7 +1573,7 @@ static CaptureResult dxgi_getFrame(
this->bpp, frame, this->pitch, this->dataHeight, this->bpp, frame, this->pitch, this->dataHeight,
tex->map, this->pitch)) tex->map, this->pitch))
framebuffer_write(frame, tex->map, framebuffer_write(frame, tex->map,
this->pitch * this->dataHeight); frameSize);
} }
} }
} }

View File

@@ -98,6 +98,7 @@ struct app
unsigned int pointerShapeIndex; unsigned int pointerShapeIndex;
unsigned alignSize; unsigned alignSize;
size_t frameMemorySize;
size_t maxFrameSize; size_t maxFrameSize;
PLGMPHostQueue frameQueue; PLGMPHostQueue frameQueue;
PLGMPMemory frameMemory[LGMP_Q_FRAME_LEN]; PLGMPMemory frameMemory[LGMP_Q_FRAME_LEN];
@@ -876,14 +877,37 @@ static bool lgmpSetup(struct IVSHMEM * shmDev)
memset(lgmpHostMemPtr(app.pointerShapeMemory[i]), 0, MAX_POINTER_SIZE); memset(lgmpHostMemPtr(app.pointerShapeMemory[i]), 0, MAX_POINTER_SIZE);
} }
app.maxFrameSize = lgmpHostMemAvail(app.lgmp); const size_t frameMemoryAvail = lgmpHostMemAvail(app.lgmp);
app.maxFrameSize = (app.maxFrameSize - (app.alignSize - 1)) & ~(app.alignSize - 1); if (!app.alignSize ||
app.maxFrameSize /= LGMP_Q_FRAME_LEN; (size_t)app.alignSize < sizeof(KVMFRFrame) + sizeof(FrameBuffer) ||
DEBUG_INFO("Max Frame Size : %u MiB", (unsigned int)(app.maxFrameSize / 1048576LL)); (app.alignSize & (app.alignSize - 1)) ||
frameMemoryAvail <= app.alignSize - 1)
{
DEBUG_ERROR("Invalid framebuffer alignment or shared memory capacity");
goto fail_lgmp;
}
/* Reserve the worst-case alignment padding once, then round each message
* down so all frame allocations are guaranteed to fit. The FrameBuffer data
* begins one alignment unit into each message. */
app.frameMemorySize = (frameMemoryAvail - (app.alignSize - 1)) /
LGMP_Q_FRAME_LEN;
app.frameMemorySize &= ~((size_t)app.alignSize - 1);
if (app.frameMemorySize <= app.alignSize ||
app.frameMemorySize > UINT32_MAX)
{
DEBUG_ERROR("Insufficient shared memory for the frame buffers");
goto fail_lgmp;
}
app.maxFrameSize = app.frameMemorySize - app.alignSize;
DEBUG_INFO("Max Frame Size : %u MiB",
(unsigned int)(app.maxFrameSize / 1048576LL));
for(int i = 0; i < LGMP_Q_FRAME_LEN; ++i) for(int i = 0; i < LGMP_Q_FRAME_LEN; ++i)
{ {
if ((status = lgmpHostMemAllocAligned(app.lgmp, app.maxFrameSize, if ((status = lgmpHostMemAllocAligned(app.lgmp,
(uint32_t)app.frameMemorySize,
app.alignSize, &app.frameMemory[i])) != LGMP_OK) app.alignSize, &app.frameMemory[i])) != LGMP_OK)
{ {
DEBUG_ERROR("lgmpHostMemAlloc Failed (Frame): %s", lgmpStatusString(status)); DEBUG_ERROR("lgmpHostMemAlloc Failed (Frame): %s", lgmpStatusString(status));