mirror of
https://github.com/morluto/rea.git
synced 2026-11-12 09:52:27 +00:00
fix(elf): reject unmatched NT_FILE pathnames (#10138)
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
This commit is contained in:
1 parent
6b2f991808
commit
fadfdf13e6
3 files changed
+67
No files matched your search
@@ -44,6 +44,9 @@ file memory regions and paths (`NT_FILE`), fault signal and code (`NT_SIGINFO`),
|
||||
auxiliary vectors (`NT_AUXV`) across 32-bit and 64-bit images. Other owners or unparsed
|
||||
notes keep `core` null.
|
||||
|
||||
An `NT_FILE` descriptor with nonzero bytes after its declared filenames
|
||||
retains its raw note evidence and leaves `core` null.
|
||||
|
||||
Linux `CORE` decoding requires System V/unspecified (0) or GNU/Linux (3)
|
||||
OSABI with ABI version zero. An unspecified OSABI alone does not establish
|
||||
Linux origin. An explicitly different OSABI or ABI version leaves `core` null
|
||||
|
||||
@@ -1079,6 +1079,63 @@ it("rejects 64-bit auxv tags and out-of-range page sizes with core: null without
|
||||
expect(report.entries[1]?.core).toBeNull();
|
||||
});
|
||||
|
||||
it.each([32, 64] as const)(
|
||||
"leaves ELF%d NT_FILE mappings unknown when the descriptor contains a surplus pathname",
|
||||
(bits) => {
|
||||
const little = bits === 64;
|
||||
const file = coreFileNote(
|
||||
[{ start: 0x1000, end: 0x2000, file_ofs: 2, path: "/bin/app" }],
|
||||
4096,
|
||||
bits,
|
||||
little,
|
||||
);
|
||||
const descriptorBytes = little
|
||||
? file.readUInt32LE(4)
|
||||
: file.readUInt32BE(4);
|
||||
// A five-byte CORE owner including its NUL pads to eight bytes.
|
||||
const descriptor = file.subarray(20, 20 + descriptorBytes);
|
||||
const inspect = (tail: Buffer) => {
|
||||
const payload = Buffer.concat([descriptor, tail]);
|
||||
return parse(
|
||||
elfNoteFixture({
|
||||
bits,
|
||||
little,
|
||||
machine: little ? 62 : 20,
|
||||
type: 4,
|
||||
ownership: "both",
|
||||
notes: elfNote("CORE", 0x46494c45, payload, little),
|
||||
}),
|
||||
);
|
||||
};
|
||||
const exact = inspect(Buffer.alloc(0));
|
||||
const padded = inspect(Buffer.alloc(3));
|
||||
expect(exact.entries).toHaveLength(2);
|
||||
expect(padded.entries.map(({ core }) => core)).toEqual(
|
||||
exact.entries.map(({ core }) => core),
|
||||
);
|
||||
for (const entry of exact.entries)
|
||||
expect(entry.core?.file?.mappings[0]).toMatchObject({
|
||||
start_address: "0x1000",
|
||||
end_address: "0x2000",
|
||||
file_offset_pages: "0x2",
|
||||
path: "/bin/app",
|
||||
});
|
||||
|
||||
const tail = Buffer.from("/lib/extra.so\0");
|
||||
const malformed = inspect(tail);
|
||||
expect(malformed.coverage).toEqual(exact.coverage);
|
||||
expect(malformed.entries).toHaveLength(2);
|
||||
const payload = Buffer.concat([descriptor, tail]);
|
||||
const sha256 = createHash("sha256").update(payload).digest("hex");
|
||||
for (const entry of malformed.entries)
|
||||
expect(entry).toMatchObject({
|
||||
type_name: "core_file",
|
||||
core: null,
|
||||
descriptor: { bytes: payload.length, sha256 },
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it("does not spend text budget on malformed or discarded NT_FILE paths", () => {
|
||||
const header = Buffer.alloc(16);
|
||||
header.writeBigUInt64LE(2n, 0); // count = 2
|
||||
|
||||
@@ -450,6 +450,13 @@ const decodeCoreFile = (
|
||||
totalPathBytes += nullIdx - strPos;
|
||||
strPos = nullIdx + 1;
|
||||
}
|
||||
if (
|
||||
cachedScan === undefined &&
|
||||
descriptor.subarray(strPos).some((byte) => byte !== 0)
|
||||
) {
|
||||
text.scans.set(scanKey, -1);
|
||||
return null;
|
||||
}
|
||||
text.scans.set(scanKey, count);
|
||||
|
||||
const pathBytes = totalPathBytes * 3;
|
||||
|
||||
Reference in new issue
Block a user