Fix atomvm:read_priv and detect truncated packs - #2340
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
22d6864 to
2a6c79b
Compare
This comment was marked as outdated.
This comment was marked as outdated.
The packbeam scanners were unbounded, so a lookup miss (e.g. read_priv for an unpacked file) ran off the pack into erased flash and crashed. Bound and validate every scan against the stored pack size. The walk now stops only at the end marker: the old scanners stopped at the first data file (flags 0), hiding every section after it. Signed-off-by: Davide Bettio <davide@uninstall.it>
Reject truncated or incomplete packs (e.g. an image flashed to a too-small partition) at load instead of failing late, validating by tail check or bounded walk. Signed-off-by: Davide Bettio <davide@uninstall.it>
Fail at configure time when boot.avm does not fit its partition. Signed-off-by: Davide Bettio <davide@uninstall.it>
A priv entry whose length prefix does not fit its own section was skipped, so a corrupt pack was indistinguishable from a missing file. Raise invalid_avm instead. A genuine miss still returns undefined. Read the length prefix unaligned: an in-place pack may sit at any byte offset and the direct load faults Xtensa/Cortex-M0+. Signed-off-by: Davide Bettio <davide@uninstall.it>
The generic_unix invalid-pack rejection in sys_open_avm_from_file returned without releasing the mapping, leaking it and its file descriptor. Pre-existing, but truncated packs now take this path. Signed-off-by: Davide Bettio <davide@uninstall.it>
The XIP_SRAM_BASE bound spans past the flash, so a corrupt section size could steer bounded header reads into unmapped address space. Signed-off-by: Davide Bettio <davide@uninstall.it>
Review of the last 6 commitsRange: The core parser rewrite is directionally sound: regular section scans are now bounded, unaligned pack bases are supported, section payload sizes are reported correctly, Findings1. Blocker — JIT mistakes ordinary data sections for the end markerFiles:
For a pack containing a
This ambiguity existed in the old flag lookup, but the revised parser retains it and the JIT safety changes rely on the lookup to identify whether a terminator exists. A generic flag query cannot distinguish the terminator from a regular flags-0 section; JIT should locate the structurally recognized end marker instead. Suggested fixdiff --git a/src/libAtomVM/jit_stream_flash.c b/src/libAtomVM/jit_stream_flash.c
@@
+static bool find_pack_end(const struct AVMPackData *pack,
+ const void **end_offset, const char **end_name)
+{
+ uint32_t real_size;
+ if (!avmpack_compute_size(pack->data, pack->size, &real_size)) {
+ return false;
+ }
+
+ *end_offset = (const uint8_t *) pack->data + real_size;
+ *end_name = (const char *) *end_offset - 4;
+ return true;
+}
@@
- if (!avmpack_find_section_by_flag(avmpack_data->data, avmpack_data->size,
- END_OF_FILE_MASK, END_OF_FILE, &end_offset, &end_size, &end_name)) {
+ if (!find_pack_end(avmpack_data, &end_offset, &end_name)) {
valid_cache = false;
continue;
}
@@
- if (!avmpack_find_section_by_flag(avmpack_data->data, avmpack_data->size,
- END_OF_FILE_MASK, END_OF_FILE, &end_offset, &end_size, &end_name)) {
+ if (!find_pack_end(avmpack_data, &end_offset, &end_name)) {
found_end = false;
valid_cache = false;
break;
}Remove the now-unused 2. Blocker — a malformed zero-sized marker can trigger an out-of-bounds string readFile: For A marker ending in Suggested fixdiff --git a/src/libAtomVM/avmpack.c b/src/libAtomVM/avmpack.c
@@
if (section_size == 0) {
- // The min-size guard above keeps the terminator name bytes in bounds for strcmp.
- if (flags == 0 && (strcmp(name, "end") == 0 || strcmp(name, "END") == 0)) {
+ // Exactly four name bytes are available in a terminator, including its NUL.
+ if (flags == 0
+ && (memcmp(name, "end", 4) == 0 || memcmp(name, "END", 4) == 0)) {Add an exact-size test ending in 3. Blocker —
|
The packbeam (.avm) scanners were unbounded and trusted section sizes,
so a lookup miss (e.g. atomvm:read_priv/2 for an unpacked file) ran off
the pack into erased flash and crashed the VM. A truncated pack failed
the same way.
Bound and validate every scan, detect truncation at load, and add a
build-time guard for the one pack known at build time. No on-disk
format change.
Also user visible:
are found
of reporting a missing file
These changes are made under both the "Apache 2.0" and the "GNU Lesser
General Public License 2.1 or later" license terms (dual license).
SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later