-
Notifications
You must be signed in to change notification settings - Fork 860
Expand file tree
/
Copy pathdaemon_linux.go
More file actions
151 lines (138 loc) · 4.09 KB
/
daemon_linux.go
File metadata and controls
151 lines (138 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// SPDX-FileCopyrightText: Copyright The Lima Authors
// SPDX-License-Identifier: Apache-2.0
package main
import (
"errors"
"net"
"os"
"os/signal"
"syscall"
"time"
"github.com/mdlayher/vsock"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/lima-vm/lima/v2/pkg/guestagent"
"github.com/lima-vm/lima/v2/pkg/guestagent/api/server"
"github.com/lima-vm/lima/v2/pkg/guestagent/metrics"
"github.com/lima-vm/lima/v2/pkg/guestagent/serialport"
"github.com/lima-vm/lima/v2/pkg/guestagent/ticker"
"github.com/lima-vm/lima/v2/pkg/portfwdserver"
)
const hostCID = 2
type cidFilteredListener struct {
*vsock.Listener
}
func (l *cidFilteredListener) Accept() (net.Conn, error) {
for {
conn, err := l.Listener.Accept()
if err != nil {
return nil, err
}
if vsockConn, ok := conn.(*vsock.Conn); ok {
if addr, ok := vsockConn.RemoteAddr().(*vsock.Addr); ok {
if addr.ContextID != hostCID {
logrus.Warnf("rejected vsock connection from unauthorized CID %d", addr.ContextID)
conn.Close()
continue
}
}
}
return conn, nil
}
}
func newDaemonCommand() *cobra.Command {
daemonCommand := &cobra.Command{
Use: "daemon",
Short: "Run the daemon",
RunE: daemonAction,
}
daemonCommand.Flags().String("runtime-dir", "/run/lima-guestagent", "Directory to store runtime state")
daemonCommand.Flags().Duration("tick", 3*time.Second, "Tick for polling events")
daemonCommand.Flags().Int("vsock-port", 0, "Use vsock server instead a UNIX socket")
daemonCommand.Flags().String("virtio-port", "", "Use virtio server instead a UNIX socket")
return daemonCommand
}
func daemonAction(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
runtimeDir, err := cmd.Flags().GetString("runtime-dir")
if err != nil {
return err
}
if err := os.MkdirAll(runtimeDir, 0o755); err != nil {
return err
}
socket := "/run/lima-guestagent.sock"
tick, err := cmd.Flags().GetDuration("tick")
if err != nil {
return err
}
vSockPort, err := cmd.Flags().GetInt("vsock-port")
if err != nil {
return err
}
virtioPort, err := cmd.Flags().GetString("virtio-port")
if err != nil {
return err
}
if tick == 0 {
return errors.New("tick must be specified")
}
if os.Geteuid() != 0 {
return errors.New("must run as the root user")
}
logrus.Infof("event tick: %v", tick)
simpleTicker := ticker.NewSimpleTicker(time.NewTicker(tick))
tickerInst := simpleTicker
// See /sys/kernel/debug/tracing/available_events for the list of available tracepoints
tracepoints := []string{"syscalls:sys_exit_bind"}
if ebpfTicker, err := ticker.NewEbpfTicker(tracepoints); err != nil {
logrus.WithError(err).Warn("failed to create eBPF ticker, falling back to simple ticker")
} else {
logrus.Infof("using eBPF ticker with tracepoints: %v", tracepoints)
tickerInst = ticker.NewCompoundTicker(simpleTicker, ebpfTicker)
}
ctx, stop := signal.NotifyContext(ctx, syscall.SIGTERM)
defer stop()
go func() {
<-ctx.Done()
logrus.Debug("Received SIGTERM, shutting down the guest agent")
}()
agent, err := guestagent.New(ctx, tickerInst, runtimeDir)
if err != nil {
return err
}
err = os.RemoveAll(socket)
if err != nil {
return err
}
var l net.Listener
if virtioPort != "" {
qemuL, err := serialport.Listen("/dev/virtio-ports/" + virtioPort)
if err != nil {
return err
}
l = qemuL
logrus.Infof("serving the guest agent on qemu serial file: %s", virtioPort)
} else if vSockPort != 0 {
vsockL, err := vsock.Listen(uint32(vSockPort), nil)
if err != nil {
return err
}
l = &cidFilteredListener{Listener: vsockL}
logrus.Infof("serving the guest agent on vsock port: %d (host CID only)", vSockPort)
} else {
var lc net.ListenConfig
socketL, err := lc.Listen(ctx, "unix", socket)
if err != nil {
return err
}
if err := os.Chmod(socket, 0o777); err != nil {
return err
}
l = socketL
logrus.Infof("serving the guest agent on %q", socket)
}
defer logrus.Debug("exiting lima-guestagent daemon")
collector := metrics.NewCollector()
return server.StartServer(ctx, l, &server.GuestServer{Agent: agent, TunnelS: portfwdserver.NewTunnelServer(), Collector: collector})
}