Repository: opencontainers/runc
Pull request #3254 (2021-10-29 16:40:54)

libct/configs/validate: allow / in sysctl names
Runtime spec [says](https://github.com/opencontainers/runtime-spec/blob/0d6cc581aeeaacee38ce707ae651a0e122f76852/config-linux.md#sysctl):

> sysctl (object, OPTIONAL) allows kernel parameters to be modified at
> runtime for the container. For more information, see the sysctl(8)
> man page.

and sysctl(8) says:

> variable
>    The name of a key to read from. An example is
>    kernel.ostype. The '/' separator is also accepted in place of a '.'.

[Apparently](https://github.com/kubernetes/kubernetes/pull/102393#issuecomment-939047989), runc config validator do not support sysctls with `/` as a
separator. Fortunately this is a one-line fix.

Add some more test data where `/` is used as a separator.

Related to: https://github.com/kubernetes/kubernetes/pull/102393


Patch:
diff --git a/libcontainer/configs/validate/validator.go b/libcontainer/configs/validate/validator.go
index 7d9511c7..a2a79c29 100644
--- a/libcontainer/configs/validate/validator.go
+++ b/libcontainer/configs/validate/validator.go
@@ -150,6 +150,7 @@ func (v *ConfigValidator) sysctl(config *configs.Config) error {
 	)
 
 	for s := range config.Sysctl {
+		s := strings.Replace(s, "/", ".", -1)
 		if validSysctlMap[s] || strings.HasPrefix(s, "fs.mqueue.") {
 			if config.Namespaces.Contains(configs.NEWIPC) {
 				continue


Test patch:
diff --git a/libcontainer/configs/validate/validator_test.go b/libcontainer/configs/validate/validator_test.go
index 4f72252d..169c2751 100644
--- a/libcontainer/configs/validate/validator_test.go
+++ b/libcontainer/configs/validate/validator_test.go
@@ -188,8 +188,11 @@ func TestValidateUsernamespaceWithoutUserNS(t *testing.T) {
 func TestValidateSysctl(t *testing.T) {
 	sysctl := map[string]string{
 		"fs.mqueue.ctl": "ctl",
+		"fs/mqueue/ctl": "ctl",
 		"net.ctl":       "ctl",
+		"net/ctl":       "ctl",
 		"kernel.ctl":    "ctl",
+		"kernel/ctl":    "ctl",
 	}
 
 	for k, v := range sysctl {
@@ -209,8 +212,11 @@ func TestValidateSysctl(t *testing.T) {
 func TestValidateValidSysctl(t *testing.T) {
 	sysctl := map[string]string{
 		"fs.mqueue.ctl": "ctl",
+		"fs/mqueue/ctl": "ctl",
 		"net.ctl":       "ctl",
+		"net/ctl":       "ctl",
 		"kernel.msgmax": "ctl",
+		"kernel/msgmax": "ctl",
 	}
 
 	for k, v := range sysctl {
diff --git a/libcontainer/integration/exec_test.go b/libcontainer/integration/exec_test.go
index f32f4989..2c346220 100644
--- a/libcontainer/integration/exec_test.go
+++ b/libcontainer/integration/exec_test.go
@@ -897,7 +897,12 @@ func TestSysctl(t *testing.T) {
 	config := newTemplateConfig(t, nil)
 	config.Sysctl = map[string]string{
 		"kernel.shmmni": "8192",
+		"kernel/shmmax": "4194304",
 	}
+	const (
+		cmd = "cat shmmni shmmax"
+		exp = "8192\n4194304\n"
+	)
 
 	container, err := newContainer(t, config)
 	ok(t, err)
@@ -905,8 +910,8 @@ func TestSysctl(t *testing.T) {
 
 	var stdout bytes.Buffer
 	pconfig := libcontainer.Process{
-		Cwd:    "/",
-		Args:   []string{"sh", "-c", "cat /proc/sys/kernel/shmmni"},
+		Cwd:    "/proc/sys/kernel",
+		Args:   []string{"sh", "-c", cmd},
 		Env:    standardEnvironment,
 		Stdin:  nil,
 		Stdout: &stdout,
@@ -918,9 +923,9 @@ func TestSysctl(t *testing.T) {
 	// Wait for process
 	waitProcess(&pconfig, t)
 
-	shmmniOutput := strings.TrimSpace(stdout.String())
-	if shmmniOutput != "8192" {
-		t.Fatalf("kernel.shmmni property expected to be 8192, but is %s", shmmniOutput)
+	out := stdout.String()
+	if out != exp {
+		t.Fatalf("expected %s, got %s", exp, out)
 	}
 }