File: 0010-Ensure-the-seccomp-pipe-is-being-read-while-exportin.patch

package info (click to toggle)
runc 1.0.0~rc93%2Bds1-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, sid
  • size: 3,172 kB
  • sloc: sh: 1,679; ansic: 1,039; makefile: 139
file content (78 lines) | stat: -rw-r--r-- 2,441 bytes parent folder | download
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
From: Shengjing Zhu <zhsj@debian.org>
Date: Sat, 10 Apr 2021 17:46:05 +0800
Subject: Ensure the seccomp pipe is being read while exporting bpf

Origin: backport, https://github.com/opencontainers/runc/pull/2871
---
 libcontainer/seccomp/patchbpf/enosys_linux.go      | 15 ++++++++++++++-
 libcontainer/seccomp/patchbpf/enosys_linux_test.go | 20 ++++++++++++++++++++
 2 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/libcontainer/seccomp/patchbpf/enosys_linux.go b/libcontainer/seccomp/patchbpf/enosys_linux.go
index cdbd59d..195ff60 100644
--- a/libcontainer/seccomp/patchbpf/enosys_linux.go
+++ b/libcontainer/seccomp/patchbpf/enosys_linux.go
@@ -3,6 +3,7 @@
 package patchbpf
 
 import (
+	"bytes"
 	"encoding/binary"
 	"io"
 	"os"
@@ -114,14 +115,26 @@ func disassembleFilter(filter *libseccomp.ScmpFilter) ([]bpf.Instruction, error)
 	defer wtr.Close()
 	defer rdr.Close()
 
+	readerBuffer := new(bytes.Buffer)
+	errChan := make(chan error, 1)
+	go func() {
+		_, err := io.Copy(readerBuffer, rdr)
+		errChan <- err
+		close(errChan)
+	}()
+
 	if err := filter.ExportBPF(wtr); err != nil {
 		return nil, errors.Wrap(err, "exporting BPF")
 	}
 	// Close so that the reader actually gets EOF.
 	_ = wtr.Close()
 
+	if copyErr := <-errChan; copyErr != nil {
+		return nil, errors.Wrap(copyErr, "reading from ExportBPF pipe")
+	}
+
 	// Parse the instructions.
-	rawProgram, err := parseProgram(rdr)
+	rawProgram, err := parseProgram(readerBuffer)
 	if err != nil {
 		return nil, errors.Wrap(err, "parsing generated BPF filter")
 	}
diff --git a/libcontainer/seccomp/patchbpf/enosys_linux_test.go b/libcontainer/seccomp/patchbpf/enosys_linux_test.go
index f9a4bf6..ee26a6a 100644
--- a/libcontainer/seccomp/patchbpf/enosys_linux_test.go
+++ b/libcontainer/seccomp/patchbpf/enosys_linux_test.go
@@ -281,3 +281,23 @@ func TestEnosysStub_MultiArch(t *testing.T) {
 		}
 	}
 }
+
+func TestDisassembleHugeFilterDoesNotHang(t *testing.T) {
+	hugeFilter, err := libseccomp.NewFilter(libseccomp.ActAllow)
+	if err != nil {
+		t.Fatalf("failed to create seccomp filter: %v", err)
+	}
+
+	for i := 1; i < 10000; i++ {
+		if err := hugeFilter.AddRule(libseccomp.ScmpSyscall(i), libseccomp.ActKill); err != nil {
+			t.Fatalf("failed to add rule to filter %d: %v", i, err)
+		}
+	}
+
+	_, err = disassembleFilter(hugeFilter)
+	if err != nil {
+		t.Fatalf("failed to disassembleFilter: %v", err)
+	}
+
+	// if we exit, we did not hang
+}