Bug 1382372 - Selinux is blocking ovs-vswitchd during functional tests
Summary: Selinux is blocking ovs-vswitchd during functional tests
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Red Hat OpenStack
Classification: Red Hat
Component: openstack-neutron
Version: 10.0 (Newton)
Hardware: Unspecified
OS: Unspecified
medium
urgent
Target Milestone: ---
: 10.0 (Newton)
Assignee: Terry Wilson
QA Contact: Toni Freger
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2016-10-06 13:36 UTC by Arie Bregman
Modified: 2017-08-15 21:49 UTC (History)
14 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2017-08-15 21:49:15 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)

Description Arie Bregman 2016-10-06 13:36:53 UTC
Description of problem:
Selinux denies openvswitch operations

Version-Release number of selected component (if applicable):
selinux-policy-3.13.1-102.el7.noarch
libselinux-2.5-6.el7.x86_64
selinux-policy-targeted-3.13.1-102.el7.noarch
libselinux-devel-2.5-6.el7.x86_64
openstack-selinux-0.7.9-1.el7ost.noarch
libselinux-utils-2.5-6.el7.x86_64
libselinux-python-2.5-6.el7.x86_64

Steps to Reproduce:
1. Install RHOSP 10 with openvswitch

Actual results:
ovs|11280|stream_tcp|ERR|tcp:127.0.0.1:3310: connect: Permission denied

Expected results:
Connection established

Additional info:
Attached logs

Comment 2 Ihar Hrachyshka 2016-10-06 15:15:16 UTC
Do we know why the port is needed?

Comment 3 Jakub Libosvar 2016-10-06 17:06:27 UTC
We don't know why openvswitch attempts to connect to a port 3310. That port is weird. I suggest to wait with allowing this port in our policy before proceeding, we could create a hole instead of fixing bug.

Comment 5 Ihar Hrachyshka 2016-10-07 10:10:34 UTC
Ryan, what's the rationale to allow that port? Do we know why it shows up in OSP?

Comment 6 Assaf Muller 2016-10-07 13:33:19 UTC
@Terry - Even though SELinux was already modified to open the port, I think it's our responsibility to investigate why we need the port opened. Let's make sure we understand why.

Comment 7 Ryan Hallisey 2016-10-07 15:01:35 UTC
type=AVC msg=audit(1475756683.078:8897): avc:  denied  { name_connect } for pid=26463 comm="ovs-vswitchd" dest=3310 scontext=system_u:system_r:openvswitch_t:s0 tcontext=system_u:object_r:clamd_port_t:s0 tclass=tcp_socket

Clamd is an anti virus daemon that listens for incoming connections and scans desired files/dirs for threats.

This rule allows for ovs to connect to clamd_port_t so clamd can receive requests.

Comment 8 Jakub Libosvar 2016-10-07 15:08:58 UTC
(In reply to Ryan Hallisey from comment #7)
> type=AVC msg=audit(1475756683.078:8897): avc:  denied  { name_connect } for
> pid=26463 comm="ovs-vswitchd" dest=3310
> scontext=system_u:system_r:openvswitch_t:s0
> tcontext=system_u:object_r:clamd_port_t:s0 tclass=tcp_socket
> 
> Clamd is an anti virus daemon that listens for incoming connections and
> scans desired files/dirs for threats.
> 
> This rule allows for ovs to connect to clamd_port_t so clamd can receive
> requests.

Yeah, it doesn't make sense to me that ovs would try to connect to anti virus. openvswitch typically connects to controller. We need to investigate first whether this is a test only issue, I doubt this happens in real deployments.

Comment 12 Terry Wilson 2016-10-08 18:17:29 UTC
Ryan: That sounds very odd to me. Why would the ovs-vswitchd process need to communicate with clam-av? I have not heard anything that would convince me that this should be in the default policy. Who is configuring ovs-vswitchd to make outgoing connections to clam-av? The only way I can think of is having it connect to it as a controller, which seems crazy unless clam-av has a built-in openflow controller that I'm not aware of.

Comment 13 Ryan Hallisey 2016-10-08 23:06:39 UTC
Ok if this is odd behaviour then we need to get to the root of why ovs is trying to connect to clam-av. Could this be a misconfiguration?

Comment 14 Arie Bregman 2016-10-08 23:11:11 UTC
I've been running the job several times and here are the results (each line is from a different build):


ovs-vswitchd: ovs|11280|stream_tcp|ERR|tcp:127.0.0.1:3310: connect: Permission denied

ovs-vswitchd: ovs|10654|stream_tcp|ERR|tcp:127.0.0.1:6543: connect: Permission denied

ovs-vswitchd: ovs|10977|stream_tcp|ERR|tcp:127.0.0.1:6792: connect: Permission denied

ovs-vswitchd: ovs|12065|stream_tcp|ERR|tcp:127.0.0.1:9280: connect: Permission denied

ovs-vswitchd: ovs|14714|stream_tcp|ERR|tcp:127.0.0.1:10081: connect: Permission denied

ovs-vswitchd: ovs|11698|stream_tcp|ERR|tcp:127.0.0.1:5004: connect: Permission denied

Comment 15 Terry Wilson 2016-10-10 20:11:26 UTC
OVSAgentTestBase sets a random of_listen_port in the config, and some tests call set_controllers() using this port. This causes ovs-vswitchd to attempt to make an outbound connection on this port, and thus SELinux being very cross with it.

Since this is a testing only issue, we should be able to remove the blocker flag. We absolutely need to remove any ports allowed in openstack-selinux from this change.

As far as solutions go, we could probably modify the tests to tell SELinux to allow the random port returned (or just allow ovs-vswitchd to connect anywhere in the test environment only, though I prefer a more targeted approach).

The permission error leads to a loop with the following log messages:

2016-10-10 16:07:03.793 27938 DEBUG ryu.base.app_manager [-] EVENT OVSNeutronAgentRyuApp->ofctl_service GetDatapathRequest send_event /usr/lib/python2.7/site-packages/ryu/base/app_manager.py:314
2016-10-10 16:07:03.794 27938 DEBUG OfctlService [-] dpid 165586572766272 -> datapath None _handle_get_datapath /usr/lib/python2.7/site-packages/ryu/app/ofctl/service.py:106

A timeout of some kind should probably be added upstream to prevent infinite looping on error.

Comment 16 Assaf Muller 2016-10-10 20:14:11 UTC
I took the liberty to remove the blocker flag in light of Terry's comment 15: "Since this is a testing only issue..."

Comment 18 Ryan Hallisey 2016-10-11 19:37:39 UTC
sounds good. Thanks everyone :)

Comment 19 Nir Yechiel 2016-10-13 06:24:13 UTC
Thanks Terry and Assaf for the investigation!

Comment 20 Assaf Muller 2016-10-14 17:06:24 UTC
We have a workaround, moving to 10.z regardless.

Comment 21 Terry Wilson 2016-10-14 17:45:10 UTC
Ryan: I have some questions about the os-ovs policy. It looks like from another bug, it was already added that OVS should be able to connect outbound to any unreserved_port_t

[terry@centos7 yum.repos.d]$ sudo sepolicy network -t unreserved_port_t (https://github.com/redhat-openstack/openstack-selinux/blob/37338757f3f929d2cce9e60d6ac464297bc7c5f2/os-ovs.te#L32)

With unreserved_port_t being:
unreserved_port_t: tcp: 1024-32767,61001-65535
unreserved_port_t: udp: 1024-32767,61001-65535

I have several questions about this:
1) Is it good SELinux policy to allow, by default, outbound connections anywhere just because it is technically possible to configure OVS that way? I thought the idea was generally to deny everything, then specifically allow only exactly what was needed?

2) If the intention really is "allow ovs to connect anywhere", unreserved_port_t leaves out reserved_port_t (1-511), hi_reserved_port_t(511-1023), and ephemeral_port_t(32768-61000). Should those be added?

3) Despite the listed port (3310) being in the range unreserved_port_t covers, it is still denied since clamd_port_t is defined. I've tested this with some other defined ports, and it appears that any defined port will cause the SELinux failure, so the above doesn't seem to actually accomplish what it set out to do. Is there actually a way to match all ports, defined or not, and allow them?

Comment 22 Ryan Hallisey 2016-10-19 14:12:26 UTC
The type unreserved_port_t is given to ports that are not reserved for a particular service. So this covers all the ports that aren't specified in `sudo semanage port -l` within 1024-32767 and 61001-65535. Since OVS can connect to any port, we'll allow it to connect to those unreserved ports.

The intention is to allow things that are requested and make sense. Since there hasn't been a request for anything with hi_reserved_port_t or ephermeral_port_t yet, I'll wait on adding that policy.

This case had the port labeled (clamd_port_t).  If it is labeled and the connection to that port makes sense, then we can allow it.

Comment 23 Terry Wilson 2016-10-19 16:59:29 UTC
> The type unreserved_port_t is given to ports that are not reserved for a particular service. So this covers all the ports that aren't specified in `sudo semanage port -l` within 1024-32767 and 61001-65535. Since OVS can connect to any port, we'll allow it to connect to those unreserved ports.

I think both of these bugs are about binding to an address. I mistakenly mentioned outbound connections earlier. I'm not an selinux expert, so I'm just trying to understand how things should be done and still have questions:

1) For the previous NSX bug, it seems like we would preferably want a very specific port allowed. Port 6640 is the standard IANA assigned port for OVSDB communication--it seems like it makes sense to specifically add it instead of unreserved_port_t. Much like how httpd can be configured to bind to any address but we have rules limiting tcp_socket name_bind http_port_t.

2) For this bug, the port used is completely random since it is used for testing purposes and multiple tests can run simultaneously and need to run from different ports. Just allowing clamd_port_t isn't beneficial, so the new rule needs to be removed.

3) If we are going to try to allow the functional tests to run with selinux in enforcing mode, then **for test environments only** we have to come up with a way to either: a) limit the "random" ports to ports that match unreserved_port_t/aren't defined elsewhere in selinux (if we keep unreserved_port_t), b) allow ovs-vswitchd to bind to *any* port, not just unreserved_port_t, or c) somehow specifically enable each random port before using it during the test (seems like it would be slow and we would still conflict with existing defined ports). I, not being an selinux expert, don't actually know how to do any of those things. Any ideas?

Comment 24 Ryan Hallisey 2016-10-19 19:12:45 UTC
Sure!  Questions welcome :)

If you need a port labeled that is currently set as unreserved_port_t then that would go into base selinux policy.  We shouldn't just carry it for openstack-selinux.  Can you file a bug with selinux for that?

Since this is testing and the port is random then it doesn't make sense to add the rule. I agree. I removed it a few builds ago.

This rule will allow ovs to connect to any port.
  corenet_tcp_connect_all_ports(openvswitch_t)

To build policy for testing:

[rhallisey@localhost ~]$ cat os-testing.te
policy_module(os-testing,0.1)

gen_require(`
        type openvswitch_t;
')

# For testing OVS only
corenet_tcp_connect_all_ports(openvswitch_t)
[rhallisey@localhost ~]$ make -f /usr/share/selinux/devel/Makefile
[rhallisey@localhost ~]$ sudo semodule -i os-testing.pp


Note You need to log in before you can comment on or make changes to this bug.