summaryrefslogtreecommitdiffstats
path: root/extras/selinux
diff options
context:
space:
mode:
Diffstat (limited to 'extras/selinux')
-rw-r--r--extras/selinux/selinux_doc.md294
-rw-r--r--extras/selinux/vpp-custom.fc22
-rw-r--r--extras/selinux/vpp-custom.if2
-rw-r--r--extras/selinux/vpp-custom.te139
4 files changed, 457 insertions, 0 deletions
diff --git a/extras/selinux/selinux_doc.md b/extras/selinux/selinux_doc.md
new file mode 100644
index 00000000000..e71bd658286
--- /dev/null
+++ b/extras/selinux/selinux_doc.md
@@ -0,0 +1,294 @@
+# SELinux - VPP Custom SELinux Policy {#selinux_doc}
+
+## Overview
+
+Security-enhanced Linux (SELinux) is a security feature in the Linux kernel. At
+a very high level, SELinux implements mandatory access controls (MAC), as
+opposed to discretionary access control (DAC) implemented in standard Linux. MAC
+defines how processes can interact with other system components (Files,
+Directories, Other Processes, Pipes, Sockets, Network Ports). Each system
+component is assigned a label, and then the SELinux Policy defines which labels
+and which actions on each label a process is able to perform. The VPP Custom
+SELinux Policy defines the actions VPP is allowed to perform on which labels.
+
+The VPP Custom SELinux Policy is intended to be installed on RPM based platforms
+(tested on CentOS 7 and RHEL 7). Though SELinux can run on Debian platforms, it
+typically is not and therefore is not currently being built for Debian.
+
+The VPP Custom SELinux Policy does not enable or disable SELinux, only allows
+VPP to run when SELinux is enabled. A fresh install of either Fedora, CentOS or
+RHEL will have SELinux enabled by default. To determine if SELinux is enabled on
+a given system and enable it if needed, run:
+
+```
+ $ getenforce
+ Permissive
+
+ $ sudo setenforce 1
+
+ $ getenforce
+ Enforcing
+```
+
+To make the change persistent, modify the following file to set
+`SELINUX=enforcing`:
+
+```
+ $ sudo vi /etc/selinux/config
+ :
+ # This file controls the state of SELinux on the system.
+ # SELINUX= can take one of these three values:
+ # enforcing - SELinux security policy is enforced.
+ # permissive - SELinux prints warnings instead of enforcing.
+ # disabled - No SELinux policy is loaded.
+ SELINUX=enforcing
+ :
+```
+
+## Installation
+
+To install VPP, see the installation instructions on the VPP Wiki
+(https://wiki.fd.io/view/VPP/Installing_VPP_binaries_from_packages). The VPP
+Custom SELinux Policy is packaged in its own RPM starting in 18.04,
+`vpp-selinux-policy-<VERSION>-<RELEASE>.rpm`. It is packaged and installed along
+with the other VPP RPMs.
+
+### Fresh Install of VPP
+
+If VPP has never been installed on a system, then starting in 18.04, the VPP
+Custom SELinux Policy will be installed with the other RPMs and all the system
+components managed by VPP will be labeled properly.
+
+### Fix SELinux Labels for VPP
+In the case where the VPP Custom Policy is being installed for the first time,
+either because VPP has been upgraded or packages were removed and then
+reinstalled, several directories and files will not not be properly labeled. The
+labels on these files will need to be fixed for VPP to run properly with SELinux
+enabled. After the VPP Custom SELinux Policy is installed, run the following
+commands to fix the labels. If VPP is already running, make sure to restart
+VPP after the labels are fixed. This change is persistent for the life of the
+file. Once the VPP Custom Policy is installed on the system, subsequent files
+created by VPP will be labeled properly. This is only to fix files created by
+VPP prior to the VPP Custom Policy being installed.
+
+```
+ $ sudo restorecon -Rv /etc/vpp/
+ $ sudo restorecon -Rv /usr/lib/vpp_api_test_plugins/
+ $ sudo restorecon -Rv /usr/lib/vpp_plugins/
+ $ sudo restorecon -Rv /usr/share/vpp/
+ $ sudo restorecon -Rv /var/run/vpp/
+
+ $ sudo chcon -t vpp_tmp_t /tmp/vpp_*
+ $ sudo chcon -t vpp_var_run_t /var/run/.vpp_*
+```
+
+**NOTE:** Because the VPP APIs allow custom filenames in certain scenarios, the
+above commands may not handle all files. Inspect your system and correct any
+files that are mislabeled. For example, to verify all VPP files in `/tmp/` are
+labeled properly, run:
+
+```
+ $ sudo ls -alZ /tmp/
+```
+
+Any files not properly labeled with `vpp_tmp_t`, run:
+
+```
+ $ sudo chcon -t vpp_tmp_t /tmp/<filename>
+```
+
+## VPP Files
+
+### Recommended Default File Directories
+
+Documentation in the VPP Wiki (https://wiki.fd.io/view/VPP/) and doxygen
+generated documentation have examples with files located in certain directories.
+Some of the recommend file locations have been moved to satisfy SELinux. Most of
+the documentation has been updated, but links to older documentation still exist
+and there may have been instances that were missed. Use the file locations
+described below to allow SELinux to properly label the given files.
+
+File locations that have changed:
+* VPP Debug CLI Script Files
+* vHost Sockets
+* VPP Log Files
+
+#### VPP Debug CLI Script Files
+
+The VPP Debug CLI, `vppctl`, allows a sequence of CLI commands to be read from a
+file and executed. To avoid from having to grant VPP access to all of `/tmp/` and
+possibly `/home/` sub-directories, it is recommended that any VPP Debug CLI script
+files be placed in a common directory such as `/usr/share/vpp/`.
+
+For example:
+```
+$ cat /usr/share/vpp/scripts/gigup.txt
+set interface state GigabitEthernet0/8/0 up
+set interface state GigabitEthernet0/9/0 up
+```
+
+To execute:
+```
+$ vppctl exec /usr/share/vpp/scripts/gigup.txt
+```
+Or
+```
+$ vppctl
+ _______ _ _ _____ ___
+ __/ __/ _ \ (_)__ | | / / _ \/ _ \
+ _/ _// // / / / _ \ | |/ / ___/ ___/
+ /_/ /____(_)_/\___/ |___/_/ /_/
+
+vpp# exec /usr/share/vpp/scripts/gigup.txt
+vpp# quit
+
+```
+
+If the file is not labeled properly, you will see something similar to:
+```
+$ vppctl exec /home/<user>/dev/vpp/scripts/vppctl/gigup.txt
+exec: failed to open `/home/<user>/dev/vpp/scripts/vppctl/gigup.txt': Permission denied
+
+$ ls -alZ
+drwxrwxr-x. <user> <user> unconfined_u:object_r:user_home_t:s0 .
+drwxrwxr-x. <user> <user> unconfined_u:object_r:user_home_t:s0 ..
+-rw-r--r--. <user> <user> unconfined_u:object_r:user_home_t:s0 gigup.txt
+```
+
+##### Original Documentation
+
+Some of the original documentation showed script files being executed out of
+`/tmp/`. Convenience also may lead to script files being placed in
+`/home/<user>/` subdirectories. If a file is generated by the VPP process in
+`/tmp/`, for example a trace file or pcap file, it will get properly labeled
+with the SELinux label `vpp_tmp_t`. When a file is created, unless a rule is in
+place for the process that created it, the file will inherit the SELinux label
+of the parent directory. So if a user creates a file themselves in `/tmp/`, it
+will get the SELinux label `tmp_t`, which VPP does not have permission to
+access. Therefore it is recommended that script files are located as described
+above.
+
+#### vHost Sockets
+
+vHost sockets are created from VPP perspective in either Server or Client mode.
+In Server mode, the socket name is provided to VPP and VPP creates the socket.
+In Client mode, the socket name is provided to VPP and the hypervisor creates
+the socket. In order for VPP and hypervisor to share the socket resource with
+SELinux enabled, a rule in the VPP Custom SELinux Policy has been added. This
+rules allows processes with the `svirt_t` label (the hypervisor) to access
+sockets with the `vpp_var_run_t` label. As such, when SELinux is enabled,
+vHost sockets should be created in the directory `/var/run/vpp/`.
+
+##### Original Documentation
+
+Some of the original documentation showed vHost sockets being created in the
+directory `/tmp/`. To work properly with SELinux enabled, vHost sockets should be
+created as described above.
+
+#### VPP Log Files
+
+The VPP log file location is set by updating the `/etc/vpp/startup.conf` file:
+
+```
+vi /etc/vpp/startup.conf
+unix {
+:
+ log /var/log/vpp/vpp.log
+:
+}
+
+```
+
+By moving the log file to `/var/log/vpp/`, it will get the label `vpp_log_t`,
+which indicates that the files are log files so they benefit from the
+associated rules (for example granting rights to logrotate so that it can
+manipulate them).
+
+##### Original Documentation
+
+The default `startup.conf` file creates the VPP log file in `/tmp/vpp.log`. By
+leaving the log file in `/tmp/`, it will get the label `vpp_tmp_t`. Moving it
+to `/var/log/vpp/`, it will get the label `vpp_log_t`.
+
+### Use of Non-default File Directories
+
+VPP installs multiple files on the system.
+Some files have fixed directory and file names:
+- /etc/bash_completion.d/vppctl_completion
+- /etc/sysctl.d/80-vpp.conf
+- /usr/lib/systemd/system/vpp.service
+
+Others files have default directory and file names but the default can be
+overwritten:
+- /etc/vpp/startup.conf
+ - Can be changed via the `/usr/lib/systemd/system/vpp.service` file by
+ changing the -c option on the VPP command line:
+
+```
+ExecStart=/usr/bin/vpp -c /etc/vpp/startup.conf
+```
+
+- /run/vpp/cli.sock
+ - Can be changed via the `/etc/vpp/startup.conf` file by changing the
+ cli-listen setting:
+
+```
+unix {
+:
+ cli-listen /run/vpp/cli.sock
+:
+}
+```
+
+
+- /var/log/vpp/vpp.log
+ - Can be changed via the `/etc/vpp/startup.conf` file by changing the log
+ setting:
+
+```
+unix {
+ :
+ log /var/log/vpp/vpp.log
+ :
+}
+
+```
+
+If the directory of any VPP installed files is changed from the default, ensure
+that the proper SELiunx label is applied. The SELinux label can be determined by
+passing the -Z option to many common Linux commands:
+
+```
+ls -alZ /run/vpp/
+drwxr-xr-x. root vpp system_u:object_r:vpp_var_run_t:s0 .
+drwxr-xr-x. root root system_u:object_r:var_run_t:s0 ..
+srwxrwxr-x. root vpp system_u:object_r:vpp_var_run_t:s0 cli.sock
+```
+
+### VPP SELinux Types ###
+
+The following SELinux types are created by the VPP Custom SELinux Policy:
+- `vpp_t` - Applied to:
+ - VPP process and spawned threads.
+
+- `vpp_config_rw_t` - Applied to:
+ - `/etc/vpp/*`
+
+- `vpp_tmp_t` - Applied to:
+ - `/tmp/*`
+
+- `vpp_exec_t` - Applied to:
+ - `/usr/bin/*`
+
+- `vpp_lib_t` - Applied to:
+ - `/usr/lib/vpp_api_test_plugins/*`
+ - `/usr/lib/vpp_plugins/*`
+
+- `vpp_unit_file_t` - Applied to:
+ - `/usr/lib/systemd/system/vpp.*`
+
+- `vpp_log_t` - Applied to:
+ - `/var/log/vpp/*`
+
+- `vpp_var_run_t` - Applied to:
+ - `/var/run/vpp/*`
diff --git a/extras/selinux/vpp-custom.fc b/extras/selinux/vpp-custom.fc
new file mode 100644
index 00000000000..5b9d277ebea
--- /dev/null
+++ b/extras/selinux/vpp-custom.fc
@@ -0,0 +1,22 @@
+/etc/vpp(/.*)? gen_context(system_u:object_r:vpp_config_rw_t,s0)
+
+/usr/bin/elftool -- gen_context(system_u:object_r:vpp_exec_t,s0)
+/usr/bin/jvpp_gen.py -- gen_context(system_u:object_r:vpp_exec_t,s0)
+/usr/bin/svmdbtool -- gen_context(system_u:object_r:vpp_exec_t,s0)
+/usr/bin/svmtool -- gen_context(system_u:object_r:vpp_exec_t,s0)
+/usr/bin/vpp -- gen_context(system_u:object_r:vpp_exec_t,s0)
+/usr/bin/vppapigen -- gen_context(system_u:object_r:vpp_exec_t,s0)
+/usr/bin/vpp_api_test -- gen_context(system_u:object_r:vpp_exec_t,s0)
+/usr/bin/vppctl -- gen_context(system_u:object_r:vpp_exec_t,s0)
+/usr/bin/vpp_get_metrics -- gen_context(system_u:object_r:vpp_exec_t,s0)
+/usr/bin/vpp_json_test -- gen_context(system_u:object_r:vpp_exec_t,s0)
+/usr/bin/vpp_restart -- gen_context(system_u:object_r:vpp_exec_t,s0)
+
+/usr/lib/systemd/system/vpp.* -- gen_context(system_u:object_r:vpp_unit_file_t,s0)
+
+/usr/lib/vpp_plugins(/.*)? gen_context(system_u:object_r:vpp_lib_t,s0)
+/usr/lib/vpp_api_test_plugins(/.*)? gen_context(system_u:object_r:vpp_lib_t,s0)
+
+/var/log/vpp(/.*)? gen_context(system_u:object_r:vpp_log_t,s0)
+
+/var/run/vpp(/.*)? gen_context(system_u:object_r:vpp_var_run_t,s0)
diff --git a/extras/selinux/vpp-custom.if b/extras/selinux/vpp-custom.if
new file mode 100644
index 00000000000..573da143cbb
--- /dev/null
+++ b/extras/selinux/vpp-custom.if
@@ -0,0 +1,2 @@
+##
+ VPP service. \ No newline at end of file
diff --git a/extras/selinux/vpp-custom.te b/extras/selinux/vpp-custom.te
new file mode 100644
index 00000000000..e0a1f64d018
--- /dev/null
+++ b/extras/selinux/vpp-custom.te
@@ -0,0 +1,139 @@
+policy_module(vpp-custom,1.0)
+
+########################################
+#
+# Declarations
+#
+
+gen_require(`
+ type hugetlbfs_t;
+ type svirt_t;
+ type svirt_image_t;
+ type systemd_sysctl_t;
+ class capability sys_admin;
+')
+
+type vpp_t;
+type vpp_exec_t;
+init_daemon_domain(vpp_t, vpp_exec_t)
+
+type vpp_config_rw_t;
+files_config_file(vpp_config_rw_t)
+
+type vpp_lib_t; # if there is vpp_var_lib_t, we don't need vpp_lib_t
+files_type(vpp_lib_t)
+
+type vpp_log_t;
+logging_log_file(vpp_log_t)
+
+type vpp_var_run_t;
+files_type(vpp_var_run_t)
+
+type vpp_unit_file_t;
+systemd_unit_file(vpp_unit_file_t)
+
+type vpp_tmpfs_t;
+files_tmpfs_file(vpp_tmpfs_t)
+
+type vpp_tmp_t;
+files_tmp_file(vpp_tmp_t)
+
+########################################
+#
+# vpp local policy
+#
+
+allow vpp_t self:capability { dac_override ipc_lock setgid sys_rawio net_raw sys_admin }; # too benefolent
+dontaudit vpp_t self:capability2 block_suspend;
+allow vpp_t self:process { execmem execstack setsched signal }; # too benefolent
+allow vpp_t self:packet_socket { bind create setopt ioctl };
+allow vpp_t self:tun_socket { create relabelto relabelfrom };
+allow vpp_t self:udp_socket { create ioctl };
+allow vpp_t self:unix_dgram_socket { connect create ioctl };
+allow vpp_t self:unix_stream_socket { create_stream_socket_perms connectto };
+
+manage_dirs_pattern(vpp_t, vpp_lib_t, vpp_lib_t)
+manage_files_pattern(vpp_t, vpp_lib_t, vpp_lib_t)
+allow vpp_t vpp_lib_t:file execute;
+files_var_lib_filetrans(vpp_t, vpp_lib_t, {file dir})
+
+manage_dirs_pattern(vpp_t, vpp_log_t, vpp_log_t)
+manage_files_pattern(vpp_t, vpp_log_t, vpp_log_t)
+logging_log_filetrans(vpp_t, vpp_log_t, {file dir})
+
+manage_dirs_pattern(vpp_t, vpp_var_run_t, vpp_var_run_t)
+manage_files_pattern(vpp_t, vpp_var_run_t, vpp_var_run_t)
+manage_sock_files_pattern(vpp_t, vpp_var_run_t, vpp_var_run_t)
+allow vpp_t vpp_var_run_t:dir mounton;
+files_pid_filetrans(vpp_t, vpp_var_run_t, { dir sock_file file })
+
+manage_dirs_pattern(vpp_t, vpp_tmp_t, vpp_tmp_t)
+manage_files_pattern(vpp_t, vpp_tmp_t, vpp_tmp_t)
+manage_sock_files_pattern(vpp_t, vpp_tmp_t, vpp_tmp_t)
+allow vpp_t vpp_tmp_t:dir mounton;
+files_tmp_filetrans(vpp_t, vpp_tmp_t, { dir sock_file file })
+
+manage_dirs_pattern(vpp_t, vpp_tmpfs_t, vpp_tmpfs_t)
+manage_files_pattern(vpp_t, vpp_tmpfs_t, vpp_tmpfs_t)
+fs_tmpfs_filetrans(vpp_t, vpp_tmpfs_t, { dir file })
+
+read_files_pattern(vpp_t, vpp_config_rw_t, vpp_config_rw_t)
+
+kernel_read_system_state(vpp_t)
+kernel_read_network_state(vpp_t)
+kernel_dgram_send(vpp_t)
+kernel_request_load_module(vpp_t)
+
+auth_read_passwd(vpp_t)
+
+corenet_rw_tun_tap_dev(vpp_t)
+
+dev_rw_userio_dev(vpp_t)
+dev_rw_sysfs(vpp_t)
+dev_read_cpuid(vpp_t)
+dev_rw_vfio_dev(vpp_t)
+
+domain_obj_id_change_exemption(vpp_t)
+
+fs_manage_hugetlbfs_dirs(vpp_t)
+fs_manage_hugetlbfs_files(vpp_t)
+allow vpp_t hugetlbfs_t:filesystem { getattr mount unmount };
+fs_getattr_tmpfs(vpp_t)
+
+logging_send_syslog_msg(vpp_t)
+
+miscfiles_read_generic_certs(vpp_t)
+
+userdom_list_user_home_content(vpp_t)
+
+optional_policy(`
+ virt_stream_connect_svirt(vpp_t)
+')
+
+optional_policy(`
+ unconfined_attach_tun_iface(vpp_t)
+')
+
+
+########################################
+#
+# svirt local policy for vpp
+#
+
+allow svirt_t vpp_t:unix_stream_socket connectto;
+
+manage_dirs_pattern(svirt_t, vpp_var_run_t, vpp_var_run_t)
+manage_files_pattern(svirt_t, vpp_var_run_t, vpp_var_run_t)
+manage_sock_files_pattern(svirt_t, vpp_var_run_t, vpp_var_run_t)
+
+allow vpp_t svirt_image_t:file { read write };
+
+
+########################################
+#
+# systemd_sysctl_t local policy for vpp
+#
+
+read_files_pattern(systemd_sysctl_t, vpp_config_rw_t, vpp_config_rw_t)
+
+