vxlan: vxlan/vxlan.api API cleanup
[vpp.git] / extras / selinux / selinux_doc.md
1 # SELinux - VPP Custom SELinux Policy    {#selinux_doc}
2
3 ## Overview
4
5 Security-enhanced Linux (SELinux) is a security feature in the Linux kernel. At
6 a very high level, SELinux implements mandatory access controls (MAC), as
7 opposed to discretionary access control (DAC) implemented in standard Linux. MAC
8 defines how processes can interact with other system components (Files,
9 Directories, Other Processes, Pipes, Sockets, Network Ports). Each system
10 component is assigned a label, and then the SELinux Policy defines which labels
11 and which actions on each label a process is able to perform. The VPP Custom
12 SELinux Policy defines the actions VPP is allowed to perform on which labels.
13
14 The VPP Custom SELinux Policy is intended to be installed on RPM based platforms
15 (tested on CentOS 7 and RHEL 7). Though SELinux can run on Debian platforms, it
16 typically is not and therefore is not currently being built for Debian.
17
18 The VPP Custom SELinux Policy does not enable or disable SELinux, only allows
19 VPP to run when SELinux is enabled. A fresh install of either Fedora, CentOS or
20 RHEL will have SELinux enabled by default. To determine if SELinux is enabled on
21 a given system and enable it if needed, run:
22
23 ```
24    $ getenforce
25    Permissive
26
27    $ sudo setenforce 1
28
29    $ getenforce
30    Enforcing
31 ```
32
33 To make the change persistent, modify the following file to set
34 `SELINUX=enforcing`:
35
36 ```
37    $ sudo vi /etc/selinux/config
38    :
39    # This file controls the state of SELinux on the system.
40    # SELINUX= can take one of these three values:
41    #     enforcing - SELinux security policy is enforced.
42    #     permissive - SELinux prints warnings instead of enforcing.
43    #     disabled - No SELinux policy is loaded.
44    SELINUX=enforcing
45    :
46 ```
47
48 ## Installation
49
50 To install VPP, see the installation instructions on the VPP Wiki
51 (https://wiki.fd.io/view/VPP/Installing_VPP_binaries_from_packages). The VPP
52 Custom SELinux Policy is packaged in its own RPM starting in 18.04,
53 `vpp-selinux-policy-<VERSION>-<RELEASE>.rpm`. It is packaged and installed along
54 with the other VPP RPMs.
55
56 ### Fresh Install of VPP
57
58 If VPP has never been installed on a system, then starting in 18.04, the VPP
59 Custom SELinux Policy will be installed with the other RPMs and all the system
60 components managed by VPP will be labeled properly.
61
62 ### Fix SELinux Labels for VPP
63 In the case where the VPP Custom Policy is being installed for the first time,
64 either because VPP has been upgraded or packages were removed and then
65 reinstalled, several directories and files will not not be properly labeled. The
66 labels on these files will need to be fixed for VPP to run properly with SELinux
67 enabled. After the VPP Custom SELinux Policy is installed, run the following
68 commands to fix the labels. If VPP is already running, make sure to restart
69 VPP after the labels are fixed. This change is persistent for the life of the
70 file. Once the VPP Custom Policy is installed on the system, subsequent files
71 created by VPP will be labeled properly. This is only to fix files created by
72 VPP prior to the VPP Custom Policy being installed.
73
74 ```
75   $ sudo restorecon -Rv /etc/vpp/
76   $ sudo restorecon -Rv /usr/lib/vpp_api_test_plugins/
77   $ sudo restorecon -Rv /usr/lib/vpp_plugins/
78   $ sudo restorecon -Rv /usr/share/vpp/
79   $ sudo restorecon -Rv /var/run/vpp/
80
81   $ sudo chcon -t vpp_tmp_t /tmp/vpp_*
82   $ sudo chcon -t vpp_var_run_t /var/run/.vpp_*
83 ```
84
85 **NOTE:** Because the VPP APIs allow custom filenames in certain scenarios, the
86 above commands may not handle all files. Inspect your system and correct any
87 files that are mislabeled. For example, to verify all VPP files in `/tmp/` are
88 labeled properly, run:
89
90 ```
91   $ sudo ls -alZ /tmp/
92 ```
93
94 Any files not properly labeled with `vpp_tmp_t`, run:
95
96 ```
97   $ sudo chcon -t vpp_tmp_t /tmp/<filename>
98 ```
99
100 ## VPP Files
101
102 ### Recommended Default File Directories
103
104 Documentation in the VPP Wiki (https://wiki.fd.io/view/VPP/) and doxygen
105 generated documentation have examples with files located in certain directories.
106 Some of the recommend file locations have been moved to satisfy SELinux. Most of
107 the documentation has been updated, but links to older documentation still exist
108 and there may have been instances that were missed. Use the file locations
109 described below to allow SELinux to properly label the given files.
110
111 File locations that have changed:
112 * VPP Debug CLI Script Files
113 * vHost Sockets
114 * VPP Log Files
115
116 #### VPP Debug CLI Script Files
117
118 The VPP Debug CLI, `vppctl`, allows a sequence of CLI commands to be read from a
119 file and executed. To avoid from having to grant VPP access to all of `/tmp/` and
120 possibly `/home/` sub-directories, it is recommended that any VPP Debug CLI script
121 files be placed in a common directory such as `/usr/share/vpp/`.
122
123 For example:
124 ```
125 $ cat /usr/share/vpp/scripts/gigup.txt
126 set interface state GigabitEthernet0/8/0 up
127 set interface state GigabitEthernet0/9/0 up
128 ```
129
130 To execute:
131 ```
132 $ vppctl exec /usr/share/vpp/scripts/gigup.txt
133 ```
134 Or
135 ```
136 $ vppctl
137     _______    _        _   _____  ___
138  __/ __/ _ \  (_)__    | | / / _ \/ _ \
139  _/ _// // / / / _ \   | |/ / ___/ ___/
140  /_/ /____(_)_/\___/   |___/_/  /_/
141
142 vpp# exec /usr/share/vpp/scripts/gigup.txt
143 vpp# quit
144
145 ```
146
147 If the file is not labeled properly, you will see something similar to:
148 ```
149 $ vppctl exec /home/<user>/dev/vpp/scripts/vppctl/gigup.txt
150 exec: failed to open `/home/<user>/dev/vpp/scripts/vppctl/gigup.txt': Permission denied
151
152 $ ls -alZ
153 drwxrwxr-x. <user> <user> unconfined_u:object_r:user_home_t:s0 .
154 drwxrwxr-x. <user> <user> unconfined_u:object_r:user_home_t:s0 ..
155 -rw-r--r--. <user> <user> unconfined_u:object_r:user_home_t:s0 gigup.txt
156 ```
157
158 ##### Original Documentation
159
160 Some of the original documentation showed script files being executed out of
161 `/tmp/`. Convenience also may lead to script files being placed in
162 `/home/<user>/` subdirectories. If a file is generated by the VPP process in
163 `/tmp/`, for example a trace file or pcap file, it will get properly labeled
164 with the SELinux label `vpp_tmp_t`. When a file is created, unless a rule is in
165 place for the process that created it, the file will inherit the SELinux label
166 of the parent directory. So if a user creates a file themselves in `/tmp/`, it
167 will get the SELinux label `tmp_t`, which VPP does not have permission to
168 access. Therefore it is recommended that script files are located as described
169 above.
170
171 #### vHost Sockets
172
173 vHost sockets are created from VPP perspective in either Server or Client mode.
174 In Server mode, the socket name is provided to VPP and VPP creates the socket.
175 In Client mode, the socket name is provided to VPP and the hypervisor creates
176 the socket. In order for VPP and hypervisor to share the socket resource with
177 SELinux enabled, a rule in the VPP Custom SELinux Policy has been added. This
178 rules allows processes with the `svirt_t` label (the hypervisor) to access
179 sockets with the `vpp_var_run_t` label. As such, when SELinux is enabled,
180 vHost sockets should be created in the directory `/var/run/vpp/`.
181
182 ##### Original Documentation
183
184 Some of the original documentation showed vHost sockets being created in the
185 directory `/tmp/`. To work properly with SELinux enabled, vHost sockets should be
186 created as described above.
187
188 #### VPP Log Files
189
190 The VPP log file location is set by updating the `/etc/vpp/startup.conf` file:
191
192 ```
193 vi /etc/vpp/startup.conf
194 unix {
195 :
196   log /var/log/vpp/vpp.log
197 :
198 }
199
200 ```
201
202 By moving the log file to `/var/log/vpp/`, it will get the label `vpp_log_t`,
203 which indicates that the files are log files so they benefit from the
204 associated rules (for example granting rights to logrotate so that it can
205 manipulate them).
206
207 ##### Original Documentation
208
209 The default `startup.conf` file creates the VPP log file in `/tmp/vpp.log`. By
210 leaving the log file in `/tmp/`, it will get the label `vpp_tmp_t`. Moving it
211 to `/var/log/vpp/`, it will get the label `vpp_log_t`.
212
213 ### Use of Non-default File Directories
214
215 VPP installs multiple files on the system.
216 Some files have fixed directory and file names:
217 - /etc/bash_completion.d/vppctl_completion
218 - /etc/sysctl.d/80-vpp.conf
219 - /usr/lib/systemd/system/vpp.service
220
221 Others files have default directory and file names but the default can be
222 overwritten:
223 - /etc/vpp/startup.conf
224   - Can be changed via the `/usr/lib/systemd/system/vpp.service` file by
225     changing the -c option on the VPP command line:
226
227 ```
228 ExecStart=/usr/bin/vpp -c /etc/vpp/startup.conf
229 ```
230
231 - /run/vpp/cli.sock
232   - Can be changed via the `/etc/vpp/startup.conf` file by changing the
233     cli-listen setting:
234
235 ```
236 unix {
237 :
238   cli-listen /run/vpp/cli.sock
239 :
240 }
241 ```
242
243
244 - /var/log/vpp/vpp.log
245   - Can be changed via the `/etc/vpp/startup.conf` file by changing the log
246     setting:
247
248 ```
249 unix {
250   :
251   log /var/log/vpp/vpp.log
252   :
253 }
254
255 ```
256
257 If the directory of any VPP installed files is changed from the default, ensure
258 that the proper SELiunx label is applied. The SELinux label can be determined by
259 passing the -Z option to many common Linux commands:
260
261 ```
262 ls -alZ /run/vpp/
263 drwxr-xr-x. root vpp  system_u:object_r:vpp_var_run_t:s0 .
264 drwxr-xr-x. root root system_u:object_r:var_run_t:s0     ..
265 srwxrwxr-x. root vpp  system_u:object_r:vpp_var_run_t:s0 cli.sock
266 ```
267
268 ### VPP SELinux Types ###
269
270 The following SELinux types are created by the VPP Custom SELinux Policy:
271 - `vpp_t` - Applied to:
272   - VPP process and spawned threads.
273
274 - `vpp_config_rw_t` - Applied to:
275   - `/etc/vpp/*`
276
277 - `vpp_tmp_t` - Applied to:
278   - `/tmp/*`
279
280 - `vpp_exec_t` - Applied to:
281   - `/usr/bin/*`
282
283 - `vpp_lib_t` - Applied to:
284   - `/usr/lib/vpp_api_test_plugins/*`
285   - `/usr/lib/vpp_plugins/*`
286
287 - `vpp_unit_file_t` - Applied to:
288   - `/usr/lib/systemd/system/vpp.*`
289
290 - `vpp_log_t` - Applied to:
291   - `/var/log/vpp/*`
292
293 - `vpp_var_run_t` - Applied to:
294   - `/var/run/vpp/*`
295
296 ## Debug SELinux Issues
297
298 If SELinux issues are suspected, there are a few steps that can be taken to
299 debug the issue. This section provides a few pointers on on those steps. Any
300 SELinux JIRAs will need this information to properly address the issue.
301
302 ### Additional SELinux Packages and Setup
303
304 First, install the SELinux troubleshooting packages:
305
306 ```
307 $ sudo yum -y install setroubleshoot setroubleshoot-server setools-console
308 -- OR --
309 $ sudo dnf -y install setroubleshoot setroubleshoot-server setools-console
310 ```
311
312 To enable proper logging, restart auditd:
313
314 ```
315 $ sudo service auditd restart
316 ```
317
318 While debugging issues, it is best to set SELinux to `Permissive` mode. In
319 `Permissive` mode, SELinux will still detect and flag errors, but will allow
320 processes to continue normal operation. This allows multiple errors to be
321 collected at once as opposed to breaking on each individual error. To set
322 SELinux to `Permissive` mode (until next reboot or it is set back), use:
323
324 ```
325 $ sudo setenforce 0
326
327 $ getenforce
328 Permissive
329 ```
330
331 After debugging, to set SELinux back to `Enforcing` mode, use:
332
333 ```
334 $ sudo setenforce 1
335
336 $ getenforce
337 Enforcing
338 ```
339
340 ### Debugging
341
342 Once the SELinux troubleshooting packages are installed, perform the actions
343 that are suspected to be blocked by SELinux. Either `tail` the log during
344 these actions or `grep` the log for additional SELinux logs:
345
346 ```
347 sudo tail -f /var/log/messages
348 -- OR --
349 sudo journalctl -f
350 ```
351
352 Below are some examples of SELinux logs that are generated:
353
354 ```
355 May 14 11:28:34 svr-22 setroubleshoot: SELinux is preventing /usr/bin/vpp from read access on the file hostCreate.txt. For complete SELinux messages run: sealert -l a418f869-f470-4c8a-b8e9-bdd41f2dd60b
356 May 14 11:28:34 svr-22 python: SELinux is preventing /usr/bin/vpp from read access on the file hostCreate.txt.#012#012*****  Plugin catchall (100. confidence) suggests   **************************#012#012If you believe that vpp should be allowed read access on the hostCreate.txt file by default.#012Then you should report this as a bug.#012You can generate a local policy module to allow this access.#012Do#012allow this access for now by executing:#012# ausearch -c 'vpp_main' --raw | audit2allow -M my-vppmain#012# semodule -i my-vppmain.pp#012
357 May 14 11:28:34 svr-22 setroubleshoot: SELinux is preventing /usr/bin/vpp from read access on the file hostCreate.txt. For complete SELinux messages run: sealert -l a418f869-f470-4c8a-b8e9-bdd41f2dd60b
358 May 14 11:28:34 svr-22 python: SELinux is preventing /usr/bin/vpp from read access on the file hostCreate.txt.#012#012*****  Plugin catchall (100. confidence) suggests   **************************#012#012If you believe that vpp should be allowed read access on the hostCreate.txt file by default.#012Then you should report this as a bug.#012You can generate a local policy module to allow this access.#012Do#012allow this access for now by executing:#012# ausearch -c 'vpp_main' --raw | audit2allow -M my-vppmain#012# semodule -i my-vppmain.pp#012
359 May 14 11:28:37 svr-22 setroubleshoot: SELinux is preventing vpp_main from map access on the packet_socket packet_socket. For complete SELinux messages run: sealert -l ab6667d9-3f14-4dbd-96a0-7a655f7b4eb1
360 May 14 11:28:37 svr-22 python: SELinux is preventing vpp_main from map access on the packet_socket packet_socket.#012#012*****  Plugin catchall (100. confidence) suggests   **************************#012#012If you believe that vpp_main should be allowed map access on the packet_socket packet_socket by default.#012Then you should report this as a bug.#012You can generate a local policy module to allow this access.#012Do#012allow this access for now by executing:#012# ausearch -c 'vpp_main' --raw | audit2allow -M my-vppmain#012# semodule -i my-vppmain.pp#012
361 May 14 11:28:51 svr-22 setroubleshoot: SELinux is preventing vpp_main from map access on the packet_socket packet_socket. For complete SELinux messages run: sealert -l ab6667d9-3f14-4dbd-96a0-7a655f7b4eb1
362 May 14 11:28:51 svr-22 python: SELinux is preventing vpp_main from map access on the packet_socket packet_socket.#012#012*****  Plugin catchall (100. confidence) suggests   **************************#012#012If you believe that vpp_main should be allowed map access on the packet_socket packet_socket by default.#012Then you should report this as a bug.#012You can generate a local policy module to allow this access.#012Do#012allow this access for now by executing:#012# ausearch -c 'vpp_main' --raw | audit2allow -M my-vppmain#012# semodule -i my-vppmain.pp#012
363 ```
364
365 From the logs above, there are two sets of commands that are recommended to be
366 run. The first is to run the `sealert` command. The second is to run the
367 `ausearch | audit2allow` commands and the `semodule` command.
368
369 #### sealert Command
370
371 This `sealert` command provides a more detailed output for the given issue
372 detected.
373
374 ```
375 $ sealert -l a418f869-f470-4c8a-b8e9-bdd41f2dd60b
376 SELinux is preventing /usr/bin/vpp from 'read, write' accesses on the chr_file noiommu-0.
377
378 *****  Plugin device (91.4 confidence) suggests   ****************************
379
380 If you want to allow vpp to have read write access on the noiommu-0 chr_file
381 Then you need to change the label on noiommu-0 to a type of a similar device.
382 Do
383 # semanage fcontext -a -t SIMILAR_TYPE 'noiommu-0'
384 # restorecon -v 'noiommu-0'
385
386 *****  Plugin catchall (9.59 confidence) suggests   **************************
387
388 If you believe that vpp should be allowed read write access on the noiommu-0 chr_file by default.
389 Then you should report this as a bug.
390 You can generate a local policy module to allow this access.
391 Do
392 allow this access for now by executing:
393 # ausearch -c 'vpp' --raw | audit2allow -M my-vpp
394 # semodule -i my-vpp.pp
395
396
397 Additional Information:
398 Source Context                system_u:system_r:vpp_t:s0
399 Target Context                system_u:object_r:device_t:s0
400 Target Objects                noiommu-0 [ chr_file ]
401 Source                        vpp
402 Source Path                   /usr/bin/vpp
403 Port                          <Unknown>
404 Host                          vpp_centos7_selinux
405 Source RPM Packages           vpp-19.01.2-rc0~17_gcfd3086.x86_64
406 Target RPM Packages
407 Policy RPM                    selinux-policy-3.13.1-229.el7_6.12.noarch
408 Selinux Enabled               True
409 Policy Type                   targeted
410 Enforcing Mode                Permissive
411 Host Name                     vpp_centos7_selinux
412 Platform                      Linux vpp_centos7_selinux
413                               3.10.0-957.12.1.el7.x86_64 #1 SMP Mon Apr 29
414                               14:59:59 UTC 2019 x86_64 x86_64
415 Alert Count                   1
416 First Seen                    2019-05-13 18:10:50 EDT
417 Last Seen                     2019-05-13 18:10:50 EDT
418 Local ID                      a418f869-f470-4c8a-b8e9-bdd41f2dd60b
419
420 Raw Audit Messages
421 type=AVC msg=audit(1557785450.964:257): avc:  denied  { read write } for  pid=5273 comm="vpp" name="noiommu-0" dev="devtmpfs" ino=36022 scontext=system_u:system_r:vpp_t:s0 tcontext=system_u:object_r:device_t:s0 tclass=chr_file permissive=1
422
423
424 type=AVC msg=audit(1557785450.964:257): avc:  denied  { open } for  pid=5273 comm="vpp" path="/dev/vfio/noiommu-0" dev="devtmpfs" ino=36022 scontext=system_u:system_r:vpp_t:s0 tcontext=system_u:object_r:device_t:s0 tclass=chr_file permissive=1
425
426
427 type=SYSCALL msg=audit(1557785450.964:257): arch=x86_64 syscall=open success=yes exit=ENOTBLK a0=7fb395ffd7f0 a1=2 a2=7fb395ffd803 a3=7fb395ffe2a0 items=0 ppid=1 pid=5273 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=993 sgid=0 fsgid=993 tty=(none) ses=4294967295 comm=vpp exe=/usr/bin/vpp subj=system_u:system_r:vpp_t:s0 key=(null)
428
429 Hash: vpp,vpp_t,device_t,chr_file,read,write
430 ```
431
432 In general, this command pumps out too much info and is only needed for
433 additional debugging for tougher issues. Also note that once the process being
434 tested is restarted, this command loses it's context and will not provide any
435 information:
436
437 ```
438 $ sealert -l a418f869-f470-4c8a-b8e9-bdd41f2dd60b
439 Error
440 query_alerts error (1003): id (a418f869-f470-4c8a-b8e9-bdd41f2dd60b) not found
441 ```
442
443 #### ausearch | audit2allow and semodule Commands
444
445 These set of commands are more useful for basic debugging. The
446 `ausearch | audit2allow` commands generate a set files. It may be worthwhile to
447 run the commands in a temporary subdirectory:
448
449 ```
450 $ mkdir test-01/; cd test-01/
451
452 $ sudo ausearch -c 'vpp_main' --raw | audit2allow -M my-vppmain
453
454 $ ls
455 my-vpp.pp  my-vpp.te
456
457 $ cat my-vpp.te
458 module my-vpp 1.0;
459
460 require {
461         type user_home_t;
462         type vpp_t;
463         class packet_socket map;
464         class file { open read };
465 }
466
467 #============= vpp_t ==============
468 allow vpp_t self:packet_socket map;
469 allow vpp_t user_home_t:file { open read };
470 ```
471
472 As shown above, the file `my-vpp.te` has been generated. This file shows
473 possible changes to the SELinux policy that may fix the issue. If an SELinux
474 policy was being created from scratch, this policy could be applied using the
475 `semodule -i my-vpp.pp` command. HOWEVER, VPP already has a policy in place. So
476 these changes need to be incorporated into the existing policy. The VPP SELinux
477 policy is located in the following files:
478
479 ```
480 $ ls extras/selinux/
481 selinux_doc.md  vpp-custom.fc  vpp-custom.if  vpp-custom.te
482 ```
483
484 In this example, `map` needs to be added to the `packet_socket` class. If the
485 `vpp-custom.te` is examined (prior to this fix), then one would see that the
486 `packet_socket` class is already defined and just needs to be updated:
487
488 ```
489 $ vi extras/selinux/vpp-custom.te
490 :
491 allow vpp_t self:process { execmem execstack setsched signal }; # too benevolent
492 allow vpp_t self:packet_socket { bind create setopt ioctl };  <---
493 allow vpp_t self:tun_socket { create relabelto relabelfrom };
494 :
495 ```
496
497 Before blindly applying the changes proposed by the `ausearch | audit2allow`
498 commands, try to determine what is being allowed by the policy and determine if
499 this is desired, or if the code can be reworked to no longer require the
500 suggested permission. In the `my-vpp.te` file from above, it is suggested to
501 allow `vpp_t` (i.e. the VPP process) access to all files in the home directory
502 (`allow vpp_t user_home_t:file { open read };`). This was because a
503 `vppctl exec` command was executed calling a script located in the
504 `/home/<user>/` directory. Once this script was run from the `/usr/share/vpp/`
505 directory as described in a section above, these permissions were no longer
506 needed.