Headline
CVE-2022-46174: Fix potential tlsport selection collision by using state file as · aws/efs-utils@f3a8f88
efs-utils is a set of Utilities for Amazon Elastic File System (EFS). A potential race condition issue exists within the Amazon EFS mount helper in efs-utils versions v1.34.3 and below. When using TLS to mount file systems, the mount helper allocates a local port for stunnel to receive NFS connections prior to applying the TLS tunnel. In affected versions, concurrent mount operations can allocate the same local port, leading to either failed mount operations or an inappropriate mapping from an EFS customer’s local mount points to that customer’s EFS file systems. This issue is patched in version v1.34.4. There is no recommended work around. We recommend affected users update the installed version of efs-utils to v1.34.4 or later.
@@ -3,9 +3,12 @@ # Licensed under the MIT License. See the LICENSE accompanying this file # for the specific language governing permissions and limitations under # the License.
import logging import random import socket import sys import tempfile import unittest from unittest.mock import MagicMock
import pytest @@ -45,42 +48,70 @@ def _get_config(): return config
def test_choose_tls_port_first_try(mocker): def test_choose_tls_port_first_try(mocker, tmpdir): sock_mock = MagicMock() sock_mock.getsockname.return_value = ("local_host", DEFAULT_TLS_PORT) mocker.patch("socket.socket", return_value=sock_mock) options = {}
tls_port_sock = mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), options) tls_port_sock = mount_efs.choose_tls_port_and_get_bind_sock( _get_config(), options, str(tmpdir) ) tls_port = mount_efs.get_tls_port_from_sock(tls_port_sock) assert DEFAULT_TLS_PORT_RANGE_LOW <= tls_port <= DEFAULT_TLS_PORT_RANGE_HIGH
def test_choose_tls_port_second_try(mocker): def test_choose_tls_port_second_try(mocker, tmpdir): bad_sock = MagicMock() bad_sock.bind.side_effect = [socket.error, None] bad_sock.getsockname.return_value = ("local_host", DEFAULT_TLS_PORT) options = {}
mocker.patch("socket.socket", return_value=bad_sock)
tls_port_sock = mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), options) tls_port_sock = mount_efs.choose_tls_port_and_get_bind_sock( _get_config(), options, str(tmpdir) ) tls_port = mount_efs.get_tls_port_from_sock(tls_port_sock)
assert DEFAULT_TLS_PORT_RANGE_LOW <= tls_port <= DEFAULT_TLS_PORT_RANGE_HIGH assert 2 == bad_sock.bind.call_count assert 1 == bad_sock.getsockname.call_count
def test_choose_tls_port_never_succeeds(mocker, capsys): @unittest.skipIf(sys.version_info < (3, 6), reason="requires python3.6") def test_choose_tls_port_collision(mocker, tmpdir, caplog): “""Ensure we don’t choose a port that is pending mount""” sock = MagicMock() mocker.patch("socket.socket", return_value=sock) mocker.patch( "random.shuffle", return_value=range(DEFAULT_TLS_PORT_RANGE_LOW, DEFAULT_TLS_PORT_RANGE_HIGH), )
port_suffix = “.%s” % str(DEFAULT_TLS_PORT_RANGE_LOW) temp_state_file = tempfile.NamedTemporaryFile( suffix=port_suffix, prefix="~", dir=tmpdir )
options = {} with caplog.at_level(logging.DEBUG): mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), options, tmpdir)
temp_state_file.close() sock.bind.assert_called_once_with(("localhost", DEFAULT_TLS_PORT_RANGE_LOW + 1)) assert “Skip binding TLS port” in caplog.text
def test_choose_tls_port_never_succeeds(mocker, tmpdir, capsys): bad_sock = MagicMock() bad_sock.bind.side_effect = socket.error() options = {}
mocker.patch("socket.socket", return_value=bad_sock)
with pytest.raises(SystemExit) as ex: mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), options) mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), options, str(tmpdir))
assert 0 != ex.value.code
@@ -93,27 +124,29 @@ def test_choose_tls_port_never_succeeds(mocker, capsys): )
def test_choose_tls_port_option_specified(mocker): def test_choose_tls_port_option_specified(mocker, tmpdir): sock_mock = MagicMock() sock_mock.getsockname.return_value = ("local_host", DEFAULT_TLS_PORT) mocker.patch("socket.socket", return_value=sock_mock) options = {"tlsport": DEFAULT_TLS_PORT}
tls_port_sock = mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), options) tls_port_sock = mount_efs.choose_tls_port_and_get_bind_sock( _get_config(), options, str(tmpdir) ) tls_port = mount_efs.get_tls_port_from_sock(tls_port_sock)
assert DEFAULT_TLS_PORT == tls_port
def test_choose_tls_port_option_specified_unavailable(mocker, capsys): def test_choose_tls_port_option_specified_unavailable(mocker, tmpdir, capsys): bad_sock = MagicMock() bad_sock.bind.side_effect = socket.error() options = {"tlsport": 1000}
mocker.patch("socket.socket", return_value=bad_sock)
with pytest.raises(SystemExit) as ex: mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), options) mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), options, str(tmpdir))
assert 0 != ex.value.code
@@ -123,13 +156,13 @@ def test_choose_tls_port_option_specified_unavailable(mocker, capsys): assert 1 == bad_sock.bind.call_count
def test_choose_tls_port_under_netns(mocker, capsys): def test_choose_tls_port_under_netns(mocker, tmpdir): mocker.patch(“builtins.open”) setns_mock = mocker.patch("mount_efs.setns", return_value=(None, None)) mocker.patch("socket.socket", return_value=MagicMock()) options = {"netns": "/proc/1000/ns/net"}
mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), options) mount_efs.choose_tls_port_and_get_bind_sock(_get_config(), options, str(tmpdir)) utils.assert_called(setns_mock)
Related news
Red Hat Security Advisory 2023-0450-01 - Red Hat OpenShift Container Platform is Red Hat's cloud computing Kubernetes application platform solution designed for on-premise or private cloud deployments.
Red Hat OpenShift Container Platform release 4.12.1 is now available with updates to packages and images that fix several bugs and add enhancements. Red Hat Product Security has rated this update as having a security impact of Moderate. A Common Vulnerability Scoring System (CVSS) base score, which gives a detailed severity rating, is available for each vulnerability from the CVE link(s) in the References section.This content is licensed under the Creative Commons Attribution 4.0 International License (https://creativecommons.org/licenses/by/4.0/). If you distribute this content, or a modified version of it, you must provide attribution to Red Hat Inc. and provide a link to the original. Related CVEs: * CVE-2022-46174: aws-efs-utils: Race condition during concurrent TLS mounts in efs-utils and aws-efs-csi-driver
### Impact A potential race condition issue exists within the Amazon EFS mount helper in efs-utils versions v1.34.3 and below, and aws-efs-csi-driver versions v1.4.7 and below. When using TLS to mount file systems, the mount helper allocates a local port for stunnel to receive NFS connections prior to applying the TLS tunnel. In affected versions, concurrent mount operations can allocate the same local port, leading to either failed mount operations or an inappropriate mapping from an EFS customer’s local mount points to that customer’s EFS file systems. Affected versions: efs-utils <= v1.34.3, aws-efs-csi-driver <= v1.4.7 ### Patches The patches are included in efs-utils version v1.34.4 and newer, and in aws-efs-csi-driver v1.4.8 and newer. ### Workarounds There is no recommended work around. We recommend affected users update the installed version of efs-utils to v1.34.4+ or aws-efs-csi-driver to v1.4.8+ to address this issue. ### References https://github.com/aws/efs-utils/commi...