carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1//go:build linux
2
3package host
4
5import (
6 "errors"
7 "fmt"
8 "io"
9 "os"
10
11 "github.com/carlosframework/platform/internal/moves"
12 "github.com/carlosframework/platform/internal/safefile"
13)
14
15// heldRenderJournalMax bounds the render journal root reads: a move's
16// journal holds step values (digests, ids, one install manifest), well
17// under this.
18const heldRenderJournalMax = 1 << 20
19
20// readHeldRenderHash is root's read of the held render's journalled hash
21// for (host, op): moves.JournalFile under the agent's data directory. The
22// journal is agent-written, so root never opens it by name (#267,
23// platform-1e): safefile.OpenFile walks every directory from / with
24// O_NOFOLLOW, pins the leaf with O_PATH|O_NOFOLLOW and fstats it before
25// opening it for reading (with O_NONBLOCK), so a symlink at any component
26// fails, and a FIFO, a device or a file with more than one link is refused
27// without being opened for reading; the bytes are read from that one
28// descriptor, bounded. A journal, or a directory on its path, that does not
29// exist is os.ErrNotExist (not yet); anything else unsafe is
30// errHeldReleaseUnsafe. A journal with no rendered step is "".
31func readHeldRenderHash(dataDir, host, op string) (string, error) {
32 f, err := safefile.OpenFile(moves.JournalFile(dataDir, host, op), os.O_RDONLY, 0)
33 if errors.Is(err, os.ErrNotExist) {
34 return "", os.ErrNotExist
35 }
36 if err != nil {
37 return "", fmt.Errorf("%w: %v", errHeldReleaseUnsafe, err)
38 }
39 defer f.Close()
40 st, err := f.Stat()
41 if err != nil {
42 return "", fmt.Errorf("%w: %v", errHeldReleaseUnsafe, err)
43 }
44 if !st.Mode().IsRegular() || st.Size() > heldRenderJournalMax {
45 return "", errHeldReleaseUnsafe
46 }
47 raw, err := io.ReadAll(io.LimitReader(f, heldRenderJournalMax+1))
48 if err != nil {
49 return "", fmt.Errorf("%w: %v", errHeldReleaseUnsafe, err)
50 }
51 if len(raw) > heldRenderJournalMax {
52 return "", errHeldReleaseUnsafe
53 }
54 j, err := moves.DecodeJournal(raw, host, op)
55 if err != nil {
56 return "", fmt.Errorf("%w: %v", errHeldReleaseUnsafe, err)
57 }
58 return j.Steps[landStepRendered], nil
59}
60