Created attachment 1314403 [details] Example script Description of problem: PyDNS randomly binds to TCP or UDP source ports from the range 1024-65535 as a defense against cache poisoning. Some ports in this range are defined as SELinux ports. Someone who is writing an SELinux policy to confine a python script that uses PyDNS will either have to: * Accept that ~1% of TCP queries will fail * Make the SELinux policy allow more than needed (i.e. corenet_tcp_bind_all_ports) Version-Release number of selected component (if applicable): 2.3.6-2.el7 How reproducible: Basic SELinux policy files and python script to demonstrate the issue are attached. Steps to Reproduce: 1. Build and install SELinux policy Place pydnstest.te and pydnstest.fc in ~/pydnstest/ $ cd ~/pydnstest $ make -f /usr/share/selinux/devel/Makefile # semodule -i ~/pydnstest/pydnstest.pp # semanage dontaudit off 2. Install script Place pydnstest.py in /usr/local/bin/ # restorecon /usr/local/bin/pydnstest.py 3. Run script $ runcon system_u:system_r:pydnstest_t:s0 /usr/local/bin/pydnstest.py Actual results: SELinux denials occur during approx. 1% of lookups. $ runcon system_u:system_r:pydnstest_t:s0 /usr/local/bin/pydnstest.py Lookup 107 failed: SocketError(error(13, 'Permission denied'),) Lookup 176 failed: SocketError(error(13, 'Permission denied'),) # ausearch -ts today 20:21 -i -m avc -su pydnstest_t | audit2allow #============= pydnstest_t ============== allow pydnstest_t i18n_input_port_t:tcp_socket name_bind; allow pydnstest_t munin_port_t:tcp_socket name_bind; In this case, ports 4949 and 9010 were among the 200 randomly selected source ports. Since they were already defined as SELinux ports (i18n_input_port_t and munin_port_t), it resulted in denials. Expected results: DNS lookups use source ports in the ephemeral range, avoiding conflicts with defined SELinux ports. Additional info: Changing source_port to 0 makes the kernel assign a random-looking port in the ephemeral range. Making this change resulted in no SELinux denials with the attached script/policy: --- /usr/lib/python2.7/site-packages/DNS/Base.py.orig 2017-05-18 16:17:50.000000000 +0000 +++ /usr/lib/python2.7/site-packages/DNS/Base.py 2017-08-16 20:30:05.717033232 +0000 @@ -181,7 +181,7 @@ "Pick random source port to avoid DNS cache poisoning attack." while True: try: - source_port = random.randint(1024,65535) + source_port = 0 self.s.bind(('', source_port)) break except socket.error, msg: This reduces the pool of random source ports from 64512 to 28232. This shouldn't matter for TCP, but will weaken this defense against DNS cache poisoning attacks for UDP queries.
Created attachment 1314404 [details] Example TE policy
Created attachment 1314405 [details] Example file context for policy
This package has changed maintainer in Fedora. Reassigning to the new maintainer of this component.
This package is dead since fedora 31. Please use python3-dns or python3-unbound