type=AVC msg=audit(1553181380.518:2594): avc: denied { name_connect } for pid=31221 comm="testapp" dest=80 scontext=system_u:system_r:testapp_t:s0 tcontext=system_u:object_r:http_port_t:s0 tclass=tcp_socket permissive=1
In this exercise, we will continue the modification of the generic application polocy to allow network traffic to be generated by the test application. There are several rules that will be needed, to handle a variety of AVC denials.
Let’s restart our app, to get an updated list of denials.
sudo systemctl restart testapp
Let’s start with one of the denials that will be present in the audit search results, related to connecting on TCP port 80:
sudo ausearch -m AVC -ts recent | grep 'dest=80'
type=AVC msg=audit(1553181380.518:2594): avc: denied { name_connect } for pid=31221 comm="testapp" dest=80 scontext=system_u:system_r:testapp_t:s0 tcontext=system_u:object_r:http_port_t:s0 tclass=tcp_socket permissive=1
You may receive more than one of these messages, depending on timing.
In the message above, you can see that the system has attempted to connect to a remote host on port 80. This is something that we want to allow. So, let’s search for an interface that would allow this kind of connection. Since networking is controlled by the kernel, we will search in the kernel directory for interface files related to networking:
ls /usr/share/selinux/devel/include/kernel/*.if | grep net
/usr/share/selinux/devel/include/kernel/corenetwork.if
/usr/share/selinux/devel/include/kernel/unlabelednet.if
Since this isn’t an unlabeled network, let’s look in corenetwork.if
. Since this is a name_connect
action, let’s look for connect and http. Using those criteria, we find:
########################################
## <summary>
## Make a TCP connection to the http port.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
interface(`corenet_tcp_connect_http_port',`
gen_require(`
type http_port_t;
')
allow $1 http_port_t:tcp_socket name_connect;
')
So, as before, add an interface to your testapp.te
file, using a line like this:
corenet_tcp_connect_http_port(testapp_t)
And compile your policy, and restart the service:
sudo ./testapp.sh
sudo systemctl restart testapp
…and last, check to see if there is still an AVC denial:
sudo systemctl restart testapp
sudo ausearch -m AVC -ts recent | grep 'dest=80' | wc -l
0
Yes! Another AVC denial fixed.
If you ausearch
still shows AVCs above, you can alternatively limit the query to the testapp’s current PID; this should confirm the policy is in effect:
sudo ausearch -m AVC -ts recent -p $(systemctl show testapp --property=MainPID | cut -d= -f2) | grep 'dest=80' | wc -l
Now, we’re going to move on, temporarily, from interfaces to allow/deny settings, in the testapp.te
file. We have several AVC denials around TCP and UDP socket system calls, that SELinux is blocking.
The AVCs in question are here (there will likely be more, on your host, but they are all in the same sategory):
sudo ausearch -m AVC -ts recent | egrep 'tcp|udp'
type=AVC msg=audit(1553190979.189:2931): avc: denied { create } for pid=2042 comm="testapp" scontext=system_u:system_r:testapp_t:s0 tcontext=system_u:system_r:testapp_t:s0 tclass=tcp_socket permissive=1
type=AVC msg=audit(1553190979.189:2932): avc: denied { connect } for pid=2042 comm="testapp" scontext=system_u:system_r:testapp_t:s0 tcontext=system_u:system_r:testapp_t:s0 tclass=tcp_socket permissive=1
type=AVC msg=audit(1553190979.379:2933): avc: denied { getopt } for pid=2042 comm="testapp" laddr=10.0.2.5 lport=60848 faddr=5.9.243.187 fport=80 scontext=system_u:system_r:testapp_t:s0 tcontext=system_u:system_r:testapp_t:s0 tclass=tcp_socket permissive=1
type=AVC msg=audit(1553190979.379:2934): avc: denied { getattr } for pid=2042 comm="testapp" laddr=10.0.2.5 lport=60848 faddr=5.9.243.187 fport=80 scontext=system_u:system_r:testapp_t:s0 tcontext=system_u:system_r:testapp_t:s0 tclass=tcp_socket permissive=1
type=AVC msg=audit(1553191083.531:2965): avc: denied { create } for pid=2042 comm="testapp" scontext=system_u:system_r:testapp_t:s0 tcontext=system_u:system_r:testapp_t:s0 tclass=udp_socket permissive=1
type=AVC msg=audit(1553191083.531:2966): avc: denied { connect } for pid=2042 comm="testapp" scontext=system_u:system_r:testapp_t:s0 tcontext=system_u:system_r:testapp_t:s0 tclass=udp_socket permissive=1
type=AVC msg=audit(1553191083.548:2967): avc: denied { getattr } for pid=2042 comm="testapp" path="socket:[314409]" dev="sockfs" ino=314409 scontext=system_u:system_r:testapp_t:s0 tcontext=system_u:system_r:testapp_t:s0 tclass=udp_socket permissive=1
audit2why
interpret for youNext, let’s ask the system to convert an AVC to English, for us:
sudo ausearch -m AVC | egrep 'udp' | head -1 | audit2why
type=AVC msg=audit(1553112150.906:909): avc: denied { create } for pid=9772 comm="testapp" scontext=system_u:system_r:testapp_t:s0 tcontext=system_u:system_r:testapp_t:s0 tclass=udp_socket permissive=1
Was caused by:
Missing type enforcement (TE) allow rule.
You can use audit2allow to generate a loadable module to allow this access.
You can see that, in this case, audit2why
wasn’t significantly helpful, other than telling us that we need to add a new allow
statement to our testapp.te
file.
audit2allow
to suggest changesSo, now we’ll take the advice that audit2why
gave us, and let audit2allow
generate some policy allow statements. You always have to be careful with audit2allow
, since it will generate rules for anything that you feed it, and won’t necessarily pick the most optimal solution.
sudo ausearch -m AVC -ts recent | egrep 'tcp|udp' | audit2allow
#============= testapp_t ==============
allow testapp_t self:tcp_socket { connect create getattr getopt setopt };
allow testapp_t self:udp_socket { connect create getattr setopt };
These rules look good, so go ahead and add them to your testapp.te
file.
The file should now look like this:
cat ~/src/policy/testapp.te
policy_module(testapp, 1.0.0)
########################################
#
# Declarations
#
type testapp_t;
type testapp_exec_t;
init_daemon_domain(testapp_t, testapp_exec_t)
permissive testapp_t;
type testapp_var_run_t;
files_pid_file(testapp_var_run_t)
########################################
#
# testapp local policy
#
allow testapp_t self:process { fork };
allow testapp_t self:fifo_file rw_fifo_file_perms;
allow testapp_t self:tcp_socket { connect create getattr getopt };
allow testapp_t self:udp_socket { connect create getattr };
allow testapp_t self:unix_stream_socket create_stream_socket_perms;
manage_dirs_pattern(testapp_t, testapp_var_run_t, testapp_var_run_t)
manage_files_pattern(testapp_t, testapp_var_run_t, testapp_var_run_t)
manage_lnk_files_pattern(testapp_t, testapp_var_run_t, testapp_var_run_t)
files_pid_filetrans(testapp_t, testapp_var_run_t, { dir file lnk_file })
corenet_tcp_connect_http_port(testapp_t)
domain_use_interactive_fds(testapp_t)
files_read_etc_files(testapp_t)
kernel_read_system_state(testapp_t)
logging_send_syslog_msg(testapp_t)
miscfiles_read_localization(testapp_t)
Keeping things in alphabetic order doesn’t make any difference to SELinux, but makes the file easier to read.
Now, let’s recompile the policy, and reload it into memory.
sudo ./testapp.sh
To see if that fixed the problem, let’s restart the application:
sudo systemctl restart testapp
…and see if there are any AVC messages about TCP or UDP:
sudo ausearch -m AVC -ts recent -p $(systemctl show testapp --property=MainPID | cut -d= -f2) | egrep 'tcp|udp' | wc -l
0
Fantastic! More AVC denials stomped.
At this point, we’re down to only a few more AVC denials to handle. Hopefully, you’re getting a handle on how to find appropriate interfaces and allow rules, for SELinux.
Domain | ||
Workshop | ||
Student ID |