Skip to content

MCB corruption from mismatch in maximum size allocated for and read from flat-format .COM executable #207

@ecm-pushbx

Description

@ecm-pushbx

Here's the Script for lDebug file that reliably causes the kernel to corrupt one of its MCBs (if an UMCB chain is present and UMB link state is disabled): https://pushbx.org/ecm/test/20250603/testbigc.sld (I will copy the contents into a subsequent comment in this thread.)

You run it like so:

ldebug
y testbigc.sld
g
dm
l
dm
q

What it does is it exposes a difference in the flat-fomat .COM style executable maximum size to allocate and to load, in task.c. The maximum required memory block is smaller than the maximum file data read, so with a certain range of free MCB size and executable size the allocation will be smaller than the amount of file data read, leading to corrupting memory beyond the end of the allocated memory block (most obviously corrupting the next MCB).

Flat-format executables sized >= FF00h bytes are rejected by the MS-DOS v4.01 and lDOS executable loaders. So the problem might be restricted to pathological cases of executable sizes. However, the other condition of this (precise free block size) is not purely pathological, it can occur when loading to UMBs using LOADHIGH.

Here's where the file size is determined to get the minimum size of memory allocation needed to run the program, it requires at most FE0h + 10h = FF0h paragraphs:

kernel/kernel/task.c

Lines 470 to 473 in b8ef68f

ULONG com_size_long = SftGetFsize(fd);
/* maximally 64k - 256 bytes stack -
256 bytes psp */
com_size = ((UWORD)min(com_size_long, 0xfe00u) >> 4) + 0x10;

Here's where the file is read, it reads up to FF00h bytes during exec (not overlay/device load) to offset 0100h hence writing to offsets 0100h .. FFFFh:

kernel/kernel/task.c

Lines 532 to 540 in b8ef68f

/* MS DOS always only loads the very first 64KB - sizeof(psp) bytes.
-- 1999/04/21 ska */
/* rewind to start */
SftSeek(fd, 0, 0);
/* read everything, but at most 64K - sizeof(PSP) */
/* lpproj: some device drivers (not exe) are larger than 0xff00bytes... */
DosRWSft(fd, (mode == OVERLAY) ? 0xfffeU : 0xff00U, sp, XFR_READ);
DosCloseSft(fd, FALSE);

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions