1

I have a rooted android device and I need to inject following policies into it:

sepolicy-inject -s init -t su -c process -p transition -l
sepolicy-inject -s su -t system_file -c file -p entrypoint -l
sepolicy-inject -s init -t su -c process -p rlimitinh -l
sepolicy-inject -s init -t su -c process -p siginh -l
sepolicy-inject -s su -t shell_exec -c file -p read -l
sepolicy-inject -s su -t shell_exec -c file -p execute -l
sepolicy-inject -s su -t shell_exec -c file -p getattr  -l
sepolicy-inject -s su -t vendor_toolbox_exec -c file -p execute_no_trans -l
sepolicy-inject -s init -t su -c process -p noatsecure -l
sepolicy-inject -s su -t toolbox_exec -c file -p getattr -l
sepolicy-inject -s su -t toolbox_exec -c file -p execute -l
sepolicy-inject -s su -t system_file -c file -p execute_no_trans -l
sepolicy-inject -s su -t storage_file -c dir -p search -l
sepolicy-inject -s su -t storage_file -c lnk_file -p read -l
sepolicy-inject -s su -t tmpfs -c dir -p search -l
sepolicy-inject -s su -t mnt_user_file -c dir -p search -l
sepolicy-inject -s su -t mnt_user_file -c lnk_file -p read -l
sepolicy-inject -s su -t sdcardfs -c dir -p search -l
sepolicy-inject -s su -t sdcardfs -c file -p append -l
sepolicy-inject -s su -t toolbox_exec -c file -p read -l
sepolicy-inject -s su -t toolbox_exec -c file -p open -l
sepolicy-inject -s su -t sdcardfs -c file -p read -l
sepolicy-inject -s su -t sdcardfs -c file -p write -l

As you can see, I am using sepolicy-inject commands to inject the required policies. I am facing a problem where on reboot these policies not exists anymore.

As per my understanding the new policies are injected at /sys/fs/selinux/policy location and this is not persistent storage. Also, there is a file on root partition /sepolicy which contain these policy rules.

I found ./sepolicy in boot.img. I have a A/B partition device so, the ./sepolicy in boot.img is for recovery only.

Now, I am not able to understand how to inject the required policies permanently to the device because of following reason:

  1. /sys/fs/selinux/policy and /sepolicy are not on permanent storage partition.
  2. boot.img only contain SELinux policies that are available on recovery only.

Please suggest how can I achieve my goal.

Vatish Sharma
  • 1,536
  • 3
  • 16
  • 35

3 Answers3

2

I know the question was asked quite some time ago, but since I tried doing something similar recently and this post was one of the top hits on Google, I want to share my recent experience to help others.

As I believe the answer answer your questions, here is a shameless copy/paste of my answer to this question:

Note that this answer will focus solely on Android 9 to 13 and Treble devices.

If we want to know how to modify the SELinux policies, I believe it is good to first understand how the policies are loaded in the first place.

SELinux in the boot process

At an early stage of the Android boot process and after mounting most of the partitions, init will attempt to load the SELinux policies from a monolithic sepolicy file found at either /odm/etc/selinux/precompiled_sepolicy or /vendor/etc/selinux/precompiled_sepolicy. If init notices that the device is updated out of sync, init will instead recompile the SELinux policies based on .cil files that can be found on several locations.

You can find all the details in the comments of the init/selinux.cpp source file and by looking at the implementation, but here is a summary of the exact steps taken by init:

  1. Find the sepolicy file to use:
    • if /odm/etc/selinux/precompiled_sepolicy exists, use it as the sepolicy file to use
    • else, if /vendor/etc/selinux/precompiled_sepolicy exists, use it as the sepolicy file to use
    • else if neither of the above exists, stop here, recompile the policies based on the .cil files and load the newly compiled sepolicy file.
  2. Check if device was updated out of sync:
    • Compare /(odm|vendor)/etc/selinux/precompiled_sepolicy.plat_sepolicy_and_mapping.sha256 and /system/etc/selinux/plat_sepolicy_and_mapping.sha256
    • Compare /(odm|vendor)/etc/selinux/precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256 and /system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256
    • Compare /(odm|vendor)/etc/selinux/precompiled_sepolicy.product_sepolicy_and_mapping.sha256 and /product/etc/selinux/product_sepolicy_and_mapping.sha256
    • (On Android 13) Compare /(odm|vendor)/etc/selinux/precompiled_sepolicy.apex_sepolicy.sha256 and /dev/selinux/apex_sepolicy.sha256
    • if any of the above pair of files do not match, stop here, recompile the policies based on the .cil files and load the newly compiled sepolicy file.
  3. If everything is ok, load the precompiled sepolicy file (/odm/etc/selinux/precompiled_sepolicy or /vendor/etc/selinux/precompiled_sepolicy)

The compilation of the policies based on the .cil files is as follows:

  1. Get the latest version of the policies that are compatible with the vendor version (/vendor/etc/selinux/plat_sepolicy_vers.txt, note that init does not look at the file in the /odm partition)
  2. Gather the .cil files to compile:
    • /system/etc/selinux/mapping/{vendor_version}.cil
    • /system/etc/selinux/mapping/{vendor_version}.compat.cil
    • /system_ext/etc/selinux/system_ext_sepolicy.cil
    • /system_ext/etc/selinux/mapping/{vendor_version}.cil
    • /product/etc/selinux/product_sepolicy.cil
    • /product/etc/selinux/mapping/{vendor_version}.cil
    • /vendor/etc/selinux/plat_pub_versioned.cil
    • /vendor/etc/selinux/vendor_sepolicy.cil or if it does not exist: /vendor/etc/selinux/nonplat_sepolicy.cil
    • /odm/etc/selinux/odm_sepolicy.cil
  3. Compile the above files with secilc to /dev/sepolicy.XXXXXX
  4. Load policies from /dev/sepolicy.XXXXXX

Modifying SELinux policies permantently

Now that we understand how init loads the policies, it is easy to see how one could permanently add new policies to the system:

  • Directly add the policies to /odm/etc/selinux/precompiled_sepolicy or /vendor/etc/selinux/precompiled_sepolicy with sepolicy-inject:
    sepolicy-inject -s su -t system_file -c file -p entrypoint -P /vendor/etc/selinux/precompiled_sepolicy -o /vendor/etc/selinux/precompiled_sepolicy
    
  • Make init thinks the device is updated out of sync (By modifying one of the above .sha256 files, or deleting the precompiled sepolicy files) and modify one of the above .cil files

Note that in both cases, you will need to have a read-write access to the partition you want to modify (/vendor, /odm, and/or /system). These partitions are normally mounted as read-only, so you will have to either:

  • Remount them as read-write if you have root access (either because your device is rooted, or using adb root on a userdebug Android build)
  • Boot in recovery mode, mount the partitions as read-write and modify them in recovery

If you do not want to have to remount the partitions every time you want to change the SELinux policies, you can add some SELinux rules to allow init to load new policies, and then create an init script that will load new policies. You can find which SELinux rules are needed by searching for SELinux violations (avc errors) in the device logs on startup:

adb logcat | grep avc

With this, you will be able to have an init script that loads new policies with sepolicy-inject.

Alhyoss
  • 21
  • 4
0

"/sepolicy" is a ramdisk so it's temporarily. You can solve it by put that command in some "init" script that will run "sepolicy-inject ..." commands at bootup ;)

emandt
  • 2,547
  • 2
  • 16
  • 20
  • 1
    "/sepolicy" is temporary ramdisk **only on pre-[system-as-root](https://source.android.com/devices/bootloader/system-as-root) devices**. – Irfan Latif Aug 13 '19 at 21:43
  • This is not working. I got `avc: denied` errors because of missing SE-Linux policies to run these commands as root. – Vatish Sharma Aug 14 '19 at 04:10
  • Please refer https://android.stackexchange.com/questions/215010/how-to-make-selinux-injected-rules-persistent-without-unpacking-packing-boot-img/215395#215395 for more detail. – Vatish Sharma Aug 14 '19 at 04:20
-1

just disable selinux by setting it to permissive