aboutsummaryrefslogtreecommitdiffstats
path: root/testing/lxd-feature/32-bit-fix.patch
blob: b8556b899eb9de2e7e8e18edd52b538ab8108672 (plain) (blame)
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
Patch-Source: https://github.com/lxc/lxd/pull/10348
From fd6845ddda3f80cdd24a8f94c42acce6bff0c41f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott@canonical.com>
Date: Fri, 29 Apr 2022 11:12:48 +0100
Subject: [PATCH] lxd/secommp: Fix sysinfo syscall interception on 32 bit
 platforms

Fixes #10347

Signed-off-by: Thomas Parrott <thomas.parrott@canonical.com>
---
 lxd/seccomp/seccomp.go    | 22 ++++++++++++++--------
 lxd/seccomp/sysinfo.go    | 13 +++++++++++++
 lxd/seccomp/sysinfo_32.go | 19 +++++++++++++++++++
 lxd/seccomp/sysinfo_64.go | 19 +++++++++++++++++++
 4 files changed, 65 insertions(+), 8 deletions(-)
 create mode 100644 lxd/seccomp/sysinfo.go
 create mode 100644 lxd/seccomp/sysinfo_32.go
 create mode 100644 lxd/seccomp/sysinfo_64.go

diff --git a/lxd/seccomp/seccomp.go b/lxd/seccomp/seccomp.go
index 03fee3c71a0..203d408a828 100644
--- a/lxd/seccomp/seccomp.go
+++ b/lxd/seccomp/seccomp.go
@@ -1709,6 +1709,7 @@ func (s *Server) HandleSysinfoSyscall(c Instance, siov *Iovec) int {
 
 	defer l.Debug("Handling sysinfo syscall")
 
+	// Pre-fill sysinfo struct with metrics from host system.
 	info := unix.Sysinfo_t{}
 	err := unix.Sysinfo(&info)
 	if err != nil {
@@ -1718,6 +1719,8 @@ func (s *Server) HandleSysinfoSyscall(c Instance, siov *Iovec) int {
 		return 0
 	}
 
+	instMetrics := Sysinfo{} // Architecture independent place to hold instance metrics.
+
 	cg, err := cgroup.NewFileReadWriter(int(siov.msg.init_pid), liblxc.HasApiExtension("cgroup2"))
 	if err != nil {
 		l.Warn("Failed loading cgroup", logger.Ctx{"err": err, "pid": siov.msg.init_pid})
@@ -1735,7 +1738,7 @@ func (s *Server) HandleSysinfoSyscall(c Instance, siov *Iovec) int {
 		return 0
 	}
 
-	info.Uptime = int64(time.Now().Sub(f.ModTime()).Seconds())
+	instMetrics.Uptime = int64(time.Now().Sub(f.ModTime()).Seconds())
 
 	// Get instance process count.
 	pids, err := cg.GetTotalProcesses()
@@ -1746,7 +1749,7 @@ func (s *Server) HandleSysinfoSyscall(c Instance, siov *Iovec) int {
 		return 0
 	}
 
-	info.Procs = uint16(pids)
+	instMetrics.Procs = uint16(pids)
 
 	// Get instance memory stats.
 	memStats, err := cg.GetMemoryStats()
@@ -1760,9 +1763,9 @@ func (s *Server) HandleSysinfoSyscall(c Instance, siov *Iovec) int {
 	for k, v := range memStats {
 		switch k {
 		case "shmem":
-			info.Sharedram = v
+			instMetrics.Sharedram = v
 		case "cache":
-			info.Bufferram = v
+			instMetrics.Bufferram = v
 		}
 	}
 
@@ -1784,8 +1787,8 @@ func (s *Server) HandleSysinfoSyscall(c Instance, siov *Iovec) int {
 		return 0
 	}
 
-	info.Totalram = uint64(memoryLimit)
-	info.Freeram = info.Totalram - uint64(memoryUsage) - info.Bufferram
+	instMetrics.Totalram = uint64(memoryLimit)
+	instMetrics.Freeram = instMetrics.Totalram - uint64(memoryUsage) - instMetrics.Bufferram
 
 	// Get instance swap info.
 	if s.s.OS.CGInfo.Supports(cgroup.MemorySwapUsage, cg) {
@@ -1805,14 +1808,17 @@ func (s *Server) HandleSysinfoSyscall(c Instance, siov *Iovec) int {
 			return 0
 		}
 
-		info.Totalswap = uint64(swapLimit)
-		info.Freeswap = info.Totalswap - uint64(swapUsage)
+		instMetrics.Totalswap = uint64(swapLimit)
+		instMetrics.Freeswap = instMetrics.Totalswap - uint64(swapUsage)
 	}
 
 	// Get writable pointer to buffer of sysinfo syscall result.
 	const sz = int(unsafe.Sizeof(info))
 	var b []byte = (*(*[sz]byte)(unsafe.Pointer(&info)))[:]
 
+	// Write instance metrics to native sysinfo struct.
+	instMetrics.ToNative(&info)
+
 	// Write sysinfo response into buffer.
 	_, err = unix.Pwrite(siov.memFd, b, int64(siov.req.data.args[0]))
 	if err != nil {
diff --git a/lxd/seccomp/sysinfo.go b/lxd/seccomp/sysinfo.go
new file mode 100644
index 00000000000..b255894af26
--- /dev/null
+++ b/lxd/seccomp/sysinfo.go
@@ -0,0 +1,13 @@
+package seccomp
+
+// Sysinfo architecture independent sysinfo struct.
+type Sysinfo struct {
+	Uptime    int64
+	Totalram  uint64
+	Freeram   uint64
+	Sharedram uint64
+	Bufferram uint64
+	Totalswap uint64
+	Freeswap  uint64
+	Procs     uint16
+}
diff --git a/lxd/seccomp/sysinfo_32.go b/lxd/seccomp/sysinfo_32.go
new file mode 100644
index 00000000000..e52808300dd
--- /dev/null
+++ b/lxd/seccomp/sysinfo_32.go
@@ -0,0 +1,19 @@
+//go:build 386 || arm || ppc || s390 || mips || mipsle
+
+package seccomp
+
+import (
+	"golang.org/x/sys/unix"
+)
+
+// ToNative fills fields from s into native fields.
+func (s *Sysinfo) ToNative(n *unix.Sysinfo_t) {
+	n.Bufferram = uint32(s.Bufferram)
+	n.Freeram = uint32(s.Freeram)
+	n.Freeswap = uint32(s.Freeswap)
+	n.Procs = s.Procs
+	n.Sharedram = uint32(s.Sharedram)
+	n.Totalram = uint32(s.Totalram)
+	n.Totalswap = uint32(s.Totalswap)
+	n.Uptime = int32(s.Uptime)
+}
diff --git a/lxd/seccomp/sysinfo_64.go b/lxd/seccomp/sysinfo_64.go
new file mode 100644
index 00000000000..84383b1c5a8
--- /dev/null
+++ b/lxd/seccomp/sysinfo_64.go
@@ -0,0 +1,19 @@
+//go:build amd64 || ppc64 || ppc64le || arm64 || s390x || mips64 || mips64le || riscv64
+
+package seccomp
+
+import (
+	"golang.org/x/sys/unix"
+)
+
+// ToNative fills fields from s into native fields.
+func (s *Sysinfo) ToNative(n *unix.Sysinfo_t) {
+	n.Bufferram = s.Bufferram
+	n.Freeram = s.Freeram
+	n.Freeswap = s.Freeswap
+	n.Procs = s.Procs
+	n.Sharedram = s.Sharedram
+	n.Totalram = s.Totalram
+	n.Totalswap = s.Totalswap
+	n.Uptime = s.Uptime
+}