Dan Walsh's Blog

Got SELinux?

Previous Entry Share Next Entry
10 things you probably did not know about SELinux.. #8 How to remove a port from a port type?
How do you remove a network port from a network port type?

First a little explanation.  Linux contains 65536 network ports for both UDP and TCP.
SELinux uses types to group network ports together.  If you want to see a listing of the port types on the system you can execute:

semanage  port -l
SELinux Port Type              Proto    Port Number

afs_bos_port_t                 udp      7007
afs_client_port_t              udp      7001
afs_fs_port_t                  tcp      2040
afs_fs_port_t                  udp      7000, 7005

Then we write rules in SELinux like

allow httpd_t http_port_t : tcp_socket name_bind ;

This rules says the apache process can execute the bind command using any port that is currently labeled http_port_t.

# semanage  port -l | grep http_port_t
http_port_t                    tcp      80, 443, 488, 8008, 8009, 8443

Now a fairly common question that gets asked is, can I remove these ports.   IE I do not want to allow apache to bind to port 8008.

How would I do this?

The simplest thing to do is to redefine port 8008 as a different port type that httpd can not bind to. 

The default port type for all unassigned ports  > 1024 is unreserved_port_t or ephemeral_port_t (Fedora 16)

# semanage  port -l | grep ^unreserved_port_t
unreserved_port_t              tcp      1024-32767, 61001-65535
unreserved_port_t              udp      1024-32767, 61001-65535
# semanage  port -l | grep ^ephemeral_port_t
ephemeral_port_t               tcp      32768-61000
ephemeral_port_t               udp      32768-61000

Note SELinux will use a more specific port type if the port has been defined, for example when the kernel sees tcp port 8008, it will use http_port_t rather then unreserved_port_t. 

But the admin can override this by adding his own port definition.

# semanage port -m -t unreserved_port_t -p tcp 8008

To prove this worked, I tested using apache.

# sed -i 's/Listen 80/Listen 8008/g' /etc/httpd/conf/httpd.conf
# semanage  port -m -t unreserved_port_t -p tcp 8008
# service httpd restart
Restarting httpd (via systemctl):  Job failed. See system logs and 'systemctl status' for details.  [FAILED]
# semanage port -d -p tcp 8008
# service httpd restart
Restarting httpd (via systemctl):                          [  OK  ]


Be careful doing this, because you have just changed the definition of http_port_t for ALL domains, not just the httpd_t domain.   Meaning if you were running firefox with a sandbox_web_t sandbox on the same machine, the firefox would no longer be able to connect to port 8008, because sandbox_web_t is only allowed to connect to http_port_t and 8008 is no longer defined as 8008.

Well the problem with that is all the kernel is returning is EPERM


2011-10-24 05:31 pm (UTC)

Which lots of programs no how to handle. Introducing a new ERRNO would be problematic and would probably caused lots of apps to blow up. Also there are potentially other LSM apps and other ways to get EPERM then just DAC. So I think it is a non starter. We are reporting errors in /var/log/messages if you have setroubleshoot-server installed, and all SELinux error messages show up in /var/log/audit/audit.log

No HTML allowed in subject


(will be screened)

You are viewing danwalsh