Security-Enhanced Linux (SELinux) is enabled in Android to enforce the Mandatory Access Control for security. SELinux supports two working modes: permissive and enforcing:
- In permissive mode, it only audits the operations of all domains and prints the AVC (Access Vector Cache) errors that violate the sepolicy rules, but it never blocks any operations.
- In enforcing mode, it prints out the AVC errors and also blocks the operations that violate the sepolicy rules.
It is a good practice to set SELinux in permissive mode at the beginning of the development phase in order to easily bring up the system and fix any SELinux errors. After resolving all AVC errors, change the SELinux mode to enforcing mode.
SELinux Configuration
To change SELinux in build time
For CiV scenario:
The SELinux operation mode is configured using mixins. Edit the mixins.spec
file in the source folder for your lunch target at device/intel/project-celadon/<target-name>/mixins.spec
and rebuild the image to take effect. Set the sepolicy
key to either permissive or enforcing to enable the corresponding SELinux mode.
...
project-celadon: default
sepolicy: permissive
graphics: project-celadon(gen9+=true,hwc2=true,vulkan=false,drmhwc=false,minigbm
...
Note
- The permissive mode is only activated in userdebug or eng builds. The user builds always operate in enforcing SELinux mode in Android.
- After you change the sepolicy value in mixins.spec, run the ‘device/intel/mixins/mixin-update’ script to make the changes take effect before the build starts.
For CiC scenario:
CiC shares the same kernel running in the host, we need to change the SELinux mode for CiC by modifying the host kernel command line. For example, on a Ubuntu host device, edit the default GRUB configuration file /etc/default/grub
, and append the following option to the GRUB_CMDLINE_LINUX_DEFAULT key:
...
GRUB_CMDLINE_LINUX_DEFAULT="androidboot.selinux=permissive"
...
After updating the GRUB bootloader configuration and reboot the host with the following commands, the Celadon in Container will be run in permissive mode by default.
$ sudo update-grub && reboot
Note
- The permissive mode is only activated in userdebug or eng builds. The user builds always operate in enforcing SELinux mode in Android.
To change SELinux mode at runtime
In addition to change the SELinux operaion mode statically by editting the configuration file during the build time, you can change the SELinux mode at runtime through adb shell commands.
- Get the current SELinux operation mode with the
getenforce
command
$ adb shell
celadon:/ $ getenforce
Permissive
- Set the SELinux operation mode with the
setenforce
command
$ adb shell
celadon:/ $ su
celadon:/ # setenforce 0
celadon:/ # getenforce
Permissive
celadon:/ # setenforce 1
celadon:/ # getenforce
Enforcing
Note
- You must run the
setenforce
command with root permission. - Changing the SELinux operation mode returns it to its default mode specified in the mixins.spec file after system reboots.
Add sepolicy rules for a module
When you add a new module to Celadon, you might need to add relevant sepolicy rules, otherwise its operations might be blocked by SELinux. The following instructions take the ‘rfkill’ module as an example, and show you the required steps to get access to the system resources.
Add the initial sepolicy rules
-
For CiV scenario, create a sub-folder
rfkill
under thedevice/intel/project-celadon/sepolicy/
directory to host the sepolicy rules files. For CiC scenario, therfkill
folder should be created indevice/intel/cic/common/sepolicy
directory. -
Introduce the previous folder to the sepolicy compiler by adding the following line to the board configuration overlay file. For CiV scenario, edit the file
device/intel/mixins/groups/rfkill/true/BoardConfig.mk
:BOARD_SEPOLICY_DIRS += $(INTEL_PATH_SEPOLICY)/rfkill
Or, for CiC scenario, edit the file
device/intel/cic/common/BoardConfig.mk
:BOARD_SEPOLICY_DIRS += device/intel/cic/common/sepolicy/rfkill
-
Inside the sepolicy rules folder, create an initial file named ‘file_contexts’ with the following content. This assigns a file label for the rfkill executable file:
/vendor/bin/rfkill-init.sh u:object_r:rfkill_exec:s0
-
Create a SELinux type enforcement file
rfkill.te
to define the policy type and access control for therfkill
module:# Define a domain that the rfkill process runs in type rfkill, domain; # Define a file type for the rfkill executable file and assign this file type type rfkill_exec, exec_type, file_type, vendor_file_type; # Grant the permission to init process so that the init process starts the rfkill service # from init.rc and transition to rfkill domain init_daemon_domain(rfkill)
Add the additional sepolicy rules
-
You seldom add only initial sepolicy rules to make a module work properly. Reboot the device and search any AVC errors related to the rfkill module in the system
dmesg
orlogcat
output. AVC errors are associated with avc: or permissive= keywords as shown in the following example: -
In the previous output, the key ‘scontext’ indicates which module generates the AVC error and the cause. You then write sepolicy rules to the ‘.te’ file associated with that module, according to the relevant AVC error as shown in the previous example.
Some useful tools for SELinux
-
- audit2allow
-
audit2allow
is a host SELinux tool, which can be used to generate sepolicy rules based on the log file. It is available in the external/SELinux/prebuilts/bin/ folder on the host system.$ adb shell logcat > my_log.txt $ audit2allow -p patch_to_sepolicy -i my_log.txt -o generated_rules.txt
-
- load_policy
-
load_policy
is a tool on the Android device, which loads the compiled sepolicy at runtime in order to validate the modified sepolicy rules without making a new build. It is available in the /system/bin/ folder on the target platform.To generate the precompiled sepolicy binary that is loaded with the
load_policy
command, go to the top-most Celadon source tree:$ make precompiled_sepolicy
Then, push the generated binary to the Celadon device for verification:
$ adb push out/target/product/<target_name>/vendor/etc/SELinux/precompiled_sepolicy /sdcard $ adb root && adb shell load_sepolicy /sdcard/precompiled_sepolicy