-
Notifications
You must be signed in to change notification settings - Fork 61
Getting Started
When doing SELinux development, it is easiest to use a Linux distribution that enables SELinux by default, like Fedora and any of its derivatives. Otherwise you will need to work through enabling SELinux and ensuring you have a working base policy before you can develop and test new enhancements or bug fixes.
Traditionally one names the Linux kernel tree “linux”. Don’t leave it as selinux or it will conflict with the userspace clone below. The dev branch is where all new development happens.
git clone -b dev https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git linux
git clone https://github.com/SELinuxProject/selinux-testsuite.git
This repository has some tooling used by Paul Moore, LSM/SELinux/audit kernel maintainer, to validate patches. Running these scripts on your patches may help catch things up front that he would otherwise complain about.
git clone https://github.com/pcmoore/git-verification_scripts
# Install dependencies - need clang-format, codespell, and python3 git module (used by spdxcheck from checkpatch.pl)
sudo dnf install clang-tools-extra codespell python3-GitPython
# Kernel scripts are under verify.linux.d directory.
# From a kernel tree with your patch applied, can run the script to check the top-most commit.
# Paul integrates the scripts into stacked git to apply to all patches.
# 10-linux_checkpatch just runs checkpatch.pl, which you should already be doing.
# 20-linux_build just tests a build, which you should already be doing.
# 30-linux_style checks formatting via clang-format and outputs a diff of differences.
# You should only be concerned with new diffs introduced by your patch, not pre-existing ones.
# 40-linux_codespell runs codespell to check spelling.
# You should only be concerned with new spelling errors introduced by your patch.
You only need this if you plan on using/testing a feature that depends on a newer version of the selinux userspace than your distribution provides, or if you plan on making a change to the selinux userspace too e.g. introducing support for a new policy capability or version into the policy compiler.
git clone https://github.com/SELinuxProject/selinux.git
# If you need a feature that depends on newer selinux userspace than your distribution package,
# follow the instructions in the README.md to build and install the userspace components.
# NB Make sure you specify your LIBDIR and SHLIBDIR so that you don't accidentally install
# 64-bit libraries to /lib instead of /lib64.
You only need to do this if you plan on making a change to the SELinux reference policy too, e.g. defining new permissions. However, even for defining new permissions, you can often achieve that locally without needing to rebuild the entire policy through a local policy module or by extracting and patching the base module (e.g. semodule -c -E base; vi base.cil; semodule -i base.cil), see Add new permissions.
git clone https://github.com/SELinuxProject/refpolicy.git
NB You must have installed the build dependencies for building the kernel, e.g.
sudo dnf build-dep kernel
Then you can configure and build your kernel:
cd linux
# Use the configuration of the kernel you are running.
cp /boot/config-$(uname -r) .config
# Generate a reduced configuration with only locally-installed modules; accept the defaults for all.
yes "" | make localmodconfig
# Merge this reduced configuration with the requirements for the selinux testsuite.
./scripts/kconfig/merge_config.sh .config ../selinux-testsuite/defconfig
# Optionally, customize your config - see below.
make menuconfig
# Compile the kernel
make
# Install the kernel and its modules
sudo make modules_install install
NB You may want to do a make menuconfig after the merge_config.sh and selectively enable debugging options under "Kernel hacking". I typically enable many debugging options to automatically catch memory corruption or leaks, locking bugs, etc. Some good ones to make sure you have enabled in your .config when testing your changes:
CONFIG_PROVE_LOCKING=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_DEBUG_LIST=y
CONFIG_UBSAN=y
CONFIG_KASAN=y # This imposes significant overhead so only use for testing; enable KFENCE instead for production.
CONFIG_KCSAN=y # Likewise imposes significant overhead and generates many false positives, only use for testing.
Before rebooting, make sure you have unhidden the GRUB menu or know how to unhide it at boot so you can select your new kernel, see https://fedoraproject.org/wiki/Changes/HiddenGrubMenu
sudo reboot
Verify that you are running the kernel you built.
# Check that the correct version and your username@hostname is listed along with the build timestamp.
cat /proc/version
Build and run the SELinux kernel testsuite. NB This requires that you have installed the dependencies mentioned in the README, ala:
sudo dnf install perl-Test perl-Test-Harness perl-Test-Simple selinux-policy-devel gcc libselinux-devel net-tools netlabel_tools iptables lksctp-tools-devel attr libbpf-devel keyutils-libs-devel quota xfsprogs-devel libuuid-devel e2fsprogs jfsutils dosfstools rdma-core-devel
The above list may be incomplete; always check the README for the most current list. Then you can run the testsuite.
cd selinux-testsuite
sudo make test
Confirm that there are no failures.
You will need to look at dmesg or cat /proc/kmsg output or journalctl -kb output to see any warnings/errors reported as a result of the debugging options; it is often good to check after running the testsuite to see if anything was reported during the run. KASAN, KFENCE, KCSAN, UBSAN, and KMEMLEAK usage are described in https://docs.kernel.org/dev-tools/index.html
Refer to https://docs.kernel.org/process/debugging/index.html
To add a new class and/or permission to the SELinux kernel code, edit security/selinux/include/classmap.h in the kernel tree and add your definition. This will define the class and/or permission for use in the kernel; the corresponding symbol definitions will be automatically generated during the kernel build. If not defined in the policy, then the class and/or permission will be handled in accordance with your policy's handle_unknown definition, which can be reject (refuse to load the policy), deny (deny the undefined class/permission), or allow (allow the undefined class/permission). handle_unknown is set to allow in modern Fedora policies.
Then, update the policy to define the permission and allow it where needed. Ultimately, this should be done by creating and submitting a patch to the refpolicy (an example can be seen here) but for testing purposes, you can locally add the new permission to your base policy and policy headers so that you can exercise the new permissions in a test that you add to the selinux-testsuite (an example can be found at this link).
To update refpolicy, edit refpolicy/policy/flask/security_classes and/or access_vectors in the refpolicy tree and add your definition. This will define the class and permission for use in the policy. You generally need to add the class and/or permission at the end of the existing list of classes or permissions for that class for backward compatibility with older kernels. The class and/or permission definition in policy need not line up with the definition in the kernel's classmap, as the values will be dynamically mapped by the kernel. Then add allow rules as appropriate to the policy for the new permissions - at a minimum you need to ensure that unconfined domains are allowed the new permissions. You likely do NOT want to load this policy into the kernel on your test system because Fedora policy has significant changes and stock refpolicy is unlikely to work out of the box. You can however test building and installing the refpolicy with your patch to its own policy directory separate from the Fedora policy. If you truly want to test loading your patched refpolicy, the best way is to download the source RPM for selinux-policy-targeted, modify it to include your change as an additional patch, and rebuild it so that you retain all of the Fedora changes.
To temporarily add the permissions to your base policy and policy headers for testing purposes, you can do the following:
# Extract base policy module in CIL format
sudo semodule -c -E base
# Edit and add your new permissions to the list of permissions in the class declaration.
# Or if introducing a new class, add a new class declaration, which can be done in a separate module instead.
# If the permission is likely to be required by other processes that are running, you should also add allow
# rules for the new permission to avoid breaking them.
vi base.cil
# Install the modified base module with your permission defined.
sudo semodule -i base.cil
# Edit the all_classname_perms macro to declare permission for use in test policy .te files
sudo dnf install selinux-policy-devel
cp /usr/share/selinux/devel/include/support/all_perms.spt .
sudo vi /usr/share/selinux/devel/include/support/all_perms.spt
# When done testing, remove your modified base module and revert the change to all_perms.spt
sudo semodule -r base
sudo cp all_perms.spt /usr/share/selinux/devel/include/support
SELinux kernel issues are listed at https://github.com/SELinuxProject/selinux-kernel/issues
SELinux userspace issues (some of which also involve kernel changes) are listed at https://github.com/SELinuxProject/selinux/issues
SELinux testsuite issues are listed at https://github.com/SELinuxProject/selinux-testsuite/issues
Outstanding patches for the SELinux kernel, userspace, and testsuite can be found at: https://patchwork.kernel.org/project/selinux/list/
See the separate SELinux Namespaces issue tracker for SELinux namespace tasks.
See https://docs.kernel.org/process/development-process.html, https://docs.kernel.org/process/submitting-patches.html, and https://docs.kernel.org/process/coding-style.html to understand how to develop and submit code for Linux in a manner that will improve your odds of acceptance.
SELinux has a public mailing list for developers, subscribe via https://subspace.kernel.org/vger.kernel.org.html#selinux. It is generally wise to read relevant postings to the list before beginning any area of new work. Searchable mailing list archives are available externally at https://lore.kernel.org/selinux/ . Patches for SELinux are tracked via https://patchwork.kernel.org/project/selinux/list/ .
- The SELinux kernel README - https://github.com/SELinuxProject/selinux-kernel/blob/main/README.md
- The SELinux Notebook - https://github.com/selinuxproject/selinux-notebook
- Paul Moore's blog (SELinux kernel maintainer), https://www.paul-moore.com/blog/
- Linux kernel documentation - https://www.kernel.org/doc/html/latest/index.html
- Linux source code cross referencer - https://elixir.bootlin.com/linux/latest/source
- SELinux userspace wiki - https://github.com/selinuxproject/selinux/wiki