Remove rootwrap execution (5)

Replace rootwrap execution with privsep context execution.
This series of patches will progressively replace any
rootwrap call.

This patch migrates some missing execution methods present in
the code and removes unneeded rootwrap filters.

Story: #2007686
Task: #41558

Change-Id: I1542dc4cf98658fc9a40018192498c7a5cd1c3fe
This commit is contained in:
Rodolfo Alonso Hernandez 2021-02-04 17:30:28 +00:00
parent 90309cf6e2
commit 5a419cbc84
15 changed files with 46 additions and 89 deletions

View File

@ -8,13 +8,6 @@
[Filters]
# This is needed because we should ping
# from inside a namespace which requires root
# _alt variants allow to match -c and -w in any order
# (used by NeutronDebugAgent.ping_all)
ping: CommandFilter, ping, root
ping6: CommandFilter, ping6, root
# "sleep" command, only for testing
sleep: RegExpFilter, sleep, root, sleep, \d+
kill_sleep: KillFilter, root, sleep, -9

View File

@ -1,15 +0,0 @@
# neutron-rootwrap command filters for nodes on which neutron is
# expected to control network
#
# This file should be owned by (and only-writeable by) the root user
# format seems to be
# cmd-name: filter-name, raw-command, user, args
[Filters]
# neutron/agent/linux/iptables_firewall.py
sysctl: CommandFilter, sysctl, root
# neutron/agent/linux/ip_conntrack.py
conntrack: CommandFilter, conntrack, root

View File

@ -8,11 +8,7 @@
[Filters]
# arping
arping: CommandFilter, arping, root
# l3_agent
sysctl: CommandFilter, sysctl, root
route: CommandFilter, route, root
radvd: CommandFilter, radvd, root
@ -30,12 +26,6 @@ kill_radvd_script: CommandFilter, radvd-kill, root
ip: IpFilter, ip, root
ip_exec: IpNetnsExecFilter, ip, root
# l3_tc_lib
l3_tc_show_filters: RegExpFilter, tc, root, tc, -p, -s, -d, filter, show, dev, .+, parent, .+, prio, 1
l3_tc_delete_filters: RegExpFilter, tc, root, tc, filter, del, dev, .+, parent, .+, prio, 1, handle, .+, u32
l3_tc_add_filter_ingress: RegExpFilter, tc, root, tc, filter, add, dev, .+, parent, .+, protocol, ip, prio, 1, u32, match, ip, dst, .+, police, rate, .+, burst, .+, mtu, 64kb, drop, flowid, :1
l3_tc_add_filter_egress: RegExpFilter, tc, root, tc, filter, add, dev, .+, parent, .+, protocol, ip, prio, 1, u32, match, ip, src, .+, police, rate, .+, burst, .+, mtu, 64kb, drop, flowid, :1
# For ip monitor
kill_ip_monitor: KillFilter, root, ip, -9
@ -51,9 +41,6 @@ kill_keepalived: KillFilter, root, keepalived, -HUP, -15, -9
# keepalived kill script filter
kill_keepalived_script: CommandFilter, keepalived-kill, root
# l3 agent to delete floatingip's conntrack state
conntrack: CommandFilter, conntrack, root
# keepalived state change monitor
keepalived_state_change: CommandFilter, neutron-keepalived-state-change, root
# The following filters are used to kill the keepalived state change monitor.

View File

@ -8,13 +8,6 @@
[Filters]
# linuxbridge-agent
# unclear whether both variants are necessary, but I'm transliterating
# from the old mechanism
brctl: CommandFilter, brctl, root
bridge: CommandFilter, bridge, root
sysctl: CommandFilter, sysctl, root
# ip_lib
ip: IpFilter, ip, root
ip_exec: IpNetnsExecFilter, ip, root

View File

@ -17,6 +17,3 @@ ovsdb-client: CommandFilter, ovsdb-client, root
# ip_lib
ip: IpFilter, ip, root
ip_exec: IpNetnsExecFilter, ip, root
# needed for FDB extension
bridge: CommandFilter, bridge, root

View File

@ -163,7 +163,7 @@ class IpConntrackManager(object):
rule, remote_ip)
for cmd in conntrack_cmds:
try:
self.execute(list(cmd), run_as_root=True,
self.execute(list(cmd), run_as_root=True, privsep_exec=True,
check_exit_code=True,
extra_ok_codes=[1])
except RuntimeError:

View File

@ -135,7 +135,7 @@ class SubProcessBase(object):
opt_list = ['-%s' % o for o in options]
ip_cmd = add_namespace_to_cmd(['ip'], namespace)
cmd = ip_cmd + opt_list + [command] + list(args)
return utils.execute(cmd, run_as_root=run_as_root,
return utils.execute(cmd, run_as_root=run_as_root, privsep_exec=True,
log_fail_as_error=self.log_fail_as_error)
def set_log_fail_as_error(self, fail_with_error):

View File

@ -148,7 +148,7 @@ class IpsetManager(object):
cmd_ns.extend(['ip', 'netns', 'exec', self.namespace])
cmd_ns.extend(cmd)
self.execute(cmd_ns, run_as_root=True, process_input=input,
check_exit_code=fail_on_errors)
check_exit_code=fail_on_errors, privsep_exec=True)
def _get_new_set_ips(self, set_name, expected_ips):
new_member_ips = (set(expected_ips) -

View File

@ -102,7 +102,8 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
log_warning = False
if not a_utils.execute(
['sysctl', '-N', 'net.bridge'], run_as_root=True,
log_fail_as_error=False, check_exit_code=False):
log_fail_as_error=False, check_exit_code=False,
privsep_exec=True):
LOG.warning('Kernel module br_netfilter is not loaded.')
log_warning = True
if not log_warning:
@ -110,7 +111,8 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
key = 'net.bridge.bridge-nf-call-%stables' % proto
enabled = a_utils.execute(
['sysctl', '-b', key], run_as_root=True,
log_fail_as_error=False, check_exit_code=False)
log_fail_as_error=False, check_exit_code=False,
privsep_exec=True)
if enabled == '1':
status = 'enabled'
log_method = LOG.debug

View File

@ -195,7 +195,8 @@ def _get_source_ports_from_ss_output(output):
def get_unused_port(used, start=1024, end=None):
if end is None:
port_range = utils.execute(
['sysctl', '-n', 'net.ipv4.ip_local_port_range'], run_as_root=True)
['sysctl', '-n', 'net.ipv4.ip_local_port_range'], run_as_root=True,
privsep_exec=True)
end = int(port_range.split()[0]) - 1
candidates = set(range(start, end + 1))
@ -235,11 +236,12 @@ def get_free_namespace_port(protocol, namespace=None, start=1024, end=None):
def set_local_port_range(start, end):
utils.execute(
['sysctl', '-w', 'net.ipv4.ip_local_port_range=%d %d' % (start, end)],
run_as_root=True)
utils.execute(['sysctl', '-p'], run_as_root=True)
run_as_root=True, privsep_exec=True)
utils.execute(['sysctl', '-p'], run_as_root=True, privsep_exec=True)
# verify
port_range = utils.execute(
['sysctl', '-n', 'net.ipv4.ip_local_port_range'], run_as_root=True)
['sysctl', '-n', 'net.ipv4.ip_local_port_range'], run_as_root=True,
privsep_exec=True)
assert int(port_range.split()[0]) == start
assert int(port_range.split()[1]) == end

View File

@ -45,10 +45,9 @@ class NetlinkLibTestCase(functional_base.BaseSudoTestCase):
for cmd in conntrack_cmds:
try:
linux_utils.execute(cmd,
run_as_root=True,
check_exit_code=True,
extra_ok_codes=[1])
linux_utils.execute(
cmd, run_as_root=True, check_exit_code=True,
privsep_exec=True, extra_ok_codes=[1])
except RuntimeError:
raise Exception('Error while creating entry')
@ -66,10 +65,9 @@ class NetlinkLibTestCase(functional_base.BaseSudoTestCase):
while start <= end:
cmd = ['conntrack', '-L', '-w', start]
try:
current_entries = linux_utils.execute(cmd,
run_as_root=True,
check_exit_code=True,
extra_ok_codes=[1])
current_entries = linux_utils.execute(
cmd, run_as_root=True, check_exit_code=True,
privsep_exec=True, extra_ok_codes=[1])
except RuntimeError:
raise Exception('Error while listing entries')
if not current_entries:

View File

@ -621,7 +621,7 @@ class FirewallTestCase(BaseFirewallTestCase):
# destination net unreachable
self.tester._peer.execute([
'sysctl', '-w', 'net.ipv4.conf.%s.forwarding=1' %
self.tester._peer.port.name])
self.tester._peer.port.name], privsep_exec=True)
self.tester.set_vm_default_gateway(self.tester.peer_ip_address)
vm_sg_rules = [{'ethertype': 'IPv4', 'direction': 'egress',
'protocol': 'icmp'}]

View File

@ -112,6 +112,7 @@ class TestSubProcessBase(base.BaseTestCase):
self.execute.assert_called_once_with(['ip', '-o', 'link', 'list'],
run_as_root=True,
privsep_exec=True,
log_fail_as_error=True)
def test_execute_wrapper_int_options(self):
@ -120,6 +121,7 @@ class TestSubProcessBase(base.BaseTestCase):
self.execute.assert_called_once_with(['ip', '-4', 'link', 'list'],
run_as_root=False,
privsep_exec=True,
log_fail_as_error=True)
def test_execute_wrapper_no_options(self):
@ -128,6 +130,7 @@ class TestSubProcessBase(base.BaseTestCase):
self.execute.assert_called_once_with(['ip', 'link', 'list'],
run_as_root=False,
privsep_exec=True,
log_fail_as_error=True)
def test_run_no_namespace(self):
@ -135,6 +138,7 @@ class TestSubProcessBase(base.BaseTestCase):
base._run([], 'link', ('list',))
self.execute.assert_called_once_with(['ip', 'link', 'list'],
run_as_root=False,
privsep_exec=True,
log_fail_as_error=True)
def test_run_namespace(self):
@ -143,6 +147,7 @@ class TestSubProcessBase(base.BaseTestCase):
self.execute.assert_called_once_with(['ip', 'netns', 'exec', 'ns',
'ip', 'link', 'list'],
run_as_root=True,
privsep_exec=True,
log_fail_as_error=True)
def test_as_root_namespace(self):
@ -151,6 +156,7 @@ class TestSubProcessBase(base.BaseTestCase):
self.execute.assert_called_once_with(['ip', 'netns', 'exec', 'ns',
'ip', 'link', 'list'],
run_as_root=True,
privsep_exec=True,
log_fail_as_error=True)

View File

@ -70,49 +70,42 @@ class BaseIpsetManagerTest(base.BaseTestCase):
input = '\n'.join(temp_input)
self.expected_calls.extend([
mock.call(['ipset', 'restore', '-exist'],
process_input=input,
run_as_root=True,
check_exit_code=True),
process_input=input, run_as_root=True,
check_exit_code=True, privsep_exec=True),
mock.call(['ipset', 'swap', TEST_SET_NAME_NEW, TEST_SET_NAME],
process_input=None,
run_as_root=True,
check_exit_code=True),
process_input=None, run_as_root=True,
check_exit_code=True, privsep_exec=True),
mock.call(['ipset', 'destroy', TEST_SET_NAME_NEW],
process_input=None,
run_as_root=True,
check_exit_code=False)])
process_input=None, run_as_root=True,
check_exit_code=False, privsep_exec=True)])
def expect_add(self, addresses):
self.expected_calls.extend(
mock.call(['ipset', 'add', '-exist', TEST_SET_NAME, ip],
process_input=None,
run_as_root=True,
check_exit_code=True)
process_input=None, run_as_root=True,
check_exit_code=True, privsep_exec=True)
for ip in self.ipset._sanitize_addresses(addresses))
def expect_del(self, addresses):
self.expected_calls.extend(
mock.call(['ipset', 'del', TEST_SET_NAME, ip],
process_input=None,
run_as_root=True,
check_exit_code=False)
process_input=None, run_as_root=True,
check_exit_code=False, privsep_exec=True)
for ip in self.ipset._sanitize_addresses(addresses))
def expect_create(self):
self.expected_calls.append(
mock.call(['ipset', 'create', '-exist', TEST_SET_NAME,
'hash:net', 'family', 'inet'],
process_input=None,
run_as_root=True,
check_exit_code=True))
process_input=None, run_as_root=True,
check_exit_code=True, privsep_exec=True))
def expect_destroy(self):
self.expected_calls.append(
mock.call(['ipset', 'destroy', TEST_SET_NAME],
process_input=None,
run_as_root=True,
check_exit_code=False))
process_input=None, run_as_root=True,
check_exit_code=False, privsep_exec=True))
def add_first_ip(self):
self.expect_set([FAKE_IPS[0]])

View File

@ -1418,8 +1418,8 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase):
cmd.extend(['-w', ct_zone])
calls = [
mock.call(cmd, run_as_root=True, check_exit_code=True,
extra_ok_codes=[1])]
mock.call(cmd, run_as_root=True, privsep_exec=True,
check_exit_code=True, extra_ok_codes=[1])]
self.utils_exec.assert_has_calls(calls)
def test_remove_conntrack_entries_for_delete_rule_ipv4(self):
@ -1472,8 +1472,8 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase):
if ct_zone:
cmd.extend(['-w', ct_zone])
expected_calls.append(
mock.call(cmd, run_as_root=True, check_exit_code=True,
extra_ok_codes=[1]))
mock.call(cmd, run_as_root=True, privsep_exec=True,
check_exit_code=True, extra_ok_codes=[1]))
return expected_calls
def _test_remove_conntrack_entries_for_port_sec_group_change(self,
@ -1578,7 +1578,8 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase):
conntrack_cmd.extend([remote_ip_direction, ips[ethertype][1]])
calls.append(mock.call(conntrack_cmd,
run_as_root=True, check_exit_code=True,
run_as_root=True, privsep_exec=True,
check_exit_code=True,
extra_ok_codes=[1]))
self.utils_exec.assert_has_calls(calls)