ROOT USER AND SELINUX:
User root
(with UID 0) is the super user in Discretionary Access Control (DAC) implementation of *NIX operating systems. DAC is allowed by-default i.e. anyone can access anything unless UIDs, GIDs and permission mode restrict something. So root
can do anything because it's the kernel's SUPER USER who isn't denied anything.
SELinux is Mandatory Access Control (MAC) which is denied by-default i.e. no one can access anything unless a policy rule is defined to allow the access. So there is no SUPER CONTEXT which is allowed to do anything, whatever the UID is. You have to define a rule to allow any operation you want to perform on your device.
Please note that Access Controls (DAC or MAC) are enforced by kernel at back end, who is the actual operating system.
HOW SELINUX IS ENFORCED ON ANDROID?
SELinux policy rules are defined when building ROM and saved as a binary file /sepolicy
(or as split-policy
). This policy is loaded by init
(the very first process started in kernel's SELinux domain) before starting any services/daemons/processes on boot. Kernel starts with SELinux permissive
if built with option SECURITY_SELINUX_DEVELOP=y
(which is the default as discussed here and here). After loading policy, init
- when still running with kernel's context - sets SELinux enforcing
(depending on ROM build type and kernel parameter androidboot.selinux
(0)) and then switches to init's own context. From here afterwards, even init
isn't allowed by policy to revert back to permissive
mode (1, 2). Neither the policy can be modified even by root
user (3).
However there is one exception to above said rules. On userdebug
or eng
builds, u:r:su:s0
- which is the context adb shell
gets when adbd
is run as root (4) or when /system/xbin/su
is executed (5) - is allowed to do anything, including setting SELinux permissive (6).
But on a final production (user
) build of ROM, the only way to setenforce 0
or to modify policy is to take control of booting process before SELinux is set enforcing
by init
. That's what rooting solutions like Magisk do by replacing/patching /init
and /sepolicy
in RAM disk (boot.img
). Magisk runs root processes with context u:r:magisk:s0
which is allowed by patched policy to do anything.
Once you have rights (granted by DAC and MAC) to play with SELinux policy, you can define new SELinux policy rules as explained here.
Coming to your question:
selinux is enforcing but I want it to be permissive which will never happen with stock kernel
No. SELinux is set enforcing
by init
, not by kernel, except if built with SECURITY_SELINUX_ENFORCING=y
option (7).
a higher context to do things like supolicy --live
to patch selinux policy
There is no higher context that is allowed to do anything. You can't set mode to permissive
and can't patch policy on user
builds.
what is the (target) context that will allow any other (source) context to execute the script?
As said, there is no higher source context that can do anything to others. Likewise there is no lower target context that lets others do anything.
Also when executing a script, there isn't necessarily a single target context. Every file that the script uses (binaries, configurations, logs etc.) may have its different context label. And typetransitions can change source contexts too.
If you want to modify policy, you can get all avc denials
from kernel log and then define new SELinux rules accordingly:
~# dmesg -w | grep avc:
Solution:
Since you are already on eng
build, only replace kernel binary (zImage
) in your boot.img
if you want to replace kernel. Otherwise you get stuck by using init
and sepolicy
from boot.img
of a user
build.
On eng
build:
/init
doesn't set SELinux enforcing
on boot (8)
/sepolicy
allows root adb shell
to do anything including setenforce
and load_policy
as explained above
If your kernel is built with SECURITY_SELINUX_ALWAYS_ENFORCE
, you can't set SELinux permissive
once set enforcing
(9).
RELATED: