Browse Source

seccomp.Syscall: embed runtime-spec Syscall type

This makes the type better reflect the difference with the "runtime" profile;
our local type is used to generate a runtime-spec seccomp profile and extends
the runtime-spec type with additional fields; adding a "Name" field for backward
compatibility with older JSON representations, additional "Comment" metadata,
and conditional rules ("Includes", "Excludes") used during generation to adjust
the profile based on the container (capabilities) and host's (architecture, kernel)
configuration.

This change introduces one change in the type; the "runtime-spec" type uses a
`[]LinuxSeccompArg` for the `Args` field, whereas the local type used pointers;
`[]*LinuxSeccompArg`.

In addition, the runtime-spec Syscall type brings a new `ErrnoRet` field, allowing
the profile to specify the errno code returned for the syscall, which allows
changing the default EPERM for specific syscalls.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 4 years ago
parent
commit
d92739713c

+ 0 - 19
profiles/seccomp/default.json

@@ -394,7 +394,6 @@
 				"writev"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {},
 			"excludes": {}
@@ -406,7 +405,6 @@
 				"ptrace"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": null,
 			"comment": "",
 			"includes": {
 				"minKernel": "4.8"
@@ -498,7 +496,6 @@
 				"sync_file_range2"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"arches": [
@@ -517,7 +514,6 @@
 				"set_tls"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"arches": [
@@ -532,7 +528,6 @@
 				"arch_prctl"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"arches": [
@@ -547,7 +542,6 @@
 				"modify_ldt"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"arches": [
@@ -565,7 +559,6 @@
 				"s390_runtime_instr"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"arches": [
@@ -580,7 +573,6 @@
 				"open_by_handle_at"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"caps": [
@@ -614,7 +606,6 @@
 				"unshare"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"caps": [
@@ -677,7 +668,6 @@
 				"reboot"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"caps": [
@@ -691,7 +681,6 @@
 				"chroot"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"caps": [
@@ -707,7 +696,6 @@
 				"finit_module"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"caps": [
@@ -721,7 +709,6 @@
 				"acct"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"caps": [
@@ -740,7 +727,6 @@
 				"ptrace"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"caps": [
@@ -755,7 +741,6 @@
 				"ioperm"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"caps": [
@@ -771,7 +756,6 @@
 				"clock_settime"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"caps": [
@@ -785,7 +769,6 @@
 				"vhangup"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"caps": [
@@ -801,7 +784,6 @@
 				"set_mempolicy"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"caps": [
@@ -815,7 +797,6 @@
 				"syslog"
 			],
 			"action": "SCMP_ACT_ALLOW",
-			"args": [],
 			"comment": "",
 			"includes": {
 				"caps": [

File diff suppressed because it is too large
+ 475 - 453
profiles/seccomp/default_linux.go


+ 6 - 0
profiles/seccomp/fixtures/example.json

@@ -22,6 +22,12 @@
             "name": "close",
             "action": "SCMP_ACT_ALLOW",
             "args": []
+        },
+        {
+            "name": "syslog",
+            "action": "SCMP_ACT_ERRNO",
+            "errnoRet": 12345,
+            "args": []
         }
     ]
 }

+ 11 - 8
profiles/seccomp/seccomp.go

@@ -40,15 +40,18 @@ type Filter struct {
 	MinKernel *KernelVersion `json:"minKernel,omitempty"`
 }
 
-// Syscall is used to match a group of syscalls in Seccomp
+// Syscall is used to match a group of syscalls in Seccomp. It extends the
+// runtime-spec Syscall type, adding a "Name" field for backward compatibility
+// with older JSON representations, additional "Comment" metadata, and conditional
+// rules ("Includes", "Excludes") used to generate a runtime-spec Seccomp profile
+// based on the container (capabilities) and host's (arch, kernel) configuration.
 type Syscall struct {
-	Name     string                   `json:"name,omitempty"`
-	Names    []string                 `json:"names,omitempty"`
-	Action   specs.LinuxSeccompAction `json:"action"`
-	Args     []*specs.LinuxSeccompArg `json:"args"`
-	Comment  string                   `json:"comment"`
-	Includes Filter                   `json:"includes"`
-	Excludes Filter                   `json:"excludes"`
+	specs.LinuxSyscall
+	// Deprecated: kept for backward compatibility with old JSON profiles, use Names instead
+	Name     string `json:"name,omitempty"`
+	Comment  string `json:"comment"`
+	Includes Filter `json:"includes"`
+	Excludes Filter `json:"excludes"`
 }
 
 // KernelVersion holds information about the kernel.

+ 6 - 20
profiles/seccomp/seccomp_linux.go

@@ -150,29 +150,15 @@ Loop:
 			}
 		}
 
-		if call.Name != "" && len(call.Names) != 0 {
-			return nil, errors.New("'name' and 'names' were specified in the seccomp profile, use either 'name' or 'names'")
-		}
-
 		if call.Name != "" {
-			newConfig.Syscalls = append(newConfig.Syscalls, createSpecsSyscall([]string{call.Name}, call.Action, call.Args))
-		} else {
-			newConfig.Syscalls = append(newConfig.Syscalls, createSpecsSyscall(call.Names, call.Action, call.Args))
+			if len(call.Names) != 0 {
+				return nil, errors.New("'name' and 'names' were specified in the seccomp profile, use either 'name' or 'names'")
+			}
+			call.Names = append(call.Names, call.Name)
 		}
-	}
 
-	return newConfig, nil
-}
-
-func createSpecsSyscall(names []string, action specs.LinuxSeccompAction, args []*specs.LinuxSeccompArg) specs.LinuxSyscall {
-	newCall := specs.LinuxSyscall{
-		Names:  names,
-		Action: action,
+		newConfig.Syscalls = append(newConfig.Syscalls, call.LinuxSyscall)
 	}
 
-	// Loop through all the arguments of the syscall and convert them
-	for _, arg := range args {
-		newCall.Args = append(newCall.Args, *arg)
-	}
-	return newCall
+	return newConfig, nil
 }

+ 37 - 1
profiles/seccomp/seccomp_test.go

@@ -18,9 +18,45 @@ func TestLoadProfile(t *testing.T) {
 		t.Fatal(err)
 	}
 	rs := createSpec()
-	if _, err := LoadProfile(string(f), &rs); err != nil {
+	p, err := LoadProfile(string(f), &rs)
+	if err != nil {
 		t.Fatal(err)
 	}
+	var expectedErrno uint = 12345
+	expected := specs.LinuxSeccomp{
+		DefaultAction: "SCMP_ACT_ERRNO",
+		Syscalls: []specs.LinuxSyscall{
+			{
+				Names:  []string{"clone"},
+				Action: "SCMP_ACT_ALLOW",
+				Args: []specs.LinuxSeccompArg{{
+					Index:    0,
+					Value:    2114060288,
+					ValueTwo: 0,
+					Op:       "SCMP_CMP_MASKED_EQ",
+				}},
+			},
+			{
+
+				Names:  []string{"open"},
+				Action: "SCMP_ACT_ALLOW",
+				Args:   []specs.LinuxSeccompArg{},
+			},
+			{
+				Names:  []string{"close"},
+				Action: "SCMP_ACT_ALLOW",
+				Args:   []specs.LinuxSeccompArg{},
+			},
+			{
+				Names:    []string{"syslog"},
+				Action:   "SCMP_ACT_ERRNO",
+				ErrnoRet: &expectedErrno,
+				Args:     []specs.LinuxSeccompArg{},
+			},
+		},
+	}
+
+	assert.DeepEqual(t, expected, *p)
 }
 
 // TestLoadLegacyProfile tests loading a seccomp profile in the old format

Some files were not shown because too many files changed in this diff