Skip to content

An install from a file overwrites what is installed before the file is known to be whole #103

Open

Description

@jbenedictocenteno

SDK version

develop (1c93155), ESP-IDF v6.1

Component

kaos (AO_AppMgr), kdrv (kdrv_apps, kdrv_kfw)

Where it runs

kodeOS on a Kode Dot: an install with dst=app from a file on the card or the internal volume, or from a URL, and the same installs started from Apps.

What happened

When the apps region has no room for the new image, an install first gives up what is there (it evicts, or drops the old copy of the app it replaces), writes the new image into that room, and verifies it last. A file that is cut or corrupt part way fails that last check after the room it took has been overwritten.

Seen on a board, on a build of develop with changes not merged yet: a 3.4 MB file on the card, cut short of its image, of an app that was already installed, with no room in the region for both. The old copy made room (the old copy of the app being replaced makes room for its new version), the write took about 16 s, the install ended in install failed: the written image did not verify, and the app was gone, the version that worked included. An app being replaced is not copied to the card first: it is no victim (keep_defer() leaves plan->replaced out).

Read from the code: the same holds for the apps evicted to make room, with one difference. With a card mounted their copies are on it, since the keep round runs first; without a card they are lost.

The mailbox already avoids this. AO_AppMgr's own comment: "Eviction is about to delete a live app, and a torn upload only fails the full verify, which runs after the copy. Verify the mailbox in place first." A file on the card or on the internal volume gets no such check, and neither does a download.

What you expected

An install that cannot succeed costs nothing that was installed.

Anything else

What could be done, by source:

  • A file on a medium. Read it through once before the plan gives anything up, only when the plan needs the room of something installed: the segment chain against the file's length, then the hash the image carries. It costs one more read of the file.
  • A URL. With a card mounted and room on it, download to the card and install from that file, which then gets the check above. Without a card, today's order is the only one there is.
  • The terminal. The bytes cannot be judged before they arrive; the copy kept on the card is what would protect a victim there, and a terminal install keeps none today (An install down the wire evicts with no copy on the card, even with a card mounted #102).

Activity

  1. jbenedictocenteno commented on Nov 13, 2026

    @jbenedictocenteno
    ContributorAuthor

    Part of this is in develop now (#125). An install from a file on the card or the internal volume, whose plan gives something up, reads the file through first: the header chain against the file's length and the SHA-256 the image carries. A file that does not hold together ends the install with nothing given up.

    Seen on a board: a file cut past its first segment, whose install would evict, is refused in 0.2 s with the apps and the card as they were; a whole 3.1 MB file reads through in 0.85 s and installs.

    Still open, which is why this issue stays open:

    • a .kfw container: its decoder places the image, and so evicts, at its header, and compares the digest only at the end;
    • an install from a URL and one from the terminal: neither can be read twice, so a cut one still costs what it overwrote (what it did not reach comes back, since fix(kaos): Make a failed install cost only what it overwrote #115);
    • an image with no appended hash is judged by its segment chain alone.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestkaosTouches kaos

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions