blob: cdd5dc1d19df7105916872846d93ba0dbbbf5c7d [file] [log] [blame]
Lorenz Brun62948542023-01-10 13:28:44 +00001package main
2
3import (
Lorenz Brunaadeb792023-03-27 15:53:56 +02004 "context"
Lorenz Brun62948542023-01-10 13:28:44 +00005 "fmt"
Lorenz Brunaadeb792023-03-27 15:53:56 +02006 "io"
7 "os"
Lorenz Brun5d503b32023-04-11 13:20:23 +02008 "regexp"
Lorenz Brun62948542023-01-10 13:28:44 +00009
Lorenz Brunaadeb792023-03-27 15:53:56 +020010 "golang.org/x/sys/unix"
11
Lorenz Brun5d503b32023-04-11 13:20:23 +020012 "source.monogon.dev/metropolis/pkg/bootparam"
Lorenz Brunaadeb792023-03-27 15:53:56 +020013 "source.monogon.dev/metropolis/pkg/logtree"
14 "source.monogon.dev/metropolis/pkg/supervisor"
Lorenz Brun62948542023-01-10 13:28:44 +000015)
16
Lorenz Brun5d503b32023-04-11 13:20:23 +020017var validTTYRegexp = regexp.MustCompile(`^[a-zA-Z0-9]+$`)
18
Lorenz Brun62948542023-01-10 13:28:44 +000019func main() {
Lorenz Brunaadeb792023-03-27 15:53:56 +020020 setupMounts()
21
Lorenz Brun5d503b32023-04-11 13:20:23 +020022 // Set up logger for the Agent. Parse consoles from the kernel command line
23 // as well as adding the two standard tty0/ttyS0 consoles.
24 consoles := make(map[string]bool)
25 cmdline, err := os.ReadFile("/proc/cmdline")
26 if err == nil {
27 params, _, err := bootparam.Unmarshal(string(cmdline))
28 if err == nil {
29 consoles = params.Consoles()
30 }
31 }
32 consoles["tty0"] = true
33 consoles["ttyS0"] = true
34
Lorenz Brunaadeb792023-03-27 15:53:56 +020035 lt := logtree.New()
Lorenz Brun5d503b32023-04-11 13:20:23 +020036 for p := range consoles {
37 f, err := os.OpenFile("/dev/"+p, os.O_WRONLY, 0)
Lorenz Brunaadeb792023-03-27 15:53:56 +020038 if err != nil {
39 continue
40 }
41 reader, err := lt.Read("", logtree.WithChildren(), logtree.WithStream())
42 if err != nil {
43 panic(fmt.Errorf("could not set up root log reader: %v", err))
44 }
45 go func(path string, f io.Writer) {
46 for {
47 p := <-reader.Stream
48 fmt.Fprintf(f, "%s\n", p.String())
49 }
50 }(p, f)
51 }
52
53 sCtx := context.Background()
54 supervisor.New(sCtx, agentRunnable, supervisor.WithExistingLogtree(lt))
55 select {}
56}
57
58func mkdirAndMount(dir, fs string, flags uintptr) error {
59 if err := os.MkdirAll(dir, 0o755); err != nil {
60 return fmt.Errorf("could not make %s: %w", dir, err)
61 }
62 if err := unix.Mount(fs, dir, fs, flags, ""); err != nil {
63 return fmt.Errorf("could not mount %s on %s: %w", fs, dir, err)
64 }
65 return nil
66}
67
68// setupMounts sets up basic mounts like sysfs, procfs, devtmpfs and cgroups.
69// This should be called early during init as a lot of processes depend on this
70// being available.
71func setupMounts() error {
72 // Set up target filesystems.
73 for _, el := range []struct {
74 dir string
75 fs string
76 flags uintptr
77 }{
78 {"/sys", "sysfs", unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV},
79 {"/sys/kernel/tracing", "tracefs", unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV},
80 {"/sys/fs/pstore", "pstore", unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV},
81 {"/proc", "proc", unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV},
82 {"/dev", "devtmpfs", unix.MS_NOEXEC | unix.MS_NOSUID},
83 {"/dev/pts", "devpts", unix.MS_NOEXEC | unix.MS_NOSUID},
84 } {
85 if err := mkdirAndMount(el.dir, el.fs, el.flags); err != nil {
86 return err
87 }
88 }
89 return nil
Lorenz Brun62948542023-01-10 13:28:44 +000090}