From a605a22157d7b96a84dc5e2fff74dd6a2f577d35 Mon Sep 17 00:00:00 2001 From: sxt1001 Date: Sun, 14 May 2023 23:34:12 +0800 Subject: [PATCH] fix CVE-2022-2084 --- backport-CVE-2022-2084.patch | 90 ++++++++ cloud-init.spec | 7 +- ...rs-from-log-for-cloudinit-config-cc_.patch | 194 ++++++++++++++++++ 3 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2022-2084.patch create mode 100644 remove-schema-errors-from-log-for-cloudinit-config-cc_.patch diff --git a/backport-CVE-2022-2084.patch b/backport-CVE-2022-2084.patch new file mode 100644 index 0000000..5cafaf3 --- /dev/null +++ b/backport-CVE-2022-2084.patch @@ -0,0 +1,90 @@ +From 4d467b14363d800b2185b89790d57871f11ea88c Mon Sep 17 00:00:00 2001 +From: James Falcon +Date: Wed, 29 Jun 2022 17:27:44 -0500 +Subject: [PATCH] Remove schema errors from log (#1551) + +When schema errors are encountered, the section of userdata in question +gets printed to the cloud-init log. As this could contain sensitive +data, so log a generic warning instead and redirect user to run +cloud-init schema --system as root. + +LP: #1978422 +CVE: 2022-2084 +--- + cloudinit/config/schema.py | 15 ++++++++++++--- + tests/unittests/test_handler/test_schema.py | 17 +++++++++++++++++ + 2 files changed, 29 insertions(+), 3 deletions(-) + +diff --git a/cloudinit/config/schema.py b/cloudinit/config/schema.py +index 807c3ee..cc0a2a5 100644 +--- a/cloudinit/config/schema.py ++++ b/cloudinit/config/schema.py +@@ -58,7 +58,7 @@ class SchemaValidationError(ValueError): + super(SchemaValidationError, self).__init__(message) + + +-def validate_cloudconfig_schema(config, schema, strict=False): ++def validate_cloudconfig_schema(config, schema, strict=False, log_details=True): + """Validate provided config meets the schema definition. + + @param config: Dict of cloud configuration settings validated against +@@ -67,6 +67,9 @@ def validate_cloudconfig_schema(config, schema, strict=False): + for the cloud config module (config.cc_*). + @param strict: Boolean, when True raise SchemaValidationErrors instead of + logging warnings. ++ @param log_details: Boolean, when True logs details of validation errors. ++ If there are concerns about logging sensitive userdata, this should ++ be set to False. + + @raises: SchemaValidationError when provided config does not validate + against the provided schema. +@@ -84,10 +87,16 @@ def validate_cloudconfig_schema(config, schema, strict=False): + errors += ((path, error.message),) + if errors: + if strict: ++ # This could output/log sensitive data + raise SchemaValidationError(errors) +- else: ++ if log_details: + messages = ['{0}: {1}'.format(k, msg) for k, msg in errors] +- logging.warning('Invalid config:\n%s', '\n'.join(messages)) ++ details = "\n" + "\n".join(messages) ++ else: ++ details = ( ++ "Please run 'sudo cloud-init devel schema --system' or 'cloud-init devel schema -c config-file' to see the schema errors." ++ ) ++ logging.warning('Invalid config:%s', details) + + + def annotated_cloudconfig_file(cloudconfig, original_content, schema_errors): +diff --git a/tests/unittests/test_handler/test_schema.py b/tests/unittests/test_handler/test_schema.py +index e69a47a..85f281d 100644 +--- a/tests/unittests/test_handler/test_schema.py ++++ b/tests/unittests/test_handler/test_schema.py +@@ -78,6 +78,23 @@ class ValidateCloudConfigSchemaTest(CiTestCase): + "Invalid config:\np1: -1 is not of type 'string'\n", + self.logs.getvalue()) + ++ @skipUnlessJsonSchema() ++ def test_validateconfig_schema_sensitive(self): ++ """When log_details=False, ensure details are omitted""" ++ schema = { ++ "properties": {"hashed_password": {"type": "string"}}, ++ "additionalProperties": False, ++ } ++ validate_cloudconfig_schema( ++ {"hashed-password": "secret"}, ++ schema, ++ strict=False, ++ log_details=False, ++ ) ++ self.assertIn( ++ "Please run 'sudo cloud-init devel schema --system' or 'cloud-init devel schema -c config-file' to see the schema errors.", ++ self.logs.getvalue()) ++ + @skipUnlessJsonSchema() + def test_validateconfig_schema_emits_warning_on_missing_jsonschema(self): + """Warning from validate_cloudconfig_schema when missing jsonschema.""" +-- +2.33.0 + diff --git a/cloud-init.spec b/cloud-init.spec index f57fe3c..d73e4dd 100644 --- a/cloud-init.spec +++ b/cloud-init.spec @@ -1,6 +1,6 @@ Name: cloud-init Version: 19.4 -Release: 11 +Release: 12 Summary: the defacto multi-distribution package that handles early initialization of a cloud instance. License: ASL 2.0 or GPLv3 URL: http://launchpad.net/cloud-init @@ -18,6 +18,8 @@ Patch7: backport-CVE-2020-8632-cc_set_password-increase-random-pwlength-from-9-t Patch8: backport-CVE-2021-3429-write-passwords-only-to-serial-console-lock-down-clo.patch Patch9: backport-testing-add-additional-mocks-to-test_net-tests-1356.patch Patch10:fix-a-small-unitest-error.patch +Patch11: backport-CVE-2022-2084.patch +Patch12: remove-schema-errors-from-log-for-cloudinit-config-cc_.patch Patch9000: Fix-the-error-level-logs-displayed-for-the-cloud-init-local-service.patch @@ -126,6 +128,9 @@ fi %exclude /usr/share/doc/* %changelog +* Sun May 14 2023 shixuantong - 19.4-12 +- fix CVE-2022-2084 + * Sun Apr 23 2023 shixuantong - 19.4-11 - Fix a unitest error diff --git a/remove-schema-errors-from-log-for-cloudinit-config-cc_.patch b/remove-schema-errors-from-log-for-cloudinit-config-cc_.patch new file mode 100644 index 0000000..f15a997 --- /dev/null +++ b/remove-schema-errors-from-log-for-cloudinit-config-cc_.patch @@ -0,0 +1,194 @@ +From 4aec33275d56c398234af45ca1dc51dd7995360f Mon Sep 17 00:00:00 2001 +From: sxt1001 +Date: Sun, 14 May 2023 23:24:15 +0800 +Subject: [PATCH] remove schema errors from log for cloudinit/config/cc_* + +--- + cloudinit/config/cc_bootcmd.py | 2 +- + cloudinit/config/cc_ntp.py | 2 +- + cloudinit/config/cc_resizefs.py | 2 +- + cloudinit/config/cc_runcmd.py | 2 +- + cloudinit/config/cc_snap.py | 2 +- + cloudinit/config/cc_ubuntu_advantage.py | 2 +- + cloudinit/config/cc_ubuntu_drivers.py | 2 +- + cloudinit/config/tests/test_snap.py | 5 ++--- + tests/unittests/test_handler/test_handler_bootcmd.py | 8 ++++---- + tests/unittests/test_handler/test_handler_resizefs.py | 4 ++-- + tests/unittests/test_handler/test_handler_runcmd.py | 8 ++++---- + 11 files changed, 19 insertions(+), 20 deletions(-) + +diff --git a/cloudinit/config/cc_bootcmd.py b/cloudinit/config/cc_bootcmd.py +index 6813f53..cee7585 100644 +--- a/cloudinit/config/cc_bootcmd.py ++++ b/cloudinit/config/cc_bootcmd.py +@@ -83,7 +83,7 @@ def handle(name, cfg, cloud, log, _args): + " no 'bootcmd' key in configuration"), name) + return + +- validate_cloudconfig_schema(cfg, schema) ++ validate_cloudconfig_schema(cfg, schema, log_details=False) + with temp_utils.ExtendedTemporaryFile(suffix=".sh") as tmpf: + try: + content = util.shellify(cfg["bootcmd"]) +diff --git a/cloudinit/config/cc_ntp.py b/cloudinit/config/cc_ntp.py +index 926dfea..5481f54 100644 +--- a/cloudinit/config/cc_ntp.py ++++ b/cloudinit/config/cc_ntp.py +@@ -502,7 +502,7 @@ def handle(name, cfg, cloud, log, _args): + "'ntp' key existed in config, but not a dictionary type," + " is a {_type} instead".format(_type=type_utils.obj_name(ntp_cfg))) + +- validate_cloudconfig_schema(cfg, schema) ++ validate_cloudconfig_schema(cfg, schema, log_details=False) + + # Allow users to explicitly enable/disable + enabled = ntp_cfg.get('enabled', True) +diff --git a/cloudinit/config/cc_resizefs.py b/cloudinit/config/cc_resizefs.py +index 01dfc12..88fc89e 100644 +--- a/cloudinit/config/cc_resizefs.py ++++ b/cloudinit/config/cc_resizefs.py +@@ -233,7 +233,7 @@ def handle(name, cfg, _cloud, log, args): + resize_root = args[0] + else: + resize_root = util.get_cfg_option_str(cfg, "resize_rootfs", True) +- validate_cloudconfig_schema(cfg, schema) ++ validate_cloudconfig_schema(cfg, schema, log_details=False) + if not util.translate_bool(resize_root, addons=[NOBLOCK]): + log.debug("Skipping module named %s, resizing disabled", name) + return +diff --git a/cloudinit/config/cc_runcmd.py b/cloudinit/config/cc_runcmd.py +index 1f75d6c..6a2ff44 100644 +--- a/cloudinit/config/cc_runcmd.py ++++ b/cloudinit/config/cc_runcmd.py +@@ -84,7 +84,7 @@ def handle(name, cfg, cloud, log, _args): + " no 'runcmd' key in configuration"), name) + return + +- validate_cloudconfig_schema(cfg, schema) ++ validate_cloudconfig_schema(cfg, schema, log_details=False) + out_fn = os.path.join(cloud.get_ipath('scripts'), "runcmd") + cmd = cfg["runcmd"] + try: +diff --git a/cloudinit/config/cc_snap.py b/cloudinit/config/cc_snap.py +index 90724b8..6e17595 100644 +--- a/cloudinit/config/cc_snap.py ++++ b/cloudinit/config/cc_snap.py +@@ -220,7 +220,7 @@ def handle(name, cfg, cloud, log, args): + " no 'snap' key in configuration"), name) + return + +- validate_cloudconfig_schema(cfg, schema) ++ validate_cloudconfig_schema(cfg, schema, log_details=False) + if util.is_true(cfgin.get('squashfuse_in_container', False)): + maybe_install_squashfuse(cloud) + add_assertions(cfgin.get('assertions', [])) +diff --git a/cloudinit/config/cc_ubuntu_advantage.py b/cloudinit/config/cc_ubuntu_advantage.py +index f846e9a..f7bb82d 100644 +--- a/cloudinit/config/cc_ubuntu_advantage.py ++++ b/cloudinit/config/cc_ubuntu_advantage.py +@@ -164,7 +164,7 @@ def handle(name, cfg, cloud, log, args): + LOG.debug("Skipping module named %s," + " no 'ubuntu_advantage' configuration found", name) + return +- validate_cloudconfig_schema(cfg, schema) ++ validate_cloudconfig_schema(cfg, schema, log_details=False) + if 'commands' in ua_section: + msg = ( + 'Deprecated configuration "ubuntu-advantage: commands" provided.' +diff --git a/cloudinit/config/cc_ubuntu_drivers.py b/cloudinit/config/cc_ubuntu_drivers.py +index 297451d..8b84501 100644 +--- a/cloudinit/config/cc_ubuntu_drivers.py ++++ b/cloudinit/config/cc_ubuntu_drivers.py +@@ -156,5 +156,5 @@ def handle(name, cfg, cloud, log, _args): + log.debug("Skipping module named %s, no 'drivers' key in config", name) + return + +- validate_cloudconfig_schema(cfg, schema) ++ validate_cloudconfig_schema(cfg, schema, log_details=False) + install_drivers(cfg['drivers'], cloud.distro.install_packages) +diff --git a/cloudinit/config/tests/test_snap.py b/cloudinit/config/tests/test_snap.py +index 3c47289..794e8e6 100644 +--- a/cloudinit/config/tests/test_snap.py ++++ b/cloudinit/config/tests/test_snap.py +@@ -457,9 +457,8 @@ class TestHandle(CiTestCase): + 'cloudinit.config.cc_snap', + {'ASSERTIONS_FILE': {'new': assert_file}}, + handle, 'snap', cfg=cfg, cloud=None, log=self.logger, args=None) +- self.assertEqual( +- "WARNING: Invalid config:\nsnap: Additional properties are not" +- " allowed ('invalid' was unexpected)\n", ++ self.assertIn( ++ "Invalid config:Please run 'sudo cloud-init devel schema --system' or 'cloud-init devel schema -c config-file' to see the schema errors.", + self.logs.getvalue()) + + +diff --git a/tests/unittests/test_handler/test_handler_bootcmd.py b/tests/unittests/test_handler/test_handler_bootcmd.py +index a76760f..eb77252 100644 +--- a/tests/unittests/test_handler/test_handler_bootcmd.py ++++ b/tests/unittests/test_handler/test_handler_bootcmd.py +@@ -79,7 +79,8 @@ class TestBootcmd(CiTestCase): + with self.assertRaises(TypeError): + handle('cc_bootcmd', invalid_config, cc, LOG, []) + self.assertIn( +- 'Invalid config:\nbootcmd: 1 is not of type \'array\'', ++ "Invalid config:Please run 'sudo cloud-init devel schema --system' or" ++ " 'cloud-init devel schema -c config-file' to see the schema errors.", + self.logs.getvalue()) + self.assertIn('Failed to shellify', self.logs.getvalue()) + +@@ -96,9 +97,8 @@ class TestBootcmd(CiTestCase): + with self.assertRaises(TypeError) as context_manager: + handle('cc_bootcmd', invalid_config, cc, LOG, []) + expected_warnings = [ +- 'bootcmd.1: 20 is not valid under any of the given schemas', +- 'bootcmd.3: {\'a\': \'n\'} is not valid under any of the given' +- ' schema' ++ "Invalid config:Please run 'sudo cloud-init devel schema --system' or" ++ " 'cloud-init devel schema -c config-file' to see the schema errors.", + ] + logs = self.logs.getvalue() + for warning in expected_warnings: +diff --git a/tests/unittests/test_handler/test_handler_resizefs.py b/tests/unittests/test_handler/test_handler_resizefs.py +index db9a041..eda27b4 100644 +--- a/tests/unittests/test_handler/test_handler_resizefs.py ++++ b/tests/unittests/test_handler/test_handler_resizefs.py +@@ -82,8 +82,8 @@ class TestResizefs(CiTestCase): + handle('cc_resizefs', cfg, _cloud=None, log=LOG, args=[]) + logs = self.logs.getvalue() + self.assertIn( +- "WARNING: Invalid config:\nresize_rootfs: 'junk' is not one of" +- " [True, False, 'noblock']", ++ "Invalid config:Please run 'sudo cloud-init devel schema --system' or" ++ " 'cloud-init devel schema -c config-file' to see the schema errors.", + logs) + self.assertIn( + 'DEBUG: Skipping module named cc_resizefs, resizing disabled\n', +diff --git a/tests/unittests/test_handler/test_handler_runcmd.py b/tests/unittests/test_handler/test_handler_runcmd.py +index 9ce334a..5fea44e 100644 +--- a/tests/unittests/test_handler/test_handler_runcmd.py ++++ b/tests/unittests/test_handler/test_handler_runcmd.py +@@ -62,7 +62,8 @@ class TestRuncmd(FilesystemMockingTestCase): + cc = self._get_cloud('ubuntu') + handle('cc_runcmd', invalid_config, cc, LOG, []) + self.assertIn( +- 'Invalid config:\nruncmd: 1 is not of type \'array\'', ++ "Invalid config:Please run 'sudo cloud-init devel schema --system' or" ++ " 'cloud-init devel schema -c config-file' to see the schema errors.", + self.logs.getvalue()) + self.assertIn('Failed to shellify', self.logs.getvalue()) + +@@ -78,9 +79,8 @@ class TestRuncmd(FilesystemMockingTestCase): + cc = self._get_cloud('ubuntu') + handle('cc_runcmd', invalid_config, cc, LOG, []) + expected_warnings = [ +- 'runcmd.1: 20 is not valid under any of the given schemas', +- 'runcmd.3: {\'a\': \'n\'} is not valid under any of the given' +- ' schema' ++ "Invalid config:Please run 'sudo cloud-init devel schema --system' or" ++ " 'cloud-init devel schema -c config-file' to see the schema errors.", + ] + logs = self.logs.getvalue() + for warning in expected_warnings: +-- +2.33.0 + -- Gitee