blob: 45c3e527b11880f05f5b90a44e2c3e879fcfcca9 [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 "os"
Lorenz Brun5d503b32023-04-11 13:20:23 +02007 "regexp"
Lorenz Brun62948542023-01-10 13:28:44 +00008
Lorenz Brunaadeb792023-03-27 15:53:56 +02009 "golang.org/x/sys/unix"
10
Lorenz Brun5d503b32023-04-11 13:20:23 +020011 "source.monogon.dev/metropolis/pkg/bootparam"
Lorenz Brunaadeb792023-03-27 15:53:56 +020012 "source.monogon.dev/metropolis/pkg/logtree"
13 "source.monogon.dev/metropolis/pkg/supervisor"
Lorenz Brun62948542023-01-10 13:28:44 +000014)
15
Lorenz Brun5d503b32023-04-11 13:20:23 +020016var validTTYRegexp = regexp.MustCompile(`^[a-zA-Z0-9]+$`)
17
Lorenz Brun62948542023-01-10 13:28:44 +000018func main() {
Lorenz Brunaadeb792023-03-27 15:53:56 +020019 setupMounts()
20
Lorenz Brun5d503b32023-04-11 13:20:23 +020021 // Set up logger for the Agent. Parse consoles from the kernel command line
22 // as well as adding the two standard tty0/ttyS0 consoles.
23 consoles := make(map[string]bool)
24 cmdline, err := os.ReadFile("/proc/cmdline")
25 if err == nil {
26 params, _, err := bootparam.Unmarshal(string(cmdline))
27 if err == nil {
28 consoles = params.Consoles()
29 }
30 }
31 consoles["tty0"] = true
32 consoles["ttyS0"] = true
33
Lorenz Brunaadeb792023-03-27 15:53:56 +020034 lt := logtree.New()
Tim Windelschmidt13b83f72024-04-11 23:10:16 +020035 for path := range consoles {
36 f, err := os.OpenFile("/dev/"+path, os.O_WRONLY, 0)
Lorenz Brunaadeb792023-03-27 15:53:56 +020037 if err != nil {
38 continue
39 }
40 reader, err := lt.Read("", logtree.WithChildren(), logtree.WithStream())
41 if err != nil {
Tim Windelschmidt6b207812024-04-22 19:13:15 +020042 panic(fmt.Sprintf("could not set up root log reader: %v", err))
Lorenz Brunaadeb792023-03-27 15:53:56 +020043 }
Tim Windelschmidt13b83f72024-04-11 23:10:16 +020044 go func() {
Lorenz Brunaadeb792023-03-27 15:53:56 +020045 for {
46 p := <-reader.Stream
47 fmt.Fprintf(f, "%s\n", p.String())
48 }
Tim Windelschmidt13b83f72024-04-11 23:10:16 +020049 }()
Lorenz Brunaadeb792023-03-27 15:53:56 +020050 }
51
52 sCtx := context.Background()
53 supervisor.New(sCtx, agentRunnable, supervisor.WithExistingLogtree(lt))
54 select {}
55}
56
57func mkdirAndMount(dir, fs string, flags uintptr) error {
58 if err := os.MkdirAll(dir, 0o755); err != nil {
59 return fmt.Errorf("could not make %s: %w", dir, err)
60 }
61 if err := unix.Mount(fs, dir, fs, flags, ""); err != nil {
62 return fmt.Errorf("could not mount %s on %s: %w", fs, dir, err)
63 }
64 return nil
65}
66
67// setupMounts sets up basic mounts like sysfs, procfs, devtmpfs and cgroups.
68// This should be called early during init as a lot of processes depend on this
69// being available.
70func setupMounts() error {
71 // Set up target filesystems.
72 for _, el := range []struct {
73 dir string
74 fs string
75 flags uintptr
76 }{
77 {"/sys", "sysfs", unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV},
78 {"/sys/kernel/tracing", "tracefs", unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV},
79 {"/sys/fs/pstore", "pstore", unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV},
80 {"/proc", "proc", unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV},
81 {"/dev", "devtmpfs", unix.MS_NOEXEC | unix.MS_NOSUID},
82 {"/dev/pts", "devpts", unix.MS_NOEXEC | unix.MS_NOSUID},
83 } {
84 if err := mkdirAndMount(el.dir, el.fs, el.flags); err != nil {
85 return err
86 }
87 }
88 return nil
Lorenz Brun62948542023-01-10 13:28:44 +000089}