201 lines
5.8 KiB
Diff
201 lines
5.8 KiB
Diff
From 57c633981dd80f602f829434275b93103d6251c7 Mon Sep 17 00:00:00 2001
|
|
From: bwzhang <zhangbowei@kylinos.cn>
|
|
Date: Mon, 18 Mar 2024 09:48:34 +0800
|
|
Subject: [PATCH] fix CVE-2022-0811
|
|
|
|
---
|
|
internal/config/nsmgr/nsmgr.go | 23 ++--------------------
|
|
pinns/src/pinns.c | 10 +++++++---
|
|
pinns/src/sysctl.c | 35 +++++++++-------------------------
|
|
pinns/src/sysctl.h | 2 +-
|
|
4 files changed, 19 insertions(+), 51 deletions(-)
|
|
|
|
diff --git a/internal/config/nsmgr/nsmgr.go b/internal/config/nsmgr/nsmgr.go
|
|
index 6c7d8ce..344419b 100644
|
|
--- a/internal/config/nsmgr/nsmgr.go
|
|
+++ b/internal/config/nsmgr/nsmgr.go
|
|
@@ -5,7 +5,6 @@ import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
- "strings"
|
|
"syscall"
|
|
|
|
nspkg "github.com/containernetworking/plugins/pkg/ns"
|
|
@@ -87,12 +86,8 @@ func (mgr *NamespaceManager) NewPodNamespaces(cfg *PodNamespacesConfig) ([]Names
|
|
"-f", pinnedNamespace,
|
|
}
|
|
|
|
- if len(cfg.Sysctls) != 0 {
|
|
- pinnsSysctls, err := getSysctlForPinns(cfg.Sysctls)
|
|
- if err != nil {
|
|
- return nil, errors.Wrapf(err, "invalid sysctl")
|
|
- }
|
|
- pinnsArgs = append(pinnsArgs, "-s", pinnsSysctls)
|
|
+ for key, value := range cfg.Sysctls {
|
|
+ pinnsArgs = append(pinnsArgs, "-s", fmt.Sprintf("%s=%s", key, value))
|
|
}
|
|
|
|
var rootPair idtools.IDPair
|
|
@@ -175,20 +170,6 @@ func getMappingsForPinns(mappings []idtools.IDMap) string {
|
|
return g.String()
|
|
}
|
|
|
|
-func getSysctlForPinns(sysctls map[string]string) (string, error) {
|
|
- // This assumes there's no valid sysctl value with a `+` in it
|
|
- // and as such errors if one is found.
|
|
- const pinnsSysctlDelim = "+"
|
|
- g := new(bytes.Buffer)
|
|
- for key, value := range sysctls {
|
|
- if strings.Contains(key, pinnsSysctlDelim) || strings.Contains(value, pinnsSysctlDelim) {
|
|
- return "", errors.Errorf("'%s=%s' is invalid: %s found yet should not be present", key, value, pinnsSysctlDelim)
|
|
- }
|
|
- fmt.Fprintf(g, "'%s=%s'%s", key, value, pinnsSysctlDelim)
|
|
- }
|
|
- return strings.TrimSuffix(g.String(), pinnsSysctlDelim), nil
|
|
-}
|
|
-
|
|
// NamespaceFromProcEntry creates a new namespace object from a bind mount from a processes proc entry.
|
|
// The caller is responsible for cleaning up the namespace by calling Namespace.Remove().
|
|
// This function is heavily based on containernetworking ns package found at:
|
|
diff --git a/pinns/src/pinns.c b/pinns/src/pinns.c
|
|
index dc25d09..f44df47 100644
|
|
--- a/pinns/src/pinns.c
|
|
+++ b/pinns/src/pinns.c
|
|
@@ -49,7 +49,8 @@ int main(int argc, char **argv) {
|
|
bool bind_user = false;
|
|
bool bind_cgroup = false;
|
|
bool bind_mount = false;
|
|
- char *sysctls = NULL;
|
|
+ char **sysctls = NULL;
|
|
+ int sysctls_count = 0;
|
|
char res;
|
|
|
|
static const struct option long_options[] = {
|
|
@@ -67,6 +68,8 @@ int main(int argc, char **argv) {
|
|
{"sysctl", optional_argument, NULL, 's'},
|
|
};
|
|
|
|
+ sysctls = calloc(argc/2, sizeof(char *));
|
|
+
|
|
while ((c = getopt_long(argc, argv, "mpchuUind:f:s:", long_options, NULL)) != -1) {
|
|
switch (c) {
|
|
case 'u':
|
|
@@ -113,7 +116,8 @@ int main(int argc, char **argv) {
|
|
pin_path = optarg;
|
|
break;
|
|
case 's':
|
|
- sysctls = optarg;
|
|
+ sysctls[sysctls_count] = optarg;
|
|
+ sysctls_count++;
|
|
break;
|
|
case 'f':
|
|
filename = optarg;
|
|
@@ -239,7 +243,7 @@ int main(int argc, char **argv) {
|
|
close(p[0]);
|
|
}
|
|
|
|
- if (sysctls && configure_sysctls(sysctls) < 0) {
|
|
+ if (sysctls_count != 0 && configure_sysctls(sysctls, sysctls_count) < 0) {
|
|
pexit("Failed to configure sysctls after unshare");
|
|
}
|
|
|
|
diff --git a/pinns/src/sysctl.c b/pinns/src/sysctl.c
|
|
index 058afb9..1c7377c 100644
|
|
--- a/pinns/src/sysctl.c
|
|
+++ b/pinns/src/sysctl.c
|
|
@@ -8,37 +8,27 @@
|
|
|
|
static int separate_sysctl_key_value (char* sysctl_key_value, char** sysctl_key, char** sysctl_value);
|
|
static int write_sysctl_to_file (char * sysctl_key, char* sysctl_value);
|
|
-const char *sysctl_delim = "+";
|
|
|
|
-int configure_sysctls (char * const sysctls)
|
|
+int configure_sysctls (char ** const sysctls, int size)
|
|
{
|
|
- char* sysctl = strtok(sysctls, sysctl_delim);
|
|
char* key = NULL;
|
|
char* value = NULL;
|
|
- while (sysctl)
|
|
+
|
|
+ for (int i = 0; i < size; ++i)
|
|
{
|
|
- if (separate_sysctl_key_value (sysctl, &key, &value) < 0)
|
|
+ if (separate_sysctl_key_value (sysctls[i], &key, &value) < 0)
|
|
return -1;
|
|
|
|
if (write_sysctl_to_file (key, value) < 0)
|
|
return -1;
|
|
- sysctl = strtok (NULL, sysctl_delim);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
-// key_value should be in the form `'k=v'`
|
|
+// key_value should be in the form `k=v`
|
|
static int separate_sysctl_key_value (char* key_value, char** key, char** value)
|
|
{
|
|
- // begin by stripping the `'`, we now have `k=v'`
|
|
- bool quote_stripped = false;
|
|
- if (*key_value == '\'')
|
|
- {
|
|
- key_value++;
|
|
- quote_stripped = true;
|
|
- }
|
|
-
|
|
// now find the `=` and convert it to a delimiter
|
|
char * equals_token = strchr (key_value, '=');
|
|
if (!equals_token)
|
|
@@ -55,31 +45,24 @@ static int separate_sysctl_key_value (char* key_value, char** key, char** value)
|
|
return -1;
|
|
}
|
|
|
|
- // we now have `k\0v'`
|
|
+ // we now have `k\0v`
|
|
*equals_token = '\0';
|
|
|
|
// key is now `k`
|
|
*key = key_value;
|
|
|
|
- // equals_token is now `v'`
|
|
+ // equals_token is now `v`
|
|
++equals_token;
|
|
|
|
- // if we stripped the beginning single quote
|
|
- // we should find and strip the ending, as well as anything after
|
|
- if (quote_stripped)
|
|
- {
|
|
- char* ending_char = strchr (equals_token, '\'');
|
|
- if (ending_char)
|
|
- *ending_char = '\0';
|
|
- }
|
|
-
|
|
// value is now `v`
|
|
*value = equals_token;
|
|
+
|
|
if (!strlen (*value))
|
|
{
|
|
nwarnf ("sysctl must be in the form of 'key=value'; value is empty");
|
|
return -1;
|
|
}
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/pinns/src/sysctl.h b/pinns/src/sysctl.h
|
|
index 9f90d4e..2a753eb 100644
|
|
--- a/pinns/src/sysctl.h
|
|
+++ b/pinns/src/sysctl.h
|
|
@@ -2,6 +2,6 @@
|
|
#if !defined(SYSCTL_H)
|
|
#define SYSCTL_H
|
|
|
|
-int configure_sysctls (char * const sysctls);
|
|
+int configure_sysctls (char ** const sysctls, int size);
|
|
|
|
#endif // SYSCTL_H
|
|
--
|
|
2.20.1
|
|
|