From 57c633981dd80f602f829434275b93103d6251c7 Mon Sep 17 00:00:00 2001 From: bwzhang 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