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 activator
4
5import (
6 "context"
7 "os"
8 "os/exec"
9 "path/filepath"
10 "strconv"
11 "strings"
12
13 "github.com/carlosframework/platform/internal/cgroup"
14 "github.com/carlosframework/platform/internal/hostbox"
15 "github.com/carlosframework/platform/internal/hostclaim"
16 "github.com/carlosframework/platform/internal/hostwrite"
17 "golang.org/x/sys/unix"
18)
19
20// Start never executes tenant code in the agent's namespace. With the
21// isolated root protocol it asks root to run the reserved role in main's
22// isolated unit; without it every shape stays refused.
23func (l RoleLaunch) Start(ctx context.Context, role string, attempt hostclaim.WakeRetryAttempt, build func() *exec.Cmd, before func() error) (*exec.Cmd, *cgroup.Prepared, func(context.Context) error, RoleProducer, error) {
24 if l.Root == nil {
25 return nil, nil, nil, RoleProducer{}, ErrClaimIsolationUnavailable
26 }
27 return l.startIsolated(ctx, role, attempt, build, before)
28}
29
30func roleProcessStart(pid int) (string, error) {
31 raw, err := os.ReadFile("/proc/" + strconv.Itoa(pid) + "/stat")
32 if err != nil {
33 return "", err
34 }
35 i := strings.LastIndexByte(string(raw), ')')
36 if i < 0 {
37 return "", hostwrite.ErrUnavailable
38 }
39 fields := strings.Fields(string(raw)[i+1:])
40 if len(fields) < 20 || fields[0] == "Z" || fields[0] == "X" {
41 return "", hostwrite.ErrUnavailable
42 }
43 return fields[19], nil
44}
45func (l RoleLaunch) ExactHealth(ctx context.Context, cmd *exec.Cmd, a hostclaim.WakeRetryAttempt) error {
46 _, err := l.RoleCgroup(ctx, cmd, a)
47 return err
48}
49
50// RoleCgroup returns the absolute cgroup directory of the started main role
51// for attempt a after the same checks as ExactHealth: the journalled started
52// reservation names cmd's pid and process start, its group still has the
53// journalled device and inode, and the pid is a member of exactly that group.
54func (l RoleLaunch) RoleCgroup(ctx context.Context, cmd *exec.Cmd, a hostclaim.WakeRetryAttempt) (string, error) {
55 if l.Journal == nil || cmd == nil || cmd.Process == nil || !filepath.IsAbs(l.CgroupRoot) {
56 return "", hostwrite.ErrUnavailable
57 }
58 inventory, err := l.Journal.Read(ctx, l.Target)
59 if err != nil {
60 return "", err
61 }
62 started := "started"
63 if l.Root != nil {
64 // A root-launched role is only ever a unit reservation root wrote.
65 started = hostbox.UnitStarted
66 }
67 for _, r := range inventory.Reservations {
68 if r.ID != a.ID+":main" || r.State != started || r.InvocationID != a.InvocationID || r.Inputs != a.LaunchInputs || r.PID != cmd.Process.Pid || r.Target.Session != a.Session {
69 continue
70 }
71 start, err := roleProcessStart(r.PID)
72 if err != nil {
73 return "", err
74 }
75 if start != r.ProcessStart {
76 return "", hostbox.ErrChanged
77 }
78 group := filepath.Join(l.CgroupRoot, r.Group.RelativePath)
79 var stat unix.Stat_t
80 if err = unix.Stat(group, &stat); err != nil {
81 return "", err
82 }
83 if uint64(stat.Dev) != r.Group.Device || stat.Ino != r.Group.Inode {
84 return "", hostbox.ErrChanged
85 }
86 rel, err := filepath.Rel("/sys/fs/cgroup", group)
87 if err != nil || strings.HasPrefix(rel, "..") {
88 return "", hostwrite.ErrUnavailable
89 }
90 raw, err := os.ReadFile("/proc/" + strconv.Itoa(r.PID) + "/cgroup")
91 if err != nil {
92 return "", err
93 }
94 found := false
95 for _, line := range strings.Split(string(raw), "\n") {
96 if line == "0::/"+rel {
97 found = true
98 }
99 }
100 if !found {
101 return "", hostbox.ErrChanged
102 }
103 return group, nil
104 }
105 return "", hostbox.ErrChanged
106}
107