From 5964adea8c71dfcac22565b3a53ca12aebdc4d8c Mon Sep 17 00:00:00 2001 From: Oyvind Albrigtsen Date: Thu, 30 May 2024 09:13:43 +0200 Subject: [PATCH] - fence_eps: add fence_epsr2 for ePowerSwitch R2 and newer Resolves: RHEL-7734 - bundled jinja2: fix CVE-2024-34064 Resolves: RHEL-35655 --- ...rt-fix-bundled-jinja2-CVE-2024-34064.patch | 65 ++++ ..._epsr2-for-ePowerSwitch-R2-and-newer.patch | 365 ++++++++++++++++++ fence-agents.spec | 12 +- 3 files changed, 441 insertions(+), 1 deletion(-) create mode 100644 RHEL-35655-kubevirt-fix-bundled-jinja2-CVE-2024-34064.patch create mode 100644 RHEL-7734-fence_eps-add-fence_epsr2-for-ePowerSwitch-R2-and-newer.patch diff --git a/RHEL-35655-kubevirt-fix-bundled-jinja2-CVE-2024-34064.patch b/RHEL-35655-kubevirt-fix-bundled-jinja2-CVE-2024-34064.patch new file mode 100644 index 0000000..700ab80 --- /dev/null +++ b/RHEL-35655-kubevirt-fix-bundled-jinja2-CVE-2024-34064.patch @@ -0,0 +1,65 @@ +From d655030770081e2dfe46f90e27620472a502289d Mon Sep 17 00:00:00 2001 +From: David Lord +Date: Thu, 2 May 2024 09:14:00 -0700 +Subject: [PATCH] disallow invalid characters in keys to xmlattr filter + +--- + CHANGES.rst | 6 ++++++ + src/jinja2/filters.py | 22 +++++++++++++++++----- + tests/test_filters.py | 11 ++++++----- + 3 files changed, 29 insertions(+), 10 deletions(-) + +diff --git a/kubevirt/jinja2/filters.py b/kubevirt/jinja2/filters.py +index 4cf3c11fb..acd11976e 100644 +--- a/kubevirt/jinja2/filters.py ++++ b/kubevirt/jinja2/filters.py +@@ -250,7 +250,9 @@ def do_items(value: t.Union[t.Mapping[K, V], Undefined]) -> t.Iterator[t.Tuple[K + yield from value.items() + + +-_space_re = re.compile(r"\s", flags=re.ASCII) ++# Check for characters that would move the parser state from key to value. ++# https://html.spec.whatwg.org/#attribute-name-state ++_attr_key_re = re.compile(r"[\s/>=]", flags=re.ASCII) + + + @pass_eval_context +@@ -259,8 +261,14 @@ def do_xmlattr( + ) -> str: + """Create an SGML/XML attribute string based on the items in a dict. + +- If any key contains a space, this fails with a ``ValueError``. Values that +- are neither ``none`` nor ``undefined`` are automatically escaped. ++ **Values** that are neither ``none`` nor ``undefined`` are automatically ++ escaped, safely allowing untrusted user input. ++ ++ User input should not be used as **keys** to this filter. If any key ++ contains a space, ``/`` solidus, ``>`` greater-than sign, or ``=`` equals ++ sign, this fails with a ``ValueError``. Regardless of this, user input ++ should never be used as keys to this filter, or must be separately validated ++ first. + + .. sourcecode:: html+jinja + +@@ -280,6 +288,10 @@ def do_xmlattr( + As you can see it automatically prepends a space in front of the item + if the filter returned something unless the second parameter is false. + ++ .. versionchanged:: 3.1.4 ++ Keys with ``/`` solidus, ``>`` greater-than sign, or ``=`` equals sign ++ are not allowed. ++ + .. versionchanged:: 3.1.3 + Keys with spaces are not allowed. + """ +@@ -289,8 +301,8 @@ def do_xmlattr( + if value is None or isinstance(value, Undefined): + continue + +- if _space_re.search(key) is not None: +- raise ValueError(f"Spaces are not allowed in attributes: '{key}'") ++ if _attr_key_re.search(key) is not None: ++ raise ValueError(f"Invalid character in attribute name: {key!r}") + + items.append(f'{escape(key)}="{escape(value)}"') + diff --git a/RHEL-7734-fence_eps-add-fence_epsr2-for-ePowerSwitch-R2-and-newer.patch b/RHEL-7734-fence_eps-add-fence_epsr2-for-ePowerSwitch-R2-and-newer.patch new file mode 100644 index 0000000..f59b730 --- /dev/null +++ b/RHEL-7734-fence_eps-add-fence_epsr2-for-ePowerSwitch-R2-and-newer.patch @@ -0,0 +1,365 @@ +From 55451b6fd007e6f9a6d6860e95304b7c5c27cc1b Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Thu, 2 May 2024 15:10:16 +0200 +Subject: [PATCH 1/2] fencing: add support for docs["agent_name"] to use the + main agent name when generating manpages + +--- + lib/fencing.py.py | 12 +++++++++--- + tests/data/metadata/fence_eps.xml | 9 ++++++--- + 2 files changed, 15 insertions(+), 6 deletions(-) + +diff --git a/lib/fencing.py.py b/lib/fencing.py.py +index 511eb2689..66e2ff156 100644 +--- a/lib/fencing.py.py ++++ b/lib/fencing.py.py +@@ -603,7 +603,7 @@ def usage(avail_opt): + if len(value["help"]) != 0: + print(" " + _join_wrap([value["help"]], first_indent=3)) + +-def metadata(options, avail_opt, docs): ++def metadata(options, avail_opt, docs, agent_name=os.path.basename(sys.argv[0])): + # avail_opt has to be unique, if there are duplicities then they should be removed + sorted_list = [(key, all_opt[key]) for key in list(set(avail_opt)) if "longopt" in all_opt[key]] + # Find keys that are going to replace inconsistent names +@@ -617,7 +617,7 @@ def metadata(options, avail_opt, docs): + docs["longdesc"] = re.sub(r"\\f[BPIR]|\.P|\.TP|\.br\n", r"", docs["longdesc"]) + + print("") +- print("") + for (symlink, desc) in docs.get("symlink", []): + print("") +@@ -928,9 +928,15 @@ def show_docs(options, docs=None): + sys.exit(0) + + if options.get("--action", "") in ["metadata", "manpage"]: ++ if options["--action"] == "metadata" or "agent_name" not in docs: ++ agent_name=os.path.basename(sys.argv[0]) ++ else: ++ agent_name=docs["agent_name"] ++ ++ + if "port_as_ip" in device_opt: + device_opt.remove("separator") +- metadata(options, device_opt, docs) ++ metadata(options, device_opt, docs, agent_name) + sys.exit(0) + + if "--version" in options: +diff --git a/tests/data/metadata/fence_eps.xml b/tests/data/metadata/fence_eps.xml +index 3f9ebdc22..a3aeb1aea 100644 +--- a/tests/data/metadata/fence_eps.xml ++++ b/tests/data/metadata/fence_eps.xml +@@ -1,9 +1,12 @@ + + +-fence_eps is a Power Fencing agent which can be used with the ePowerSwitch 8M+ power switch to fence connected machines. Fence agent works ONLY on 8M+ device, because this is only one, which has support for hidden page feature. ++ ++fence_eps is a Power Fencing agent which can be used with the ePowerSwitch 8M+ power switch to fence connected machines. It ONLY works on 8M+ devices, as they support the hidden page feature. + +-Agent basically works by connecting to hidden page and pass appropriate arguments to GET request. This means, that hidden page feature must be enabled and properly configured. +-http://www.epowerswitch.com ++The agent works by connecting to the hidden page and pass the appropriate arguments to GET request. This means, that the hidden page feature must be enabled and properly configured. ++ ++NOTE: In most cases you want to use fence_epsr2, as fence_eps only works with older hardware. ++https://www.neol.com + + + + +From 639f5293e0b2c0153ea01bf37534b74f436dd630 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Tue, 13 Feb 2024 11:11:25 +0100 +Subject: [PATCH 2/2] fence_eps: add fence_epsr2 for ePowerSwitch R2 and newer + +--- + agents/eps/fence_eps.py | 46 ++++--- + fence-agents.spec.in | 4 +- + tests/data/metadata/fence_epsr2.xml | 178 ++++++++++++++++++++++++++++ + 3 files changed, 211 insertions(+), 17 deletions(-) + create mode 100644 tests/data/metadata/fence_epsr2.xml + +diff --git a/agents/eps/fence_eps.py b/agents/eps/fence_eps.py +index 81e439533..1e6bda099 100644 +--- a/agents/eps/fence_eps.py ++++ b/agents/eps/fence_eps.py +@@ -3,8 +3,8 @@ + # The Following Agent Has Been Tested On: + # ePowerSwitch 8M+ version 1.0.0.4 + +-import sys, re +-import base64, string, socket ++import sys, os, re ++import base64, socket + import logging + import atexit + sys.path.append("@FENCEAGENTSLIBDIR@") +@@ -37,7 +37,7 @@ def eps_run_command(options, params): + options["--password"] = "" # Default is empty password + + # String for Authorization header +- auth_str = 'Basic ' + string.strip(base64.encodestring(options["--username"]+':'+options["--password"])) ++ auth_str = 'Basic ' + str(base64.encodebytes(bytes(options["--username"]+':'+options["--password"], "utf-8")).decode("utf-8").strip()) + logging.debug("Authorization: %s\n", auth_str) + conn.putheader('Authorization', auth_str) + +@@ -60,16 +60,22 @@ def eps_run_command(options, params): + logging.error("Failed: {}".format(str(e))) + fail(EC_LOGIN_DENIED) + +- return result ++ return result.decode("utf-8", "ignore") + + def get_power_status(conn, options): + del conn + ret_val = eps_run_command(options, "") + + result = {} +- status = re.findall(r"p(\d{2})=(0|1)\s*\", ret_val.lower()) ++ if os.path.basename(sys.argv[0]) == "fence_eps": ++ status = re.findall(r"p(\d{2})=(0|1)\s*\", ret_val.lower()) ++ elif os.path.basename(sys.argv[0]) == "fence_epsr2": ++ status = re.findall(r"m0:o(\d)=(on|off)\s*", ret_val.lower()) + for out_num, out_stat in status: +- result[out_num] = ("", (out_stat == "1" and "on" or "off")) ++ if os.path.basename(sys.argv[0]) == "fence_eps": ++ result[out_num] = ("", (out_stat == "1" and "on" or "off")) ++ elif os.path.basename(sys.argv[0]) == "fence_epsr2": ++ result[out_num] = ("", out_stat) + + if not options["--action"] in ['monitor', 'list']: + if not options["--plug"] in result: +@@ -81,7 +87,12 @@ def get_power_status(conn, options): + + def set_power_status(conn, options): + del conn +- eps_run_command(options, "P%s=%s"%(options["--plug"], (options["--action"] == "on" and "1" or "0"))) ++ if os.path.basename(sys.argv[0]) == "fence_eps": ++ eps_run_command(options, "P%s=%s"%(options["--plug"], (options["--action"] == "on" and "1" or "0"))) ++ elif os.path.basename(sys.argv[0]) == "fence_epsr2": ++ if options["--action"] == "reboot": ++ options["--action"] = "off" ++ eps_run_command(options, "M0:O%s=%s"%(options["--plug"], options["--action"])) + + # Define new option + def eps_define_new_opts(): +@@ -107,20 +118,25 @@ def main(): + options = check_input(device_opt, process_input(device_opt)) + + docs = {} ++ docs["agent_name"] = "fence_eps" + docs["shortdesc"] = "Fence agent for ePowerSwitch" +- docs["longdesc"] = "fence_eps is a Power Fencing agent \ ++ docs["longdesc"] = os.path.basename(sys.argv[0]) + " is a Power Fencing agent \ + which can be used with the ePowerSwitch 8M+ power switch to fence \ +-connected machines. Fence agent works ONLY on 8M+ device, because \ +-this is only one, which has support for hidden page feature. \ ++connected machines. It ONLY works on 8M+ devices, as \ ++they support the hidden page feature. \ + \n.TP\n\ +-Agent basically works by connecting to hidden page and pass \ +-appropriate arguments to GET request. This means, that hidden \ +-page feature must be enabled and properly configured." +- docs["vendorurl"] = "http://www.epowerswitch.com" ++The agent works by connecting to the hidden page and pass \ ++the appropriate arguments to GET request. This means, that the hidden \ ++page feature must be enabled and properly configured. \ ++\n.TP\n\ ++NOTE: In most cases you want to use fence_epsr2, as fence_eps \ ++only works with older hardware." ++ docs["vendorurl"] = "https://www.neol.com" ++ docs["symlink"] = [("fence_epsr2", "Fence agent for ePowerSwitch R2 and newer")] + show_docs(options, docs) + + run_delay(options) +- #Run fence action. Conn is None, beacause we always need open new http connection ++ #Run fence action. Conn is None, because we always need open new http connection + result = fence_action(None, options, set_power_status, get_power_status, get_power_status) + + sys.exit(result) +diff --git a/tests/data/metadata/fence_epsr2.xml b/tests/data/metadata/fence_epsr2.xml +new file mode 100644 +index 000000000..37074e052 +--- /dev/null ++++ b/tests/data/metadata/fence_epsr2.xml +@@ -0,0 +1,178 @@ ++ ++ ++ ++fence_epsr2 is a Power Fencing agent which can be used with the ePowerSwitch 8M+ power switch to fence connected machines. It ONLY works on 8M+ devices, as they support the hidden page feature. ++ ++The agent works by connecting to the hidden page and pass the appropriate arguments to GET request. This means, that the hidden page feature must be enabled and properly configured. ++ ++NOTE: In most cases you want to use fence_epsr2, as fence_eps only works with older hardware. ++https://www.neol.com ++ ++ ++ ++ ++ Fencing action ++ ++ ++ ++ ++ Name of hidden page ++ ++ ++ ++ ++ IP address or hostname of fencing device ++ ++ ++ ++ ++ IP address or hostname of fencing device ++ ++ ++ ++ ++ TCP/UDP port to use for connection with device ++ ++ ++ ++ ++ Login name ++ ++ ++ ++ ++ Name of hidden page ++ ++ ++ ++ ++ Login password or passphrase ++ ++ ++ ++ ++ Script to run to retrieve password ++ ++ ++ ++ ++ Login password or passphrase ++ ++ ++ ++ ++ Script to run to retrieve password ++ ++ ++ ++ ++ Physical plug number on device, UUID or identification of machine ++ ++ ++ ++ ++ Physical plug number on device, UUID or identification of machine ++ ++ ++ ++ ++ Login name ++ ++ ++ ++ ++ Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog. ++ ++ ++ ++ ++ Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity. ++ ++ ++ ++ ++ Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin). ++ ++ ++ ++ ++ Write debug information to given file ++ ++ ++ ++ Write debug information to given file ++ ++ ++ ++ ++ Display version information and exit ++ ++ ++ ++ ++ Display help and exit ++ ++ ++ ++ ++ Separator for plug parameter when specifying more than 1 plug ++ ++ ++ ++ ++ Separator for CSV created by 'list' operation ++ ++ ++ ++ ++ Wait X seconds before fencing is started ++ ++ ++ ++ ++ Disable timeout (true/false) (default: true when run from Pacemaker 2.0+) ++ ++ ++ ++ ++ Wait X seconds for cmd prompt after login ++ ++ ++ ++ ++ Test X seconds for status change after ON/OFF ++ ++ ++ ++ ++ Wait X seconds after issuing ON/OFF ++ ++ ++ ++ ++ Wait X seconds for cmd prompt after issuing command ++ ++ ++ ++ ++ Sleep X seconds between status calls during a STONITH action ++ ++ ++ ++ ++ Count of attempts to retry power on ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ diff --git a/fence-agents.spec b/fence-agents.spec index 0d43cb1..7e0ee54 100644 --- a/fence-agents.spec +++ b/fence-agents.spec @@ -87,7 +87,7 @@ Name: fence-agents Summary: Set of unified programs capable of host isolation ("fencing") Version: 4.2.1 -Release: 129%{?alphatag:.%{alphatag}}%{?dist} +Release: 129%{?alphatag:.%{alphatag}}%{?dist}.1 License: GPLv2+ and LGPLv2+ Group: System Environment/Base URL: https://github.com/ClusterLabs/fence-agents @@ -282,11 +282,13 @@ Patch139: RHEL-5397-fence_scsi-2-fix-ISID-reg-handling-off.patch Patch140: RHEL-5397-fence_scsi-3-fix-run_cmd.patch Patch141: RHEL-5397-4-fence_scsi-log-err.patch Patch142: RHEL-14343-fence_zvmip-2-fix-manpage-formatting.patch +Patch143: RHEL-7734-fence_eps-add-fence_epsr2-for-ePowerSwitch-R2-and-newer.patch ### HA support libs/utils ### # all archs Patch1000: bz2218234-1-kubevirt-fix-bundled-dateutil-CVE-2007-4559.patch Patch1001: RHEL-22174-kubevirt-fix-bundled-jinja2-CVE-2024-22195.patch +Patch1002: RHEL-35655-kubevirt-fix-bundled-jinja2-CVE-2024-34064.patch # cloud (x86_64 only) Patch2000: bz2218234-2-aws-fix-bundled-dateutil-CVE-2007-4559.patch @@ -509,6 +511,7 @@ BuildRequires: python3-google-api-client python3-pip python3-wheel python3-jinja %patch -p1 -P 140 %patch -p1 -P 141 %patch -p1 -P 142 +%patch -p1 -P 143 -F1 # prevent compilation of something that won't get used anyway sed -i.orig 's|FENCE_ZVM=1|FENCE_ZVM=0|' configure.ac @@ -623,6 +626,7 @@ rm -rf %{buildroot}/usr/lib/fence-agents/%{bundled_lib_dir}/kubevirt/rsa* pushd %{buildroot}/usr/lib/fence-agents/%{bundled_lib_dir} /usr/bin/patch --no-backup-if-mismatch -p1 --fuzz=0 < %{PATCH1000} /usr/bin/patch --no-backup-if-mismatch -p1 --fuzz=1 < %{PATCH1001} +/usr/bin/patch --no-backup-if-mismatch -p1 --fuzz=1 < %{PATCH1002} %ifarch x86_64 /usr/bin/patch --no-backup-if-mismatch -p1 --fuzz=0 < %{PATCH2000} @@ -1516,6 +1520,12 @@ Fence agent for IBM z/VM over IP. %endif %changelog +* Thu May 30 2024 Oyvind Albrigtsen - 4.2.1-129.1 +- fence_eps: add fence_epsr2 for ePowerSwitch R2 and newer + Resolves: RHEL-7734 +- bundled jinja2: fix CVE-2024-34064 + Resolves: RHEL-35655 + * Fri Jan 19 2024 Oyvind Albrigtsen - 4.2.1-129 - bundled urllib3: fix CVE-2023-45803 Resolves: RHEL-18132