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 "context"
7 "crypto/ed25519"
8 "crypto/sha256"
9 "encoding/hex"
10 "fmt"
11 "io"
12 "os"
13 "strconv"
14 "strings"
15
16 "github.com/carlosframework/platform/internal/hostfloor"
17 "github.com/carlosframework/platform/internal/hostwrite"
18 "github.com/carlosframework/platform/internal/release"
19 "golang.org/x/sys/unix"
20)
21
22type productionStopControllers struct{}
23
24func (productionStopControllers) VerifiedController(ctx context.Context, pid int) (string, error) {
25 if ctx.Err() != nil {
26 return "", ctx.Err()
27 }
28 if pid <= 0 {
29 return "", hostwrite.ErrUnavailable
30 }
31 boot, err := os.ReadFile("/proc/sys/kernel/random/boot_id")
32 if err != nil {
33 return "", err
34 }
35 raw, err := os.ReadFile(fmt.Sprintf("/proc/%d/stat", pid))
36 if err != nil {
37 return "", err
38 }
39 end := strings.LastIndexByte(string(raw), ')')
40 if end < 0 {
41 return "", hostwrite.ErrUnavailable
42 }
43 fields := strings.Fields(string(raw)[end+1:])
44 if len(fields) < 20 {
45 return "", hostwrite.ErrUnavailable
46 }
47 if _, err := strconv.ParseUint(fields[19], 10, 64); err != nil {
48 return "", err
49 }
50 sum := sha256.Sum256([]byte(strings.TrimSpace(string(boot)) + "\x00" + strconv.Itoa(pid) + "\x00" + fields[19]))
51 return hex.EncodeToString(sum[:]), nil
52}
53func readClaimEvidenceKey(path string) (ed25519.PrivateKey, error) {
54 if os.Geteuid() != 0 {
55 return nil, hostwrite.ErrUnavailable
56 }
57 f, err := hostfloor.OpenProtected(path)
58 if err != nil {
59 return nil, err
60 }
61 defer f.Close()
62 var stat unix.Stat_t
63 if err = unix.Fstat(int(f.Fd()), &stat); err != nil {
64 return nil, err
65 }
66 if stat.Uid != 0 || stat.Mode&unix.S_IFMT != unix.S_IFREG || stat.Mode&0077 != 0 || stat.Nlink != 1 {
67 return nil, hostwrite.ErrUnavailable
68 }
69 raw, err := io.ReadAll(io.LimitReader(f, 4097))
70 if err != nil || len(raw) > 4096 {
71 return nil, hostwrite.ErrUnavailable
72 }
73 return release.ParseSigningKey(strings.TrimSpace(string(raw)), path)
74}
75
76func prepareClaimParticipationDirectory(path string) error {
77 uid, gid, err := claimStateOwner()
78 if err != nil {
79 return err
80 }
81 if err = os.Mkdir(path, 0700); err != nil && !os.IsExist(err) {
82 return err
83 }
84 return claimPrivatePathOwner(path, uid, gid, true)
85}
86