You should definitely read the semanage(8) manual page, even if the command's syntax tends to be similar for all the concepts which are managed. You will find common options to all sub-commands: -a to add, -d to delete, -m to modify, -l to list, and -t to indicate a type (or domain).
semanage login -l lists the current mapping between user identifiers and SELinux identities. Users that have no explicit entry get the identity indicated in the __default__ entry. The semanage login -a -s user_u user command will associate the user_u identity to the given user. Finally, semanage login -d user drops the mapping entry assigned to this user.
# semanage login -a -s user_u rhertzog
# semanage login -l
Login Name SELinux User MLS/MCS Range
__default__ unconfined_u s0-s0:c0.c1023
rhertzog user_u None
root unconfined_u s0-s0:c0.c1023
system_u system_u s0-s0:c0.c1023
# semanage login -d rhertzog
semanage user -l lists the mapping between SELinux user identities and allowed roles. Adding a new identity requires to define both the corresponding roles and a labeling prefix which is used to assign a type to personal files (/home/user/*). The prefix must be picked among user, staff, and sysadm. The “staff” prefix results in files of type “staff_home_dir_t”. Creating a new SELinux user identity is done with semanage user -a -R roles -P prefix identity. Finally, you can remove an SELinux user identity with semanage user -d identity.
# semanage user -a -R 'staff_r user_r' -P staff test_u
# semanage user -l
Labeling MLS/ MLS/
SELinux User Prefix MCS Level MCS Range SELinux Roles
root sysadm s0 s0-s0:c0.c1023 staff_r sysadm_r system_r
staff_u staff s0 s0-s0:c0.c1023 staff_r sysadm_r
sysadm_u sysadm s0 s0-s0:c0.c1023 sysadm_r
system_u user s0 s0-s0:c0.c1023 system_r
test_u staff s0 s0 staff_r user_r
unconfined_u unconfined s0 s0-s0:c0.c1023 system_r unconfined_r
user_u user s0 s0 user_r
# semanage user -d test_u
14.4.3.3. Managing File Contexts, Ports and Booleans
Each SELinux module provides a set of file labeling rules, but it is also possible to add custom labeling rules to cater to a specific case. For example, if you want the web server to be able to read files within the /srv/www/ file hierarchy, you could execute semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?" followed by restorecon -R /srv/www/. The former command registers the new labeling rules and the latter resets the file types according to the current labeling rules.
Similarly, TCP/UDP ports are labeled in a way that ensures that only the corresponding daemons can listen to them. For instance, if you want that the web server be able to listen on port 8080, you should run semanage port -m -t http_port_t -p tcp 8080.
Some SELinux modules export boolean options that you can tweak to alter the behaviour of the default rules. The getsebool utility can be used to inspect those options (getsebool boolean displays one option, and getsebool -a them all). The setsebool boolean value command changes the current value of a boolean option. The -P option makes the change permanent, it means that the new value becomes the default and will be kept across reboots. The example below grants web servers an access to home directories (this is useful when users have personal websites in ~/public_html/).
# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> off
# setsebool -P httpd_enable_homedirs on
# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> on
14.4.4. Adapting the Rules
Since the SELinux policy is modular, it might be interesting to develop new modules for (possibly custom) applications that lack them. These new modules will then complete the reference policy.
To create new modules, the selinux-policy-dev package is required, as well as selinux-policy-doc. The latter contains the documentation of the standard rules (/usr/share/doc/selinux-policy-doc/html/) and sample files that can be used as templates to create new modules. Install those files and study them more closely:
$ zcat /usr/share/doc/selinux-policy-doc/Makefile.example.gz >Makefile
$ zcat /usr/share/doc/selinux-policy-doc/example.fc.gz >example.fc
$ zcat /usr/share/doc/selinux-policy-doc/example.if.gz >example.if
$ cp /usr/share/doc/selinux-policy-doc/example.te ./
The .te file is the most important one. It defines the rules. The .fc file defines the “file contexts”, that is the types assigned to files related to this module. The data within the .fc file are used during the file labelling step. Finally, the .if file defines the interface of the module: it's a set of “public functions” that other modules can use to properly interact with the module that you're creating.
14.4.4.1. Writing a .fc file
Reading the below example should be sufficient to understand the structure of such a file. You can use regular expressions to assign the same security context to multiple files, or even an entire directory tree.
Example 14.2. example.fc file
# myapp executable will have:
# labeclass="underline" system_u:object_r:myapp_exec_t
# MLS sensitivity: s0
# MCS categories: <none>
/usr/sbin/myapp -- gen_context(system_u:object_r:myapp_exec_t,s0)
14.4.4.2. Writing a .if File
In the sample below, the first interface (“myapp_domtrans”) controls who can execute the application. The second one (“myapp_read_log”) grants read rights on the application's log files.
Each interface must generate a valid set of rules which can be embedded in a .te file. You should thus declare all the types that you use (with the gen_require macro), and use standard directives to grant rights. Note, however, that you can use interfaces provided by other modules. The next section will give more explanations about how to express those rights.