Android 11 source code - security policy SELinux off

Introduction to SELinux

As part of the Android security model, Android uses Security-Enhanced Linux (SELinux) to enforce Mandatory Access Control (MAC) on all processes, even those running with Root/superuser privileges (a Linux feature). With SELinux, Android can better secure and restrict system services, control access to application data and system logs, reduce the impact of malware, and protect users from possible flaws in the code on mobile devices.

SELinux operates on the principle of default deny : anything not explicitly allowed is denied. SELinux can operate in two global modes :

  1. Permissive mode: Permission denials are logged but not enforced.
  2. Enforce Mode: Permission denial events are logged and enforced.

Android includes SELinux (in enforcing mode) and corresponding security policies that apply across AOSP by default. In enforcing mode, illegal operations are blocked and all attempted violations are logged by the kernel to dmesg and logcat. When developing, you should use these error messages to optimize your software and SELinux policies before enforcing them.

In addition, SELinux supports domain-based permissive mode. In this mode, specific domains (processes) can be placed in permissive mode while leaving the rest of the system in globally enforced mode. In simple terms, a domain is a label used in a security policy to identify a process or a group of processes, and the security policy treats all processes with the same domain label in the same way. With domain-based permissive mode, SELinux can be gradually applied to more and more parts of the system, and policies can be established for new services (while keeping the rest of the system in enforcing mode).

background

The Android security model is based in part on the concept of the application sandbox. Each application runs in its own sandbox. Prior to Android 4.3, these sandboxes were defined by creating a unique Linux UID for each application (created at application installation time). Android 4.3 and higher use SELinux to further define the boundaries of the Android application sandbox.

Based on Android 4.3 (permissive mode) and Android 4.4 (partially enforcing mode), in Android 5.0 and higher, SELinux is fully enforced. With this change, Android has moved from enforcing SELinux on a limited set of key domains (installd, netd, vold, and zygote) to enforcing SELinux on all domains (over 60). in particular:

  • In Android 5.x and higher, all domains are in enforcing mode.
  • No process other than init should run in the init domain.
  • Any general denial (for block_device, socket_device, default_service) indicates that the device requires a special domain.

Android 6.0 strengthens system security by reducing the permissiveness of our policies, enabling better user isolation and IOCTL filtering, reducing threats to services accessible from outside the device/system, further hardening the SELinux domain, and highly restrictive access to / proc access.

Android 7.0 updates SELinux configuration to further lock down the application sandbox and reduce the attack surface. This release also splits the monolithic mediaserver stack into smaller processes to reduce their scope of authority.

Android 8.0 updates SELinux to work with Treble, which separates lower-level vendor code from the Android system framework. This release updates SELinux policy to allow device manufacturers and SOC vendors to update their own policy sections, build their own images (vendor.img, boot.img, etc.), and then update those images regardless of platform, and vice versa.

While it is possible to run a higher/newer version of the platform (framework) on the device, the reverse is not true; the vendor image (vendor.img/odm.img) cannot be at a higher version than the platform (system.img). Therefore, newer versions of the platform may present SELinux compatibility issues because the version of the platform SELinux policy is newer than the vendor SELinux portion of the policy. The Android 8.0 model provides a way to maintain compatibility without unnecessary simultaneous OTAs.

Disable Android SELinux

Why it needs to be closed:
When the application layer accesses the device node, it cannot be accessed due to selinux permission issues, so close selinux first.

View the SELinux status value of the current prototype:

adb shell getenforce

Enforcing : Indicates that SELinux is on;
Permissive : Indicates that SELinux is off.

temporarily closed

It is relatively simple to temporarily close SELinux, but the premise is that the prototype can be rooted . The setenforce command modifies the value of /sys/fs/selinux/enforcethe node , which is a strategy for modifying selinux in the sense of the kernel.

adb root
adb shell setenforce 0    // 开SELinux:设置成模式permissive    
adb shell setenforce 1    // 关SELinux:设置成模式enforce    
XXX:/ # getenforce   // 获取当前SELinux状态
Enforcing
XXX:/ #  setenforce 0   // 临时关闭SELinux状态
XXX:/ # getenforce   	// 获取SELinux状态
Permissive
XXX:/ # setenforce 1   // 永久开启SELinux状态
XXX:/ # getenforce
Enforcing
XXX:/ #

important point:

  • This method is only applicable to userdebugthe version , and the modification will be invalid after the system restarts
  • Run in rootmode , and the terminal must not restrict setenforce, otherwise the following error will be reported:
setenforce: Couldn't set enforcing status to '0': Permission denied   //非root情况

permanently closed

The init process is the first user-level process started by the Android kernel, and SELinux is also started in the init process, and the code location is in system/core/init/init.cpp:

The calling method in the main() method SelinuxInitialize();initializes selinux, and the implementation of this method is located system/core/init/selinux.cppin:

int main(int argc, char** argv) {
    
    
	...
	SelinuxInitialize();
	...
}

init will judge whether to enable SELinux by checking whether the values ​​of security_getenforce() and selinux_is_enforcing() are consistent, and when they are inconsistent, it will set the value of security_setenforce to is_enforcing.

void SelinuxInitialize() {
    
    
    Timer t;

    LOG(INFO) << "Loading SELinux policy";
    if (!LoadPolicy()) {
    
    
        LOG(FATAL) << "Unable to load SELinux policy";
    }

    bool kernel_enforcing = (security_getenforce() == 1);
    bool is_enforcing = IsEnforcing();
    if (kernel_enforcing != is_enforcing) {
    
    
        if (security_setenforce(is_enforcing)) {
    
    
            PLOG(FATAL) << "security_setenforce(%s) failed" << (is_enforcing ? "true" : "false");
        }
    }

    if (auto result = WriteFile("/sys/fs/selinux/checkreqprot", "0"); !result) {
    
    
        LOG(FATAL) << "Unable to write to /sys/fs/selinux/checkreqprot: " << result.error();
    }

    // init's first stage can't set properties, so pass the time to the second stage.
    setenv("INIT_SELINUX_TOOK", std::to_string(t.duration().count()).c_str(), 1);
}

Returning false directly in the method in /selinux.cppthe file IsEnforcing()is to turn off the selinux permission.

bool IsEnforcing() {
    
    
    //if (ALLOW_PERMISSIVE_SELINUX) {
    
    
    //    return StatusFromCmdline() == SELINUX_ENFORCING;
    //}
    //return true;
    return false;
}

Reference:
https://source.android.google.cn/security/selinux?hl=zh-cn
https://blog.csdn.net/wq892373445/article/details/120823080
https://blog.csdn.net/ tkwxty/article/details/103938287?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2.pc_relevant_paycolumn_v3&depth_1-utm_source=distribute.pc_relevant.none- task-blog- 2%7Edefault%7ECTRLIST%7ERate-2.pc_relevant_paycolumn_v3&utm_relevant_index=5
https://www.jianshu.com/p/f1a6f248c607
https://blog.csdn.net/u012932409/article/details/114632885

Guess you like

Origin blog.csdn.net/tracydragonlxy/article/details/124150418