Merge "Fix potential race condition in privileged ip_lib module"
This commit is contained in:
commit
027d09b8d4
@ -48,7 +48,18 @@ class NetworkNamespaceNotFound(RuntimeError):
|
|||||||
|
|
||||||
|
|
||||||
class NetworkInterfaceNotFound(RuntimeError):
|
class NetworkInterfaceNotFound(RuntimeError):
|
||||||
pass
|
message = _("Network interface %(device)s not found in namespace "
|
||||||
|
"%(namespace)s.")
|
||||||
|
|
||||||
|
def __init__(self, message=None, device=None, namespace=None):
|
||||||
|
# NOTE(slaweq): 'message' can be passed as an optional argument
|
||||||
|
# because of how privsep daemon works. If exception is raised in
|
||||||
|
# function called by privsep daemon, it will then try to reraise it
|
||||||
|
# and will call it always with passing only message from originally
|
||||||
|
# raised exception.
|
||||||
|
message = message or self.message % {
|
||||||
|
'device': device, 'namespace': namespace}
|
||||||
|
super(NetworkInterfaceNotFound, self).__init__(message)
|
||||||
|
|
||||||
|
|
||||||
class IpAddressAlreadyExists(RuntimeError):
|
class IpAddressAlreadyExists(RuntimeError):
|
||||||
@ -110,10 +121,7 @@ def _get_link_id(device, namespace):
|
|||||||
with _get_iproute(namespace) as ip:
|
with _get_iproute(namespace) as ip:
|
||||||
return ip.link_lookup(ifname=device)[0]
|
return ip.link_lookup(ifname=device)[0]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
msg = _("Network interface %(device)s not found in namespace "
|
raise NetworkInterfaceNotFound(device=device, namespace=namespace)
|
||||||
"%(namespace)s.") % {'device': device,
|
|
||||||
'namespace': namespace}
|
|
||||||
raise NetworkInterfaceNotFound(msg)
|
|
||||||
|
|
||||||
|
|
||||||
def _run_iproute_link(command, device, namespace=None, **kwargs):
|
def _run_iproute_link(command, device, namespace=None, **kwargs):
|
||||||
@ -121,6 +129,10 @@ def _run_iproute_link(command, device, namespace=None, **kwargs):
|
|||||||
with _get_iproute(namespace) as ip:
|
with _get_iproute(namespace) as ip:
|
||||||
idx = _get_link_id(device, namespace)
|
idx = _get_link_id(device, namespace)
|
||||||
return ip.link(command, index=idx, **kwargs)
|
return ip.link(command, index=idx, **kwargs)
|
||||||
|
except NetlinkError as e:
|
||||||
|
if e.code == errno.ENODEV:
|
||||||
|
raise NetworkInterfaceNotFound(device=device, namespace=namespace)
|
||||||
|
raise
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno == errno.ENOENT:
|
if e.errno == errno.ENOENT:
|
||||||
raise NetworkNamespaceNotFound(netns_name=namespace)
|
raise NetworkNamespaceNotFound(netns_name=namespace)
|
||||||
@ -132,6 +144,10 @@ def _run_iproute_neigh(command, device, namespace, **kwargs):
|
|||||||
with _get_iproute(namespace) as ip:
|
with _get_iproute(namespace) as ip:
|
||||||
idx = _get_link_id(device, namespace)
|
idx = _get_link_id(device, namespace)
|
||||||
return ip.neigh(command, ifindex=idx, **kwargs)
|
return ip.neigh(command, ifindex=idx, **kwargs)
|
||||||
|
except NetlinkError as e:
|
||||||
|
if e.code == errno.ENODEV:
|
||||||
|
raise NetworkInterfaceNotFound(device=device, namespace=namespace)
|
||||||
|
raise
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno == errno.ENOENT:
|
if e.errno == errno.ENOENT:
|
||||||
raise NetworkNamespaceNotFound(netns_name=namespace)
|
raise NetworkNamespaceNotFound(netns_name=namespace)
|
||||||
@ -143,6 +159,10 @@ def _run_iproute_addr(command, device, namespace, **kwargs):
|
|||||||
with _get_iproute(namespace) as ip:
|
with _get_iproute(namespace) as ip:
|
||||||
idx = _get_link_id(device, namespace)
|
idx = _get_link_id(device, namespace)
|
||||||
return ip.addr(command, index=idx, **kwargs)
|
return ip.addr(command, index=idx, **kwargs)
|
||||||
|
except NetlinkError as e:
|
||||||
|
if e.code == errno.ENODEV:
|
||||||
|
raise NetworkInterfaceNotFound(device=device, namespace=namespace)
|
||||||
|
raise
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno == errno.ENOENT:
|
if e.errno == errno.ENOENT:
|
||||||
raise NetworkNamespaceNotFound(netns_name=namespace)
|
raise NetworkNamespaceNotFound(netns_name=namespace)
|
||||||
|
@ -51,6 +51,17 @@ class IpLibTestCase(base.BaseTestCase):
|
|||||||
priv_lib._run_iproute_link,
|
priv_lib._run_iproute_link,
|
||||||
"test_cmd", "eth0", None, test_param="test_value")
|
"test_cmd", "eth0", None, test_param="test_value")
|
||||||
|
|
||||||
|
def test_run_iproute_link_interface_removed_during_call(self):
|
||||||
|
with mock.patch.object(pyroute2, "IPRoute") as iproute_mock:
|
||||||
|
ip_mock = iproute_mock()
|
||||||
|
ip_mock.__enter__().link_lookup.return_value = [2]
|
||||||
|
ip_mock.__enter__().link.side_effect = pyroute2.NetlinkError(
|
||||||
|
code=errno.ENODEV)
|
||||||
|
self.assertRaises(
|
||||||
|
priv_lib.NetworkInterfaceNotFound,
|
||||||
|
priv_lib._run_iproute_link,
|
||||||
|
"test_cmd", "eth0", None, test_param="test_value")
|
||||||
|
|
||||||
def test_run_iproute_link_namespace_not_exists(self):
|
def test_run_iproute_link_namespace_not_exists(self):
|
||||||
with mock.patch.object(pyroute2, "IPRoute") as iproute_mock:
|
with mock.patch.object(pyroute2, "IPRoute") as iproute_mock:
|
||||||
iproute_mock.side_effect = OSError(
|
iproute_mock.side_effect = OSError(
|
||||||
@ -99,6 +110,17 @@ class IpLibTestCase(base.BaseTestCase):
|
|||||||
priv_lib._run_iproute_neigh,
|
priv_lib._run_iproute_neigh,
|
||||||
"test_cmd", "eth0", None, test_param="test_value")
|
"test_cmd", "eth0", None, test_param="test_value")
|
||||||
|
|
||||||
|
def test_run_iproute_neigh_interface_removed_during_call(self):
|
||||||
|
with mock.patch.object(pyroute2, "IPRoute") as iproute_mock:
|
||||||
|
ip_mock = iproute_mock()
|
||||||
|
ip_mock.__enter__().link_lookup.return_value = [2]
|
||||||
|
ip_mock.__enter__().neigh.side_effect = pyroute2.NetlinkError(
|
||||||
|
code=errno.ENODEV)
|
||||||
|
self.assertRaises(
|
||||||
|
priv_lib.NetworkInterfaceNotFound,
|
||||||
|
priv_lib._run_iproute_neigh,
|
||||||
|
"test_cmd", "eth0", None, test_param="test_value")
|
||||||
|
|
||||||
def test_run_iproute_neigh_namespace_not_exists(self):
|
def test_run_iproute_neigh_namespace_not_exists(self):
|
||||||
with mock.patch.object(pyroute2, "IPRoute") as iproute_mock:
|
with mock.patch.object(pyroute2, "IPRoute") as iproute_mock:
|
||||||
iproute_mock.side_effect = OSError(
|
iproute_mock.side_effect = OSError(
|
||||||
@ -147,6 +169,17 @@ class IpLibTestCase(base.BaseTestCase):
|
|||||||
priv_lib._run_iproute_addr,
|
priv_lib._run_iproute_addr,
|
||||||
"test_cmd", "eth0", None, test_param="test_value")
|
"test_cmd", "eth0", None, test_param="test_value")
|
||||||
|
|
||||||
|
def test_run_iproute_addr_interface_removed_during_call(self):
|
||||||
|
with mock.patch.object(pyroute2, "IPRoute") as iproute_mock:
|
||||||
|
ip_mock = iproute_mock()
|
||||||
|
ip_mock.__enter__().link_lookup.return_value = [2]
|
||||||
|
ip_mock.__enter__().addr.side_effect = pyroute2.NetlinkError(
|
||||||
|
code=errno.ENODEV)
|
||||||
|
self.assertRaises(
|
||||||
|
priv_lib.NetworkInterfaceNotFound,
|
||||||
|
priv_lib._run_iproute_addr,
|
||||||
|
"test_cmd", "eth0", None, test_param="test_value")
|
||||||
|
|
||||||
def test_run_iproute_addr_namespace_not_exists(self):
|
def test_run_iproute_addr_namespace_not_exists(self):
|
||||||
with mock.patch.object(pyroute2, "IPRoute") as iproute_mock:
|
with mock.patch.object(pyroute2, "IPRoute") as iproute_mock:
|
||||||
iproute_mock.side_effect = OSError(
|
iproute_mock.side_effect = OSError(
|
||||||
|
Loading…
Reference in New Issue
Block a user