diff options
Diffstat (limited to 'extras/selinux')
-rw-r--r-- | extras/selinux/selinux_doc.md | 294 | ||||
-rw-r--r-- | extras/selinux/vpp-custom.fc | 22 | ||||
-rw-r--r-- | extras/selinux/vpp-custom.if | 2 | ||||
-rw-r--r-- | extras/selinux/vpp-custom.te | 139 |
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) + + |