当前位置: 首页 > article >正文

Android Init 系列专题【篇二:Selinux启动流程】

Android Init 系列专题【总篇深入浅出】https://blog.csdn.net/qq_27672101/article/details/144153376Android Init 系列专题【篇一fstab分区表挂载】https://blog.csdn.net/qq_27672101/article/details/146104979Android Init 系列专题【篇二Selinux启动流程】https://blog.csdn.net/qq_27672101/article/details/149076909Android Init 系列专题【篇三property_service】https://blog.csdn.net/qq_27672101/article/details/148702336Android Init 系列专题【篇四service action】https://blog.csdn.net/qq_27672101/article/details/154580471Android Init 系列专题【篇五reboot shutdown】https://blog.csdn.net/qq_27672101/article/details/154455341Android Init 系列专题【篇六native进程自定义】https://blog.csdn.net/qq_27672101/article/details/147935703Selinux其实关系到linux kernel阶段和android第一个进程init的几个阶段下面依次针对这些阶段进行剖析。先附上流程图1、linux kernel初始化selinux\par \cf0\highlight0 Shutting Down UEFI Boot Services: 3406 ms\cf1\highlight2 \par \cf0\highlight0 Start EBS [ 3407]\cf1\highlight2 \par \cf0\highlight0 BDS: LogFs sync skipped, Unsupported\cf1\highlight2 \par \cf0\highlight0 App Log Flush : 78 ms\cf1\highlight2 \par \cf0\highlight0 Exit EBS [ 3506] UEFI End\cf1\highlight2 \par \cf0\highlight0 [ 0.000000][ T0] Booting Linux on physical CPU 0x0000000000 [0x51af8014]\cf1\highlight2 \par \cf0\highlight0 [ 0.000000][ T0] Linux version 5.15.167-android13-8-g8c2d35e2e090-abHUACE.01 (build-userbuild-host) (Android (8508608, based on r450784e) clang version 14.0.7 (https://android.googlesource.com/toolchain/llvm-project 4c603efb0cca074e9238af8b4106c30add4418f6), LLD 14.0.7) #1 SMP PREEMPT Fri May 23 02:24:42 UTC 2025\cf1\highlight2 \par \cf0\highlight0 [ 0.002810][ T0] LSM: Security Framework initializing\cf1\highlight2 \par \cf0\highlight0 [ 0.002852][ T0] SELinux: Initializing.\cf1\highlight2 \par \cf0\highlight0 [ 0.002999][ T0] Mount-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)\cf1\highlight2 \par \cf0\highlight0 [ 0.003017][ T0] Mountpoint-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)\cf1\highlight2如上日志为设备上电之后启动linux kernel的流程在0.002秒的时候开始进行LSM Security进行初始化和SELinux Initializing初始化。1.1 LSM: Security Framework initializing1.2 SELinux: Initializing1.3 linux kernel是如何设置当前状态如上核心代码逻辑为selinux_enforcing_boot如果为1者设置强制模式否则设置宽容模式。这个变量的定义如下//vendor/kernel_platform/common/security/selinux/hooks.c #ifdef CONFIG_SECURITY_SELINUX_DEVELOP //如果宏CONFIG_SECURITY_SELINUX_DEVELOP被定义执行如下代码 static int selinux_enforcing_boot __initdata; //定义变量 selinux_enforcing_boot static int __init enforcing_setup(char *str) { unsigned long enforcing; //接收来自内核启动参数到enforcing通过内核启动参数来决定 selinux_enforcing_boot的值 if (!kstrtoul(str, 0, enforcing)) selinux_enforcing_boot enforcing ? 1 : 0; return 1; } __setup(enforcing, enforcing_setup); //注册启动参数处理函数当内核启动参数中有enforcingxxx时调用enforcing_setup函数 #else //如果宏CONFIG_SECURITY_SELINUX_DEVELOP未被定义宏定义 selinux_enforcing_boot 为1 #define selinux_enforcing_boot 1 #endif根据这段代码可以知道我们必须要打开linux kernel宏控CONFIG_SECURITY_SELINUX_DEVELOP才可以在linux kernel层面去关闭selinux。1.4 linux selinuxfs实现了什么第一步linux kernel在初始化阶段会主动进行系统调用__initcall执行init_sel_fs函数在此函数中注册了文件系统结构体sel_fs_typelinux kernel在挂此结构体的时候即2233行就会自动调用.init_fs_context指向的函数指针反之在销毁的时候的会自动调用.kill_sb指向的函数指针第二步最终回调到sel_filll_super函数在此函数中在selinux文件系统目录下创建不同的子文件个人不是很了解猜测上层可以通过文件操作方式去回调后面对应的结构体例如操作enforce就会指向对于的sel_enforce_ops第三步enforce的终极解密如下代码我们指向getenforce和setenforce其实就是对selinux/enforce文件进行读写操作 最终走到了如下的两个函数可以看到我们任何版本都可以进行getenforce但是如果CONFIG_SECURITY_SELINUX_DEVELOP宏没有被定义那么无法进行setenforce//vendor/kernel_platform/common/security/selinux/selinuxfs.c //enforce指定的结构体即对selinux/enforce文件进行读操作回调sel_read_enforce函数对selinux/enforce文件进行写操作回调sel_write_enforce static const struct file_operations sel_enforce_ops { .read sel_read_enforce, .write sel_write_enforce, .llseek generic_file_llseek, }; //对selinux/enforce文件进行读操作 static ssize_t sel_read_enforce(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { struct selinux_fs_info *fsi file_inode(filp)-i_sb-s_fs_info; char tmpbuf[TMPBUFLEN]; ssize_t length; length scnprintf(tmpbuf, TMPBUFLEN, %d, enforcing_enabled(fsi-state)); return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); } //对selinux/enforce文件进行写操作 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP //如果CONFIG_SECURITY_SELINUX_DEVELOP宏被定义定义sel_write_enforce函数 static ssize_t sel_write_enforce(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct selinux_fs_info *fsi file_inode(file)-i_sb-s_fs_info; struct selinux_state *state fsi-state; char *page NULL; ssize_t length; int old_value, new_value; if (count PAGE_SIZE) return -ENOMEM; if (*ppos ! 0) return -EINVAL; page memdup_user_nul(buf, count); if (IS_ERR(page)) return PTR_ERR(page); length -EINVAL; if (sscanf(page, %d, new_value) ! 1) goto out; new_value !!new_value; old_value enforcing_enabled(state); if (new_value ! old_value) { length avc_has_perm(selinux_state, current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETENFORCE, NULL); if (length) goto out; audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS, enforcing%d old_enforcing%d auid%u ses%u enabled1 old-enabled1 lsmselinux res1, new_value, old_value, from_kuid(init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); enforcing_set(state, new_value); if (new_value) avc_ss_reset(state-avc, 0); selnl_notify_setenforce(new_value); selinux_status_update_setenforce(state, new_value); if (!new_value) call_blocking_lsm_notifier(LSM_POLICY_CHANGE, NULL); selinux_ima_measure_state(state); } length count; out: kfree(page); return length; } #else //注意如果宏CONFIG_SECURITY_SELINUX_DEVELOP没有被定义此函数指针为null即无法进行设置 #define sel_write_enforce NULL #endif2、android init初始化selinux2.1 init进程FirstStageMain阶段\par \cf0\highlight0 [0.888559][ T1] Run /init as init process\cf1\highlight2\par \cf0\highlight0 [0.894425][ T1] init: init first stage started!\cf1\highlight2如上代码vendor init进程的第一阶段关键日志如上并且没有关于selinux相关的打印至于linux kernel如果启动到vendor init第一阶段和vendor init第一阶段如何启动到system init的selinux阶段参考Android Native 之 Init进程分析2.2 init进程selinux_setup阶段行 86: 06-19 12:02:09.620936 0 0 I (0)[0:swapper/0]SELinux: Initializing. 行 3636: 06-19 12:02:11.360570 1 1 E (0)[1:init]init 3: Init Selinux SetupSelinux A 行 3638: 06-19 12:02:11.368940 1 1 I (0)[1:init]init 3: Opening SELinux policy 行 3639: 06-19 12:02:11.368982 1 1 E (0)[1:init]init 3: Init Selinux SetupSelinux B 行 3642: 06-19 12:02:11.375320 1 1 I (1)[1:init]init 3: Loading APEX Sepolicy from /system/etc/selinux/apex/SEPolicy.zip 行 3643: 06-19 12:02:11.375595 1 1 E (1)[1:init]init 3: Failed to open package /system/etc/selinux/apex/SEPolicy.zip: No such file or directory 行 3644: 06-19 12:02:11.376426 1 1 E (1)[1:init]init 3: selinux root:1 行 3645: 06-19 12:02:11.376561 1 1 I (1)[1:init]init 4: Using userdebug system sepolicy /system/etc/selinux/userdebug_plat_sepolicy_cil 行 3646: 06-19 12:02:11.376651 1 1 I (1)[1:init]init 4: Compiling SELinux policy 行 4385: 06-19 12:02:14.550937 1 1 E (1)[1:init]init 4: Init Selinux SetupSelinux C 行 4386: 06-19 12:02:14.551093 1 1 E (1)[1:init]init 4: Init Selinux SetupSelinux D 行 4387: 06-19 12:02:14.551178 1 1 I (1)[1:init]init 4: Loading SELinux policy 行 4388: 06-19 12:02:14.689998 1 1 I (1)[1:init]SELinux: policy capability network_peer_controls1 行 4389: 06-19 12:02:14.690014 1 1 I (1)[1:init]SELinux: policy capability open_perms1 行 4390: 06-19 12:02:14.690019 1 1 I (1)[1:init]SELinux: policy capability extended_socket_class1 行 4391: 06-19 12:02:14.690023 1 1 I (1)[1:init]SELinux: policy capability always_check_network0 行 4392: 06-19 12:02:14.690028 1 1 I (1)[1:init]SELinux: policy capability cgroup_seclabel0 行 4393: 06-19 12:02:14.690033 1 1 I (1)[1:init]SELinux: policy capability nnp_nosuid_transition1 行 4394: 06-19 12:02:15.148882 1 1 I (0)[1:init]selinux 4: SELinux: Loaded file context from: 行 4395: 06-19 12:02:15.148908 1 1 I (0)[1:init]selinux 4: /system/etc/selinux/plat_file_contexts 行 4396: 06-19 12:02:15.149049 1 1 I (0)[1:init]selinux 3: /system_ext/etc/selinux/system_ext_file_contexts 行 4397: 06-19 12:02:15.149064 1 1 I (0)[1:init]selinux 3: /vendor/etc/selinux/vendor_file_contexts 行 4398: 06-19 12:02:15.149310 1 1 E (0)[1:init]selinux 3: SELinux: Could not stat /dev/selinux: No such file or directory. 行 4399: 06-19 12:02:15.149380 1 1 E (0)[1:init]init 3: Init Selinux SetupSelinux E SelinuxSetEnforcement 行 4400: 06-19 12:02:15.149495 1 1 E (0)[1:init]init 3: Init Selinux SelinuxSetEnforcement kernel_enforcing is 0 行 4401: 06-19 12:02:15.149519 1 1 E (0)[1:init]init 3: Init Selinux SelinuxSetEnforcement kernel_enforcing is 0 行 4402: 06-19 12:02:15.153931 1 1 E (0)[1:init]init 3: Init Selinux SetupSelinux E 行 4404: 06-19 12:02:15.338551 1 1 I (0)[1:init]selinux: SELinux: Loaded file context from: 行 4405: 06-19 12:02:15.338575 1 1 I (0)[1:init]selinux: /system/etc/selinux/plat_file_contexts 行 4406: 06-19 12:02:15.338586 1 1 I (0)[1:init]selinux: /system_ext/etc/selinux/system_ext_file_contexts 行 4407: 06-19 12:02:15.338597 1 1 I (0)[1:init]selinux: /vendor/etc/selinux/vendor_file_contexts 行 4486: 06-19 12:02:15.503784 1 1 I (0)[1:init]selinux 6: SELinux: Loaded file context from: 行 4487: 06-19 12:02:15.503797 1 1 I (0)[1:init]selinux 6: /system/etc/selinux/plat_file_contexts 行 4488: 06-19 12:02:15.503808 1 1 I (0)[1:init]selinux 6: /system_ext/etc/selinux/system_ext_file_contexts 行 4489: 06-19 12:02:15.503819 1 1 I (0)[1:init]selinux 6: /vendor/etc/selinux/vendor_file_contexts) 行 4767: 06-19 12:02:15.783488 313 313 I (1)[313:ueventd]selinux: SELinux: Loaded file context from: 行 4768: 06-19 12:02:15.783509 313 313 I (1)[313:ueventd]selinux: /system/etc/selinux/plat_file_contexts 行 4769: 06-19 12:02:15.783519 313 313 I (1)[313:ueventd]selinux: /system_ext/etc/selinux/system_ext_file_contexts 行 4770: 06-19 12:02:15.783528 313 313 I (1)[313:ueventd]selinux: /vendor/etc/selinux/vendor_file_contexts 行 5192: 06-19 12:02:17.655100 403 403 I (3)[403:servicemanager]SELinux: SELinux: Loaded service context from: 行 5193: 06-19 12:02:17.655184 403 403 I (3)[403:servicemanager]SELinux: /system/etc/selinux/plat_service_contexts 行 5194: 06-19 12:02:17.655226 403 403 I (3)[403:servicemanager]SELinux: /system_ext/etc/selinux/system_ext_service_contexts 行 5195: 06-19 12:02:17.655266 403 403 I (3)[403:servicemanager]SELinux: /vendor/etc/selinux/vendor_service_context 行 5311: 06-19 12:02:18.024645 1 1 E (1)[1:init]selinux 21: [8398][0]SELinux: Could not stat /sys/kernel/debug: No such file or directory. 行 5314: 06-19 12:02:18.037227 1 1 I (1)[1:init]selinux 5: [8402][0]SELinux: Skipping restorecon on directory(/metadata) 行 5315: 06-19 12:02:18.040521 1 1 I (2)[1:init]selinux 5: [8413][0]SELinux: Skipping restorecon on directory(/metadata/apex) 行 5608: 06-19 12:02:18.807752 1 1 I (3)[1:init]selinux 23: [9180][0]SELinux: Skipping restorecon on directory(/data/system/shutdown-checkpoints) 行 5716: 06-19 12:02:19.468904 1 1 I (0)[1:init]selinux 5: [9841][85]SELinux: Skipping restorecon on directory(/data) 行 5801: 06-19 12:02:20.321053 1 1 E (1)[1:init]selinux 21: [10654][25]SELinux: Could not stat /data/dalvik-cache/arm64: No such file or directory. 行 5802: 06-19 12:02:20.321185 1 1 E (1)[1:init]selinux 21: [10654][25]SELinux: Could not stat /data/dalvik-cache/riscv64: No such file or directory. 行 5803: 06-19 12:02:20.321304 1 1 E (1)[1:init]selinux 5: [10654][25]SELinux: Could not stat /data/dalvik-cache/x86: No such file or directory. 行 5804: 06-19 12:02:20.321393 1 1 E (1)[1:init]selinux 5: [10654][25]SELinux: Could not stat /data/dalvik-cache/x86_64: No such file or directory. 行 5811: 06-19 12:02:20.328629 1 1 I (1)[1:init]selinux 5: [10701][0]SELinux: Skipping restorecon on directory(/data/misc/apexdata/com.android.wifi) 行 10868: 06-19 12:02:43.491842 2125 2125 I (0)[2125:init]selinux 5: SELinux: Skipping restorecon on directory(/data/vendor_ce/0) 行 10872: 06-19 12:02:43.510338 2127 2127 I (3)[2127:init]selinux 5: SELinux: Skipping restorecon on directory(/data/misc_ce/0) 行 10959: 06-19 12:02:43.772735 1 1 E (3)[1:init]selinux 5: [34144][0]SELinux: Could not get canonical path for /sys/kernel/debug/tracing/instances/wifi restorecon: No such file or directory. 行 10981: 06-19 12:02:43.989663 1 1 I (1)[1:init]selinux 5: [34359][0]SELinux: Skipping restorecon on directory(/data/misc_ce/0/apexdata/com.android.wifi)如上日志对应如下源码// The SELinux setup process is carefully orchestrated around snapuserd. Policy must be loaded off dynamic partitions, and during an OTA, those partitions cannot be read without snapuserd. // But, with kernel-privileged snapuserd running, loading the policy will immediately trigger audits. We use a five-step process to address this: // (1) Read the policy into a string, with snapuserd running. // (2) Rewrite the snapshot device-mapper tables, to generate new dm-user devices and to flush I/O. // (3) Kill snapuserd, which no longer has any dm-user devices to attach to. // (4) Load the sepolicy and issue critical restorecons in /dev, carefully avoiding anything that would read from /system. // (5) Re-launch snapuserd and attach it to the dm-user devices from step (2). // After this sequence, it is safe to enable enforcing mode and continue booting. int SetupSelinux(char** argv) { //第一步初始化阶段 SetStdioToDevNull(argv); //重定向标准IO到/dev/null InitKernelLogging(argv); //初始化内核日志系统 LOG(ERROR) Init Selinux SetupSelinux A; if (REBOOT_BOOTLOADER_ON_PANIC) InstallRebootSignalHandlers();//安装崩溃重启处理器 boot_clock::time_point start_time boot_clock::now(); MountMissingSystemPartitions(); //挂载缺失的系统分区 SelinuxSetupKernelLogging(); //第二步策略预加载阶段 LOG(INFO) Opening SELinux policy; LOG(ERROR) Init Selinux SetupSelinux B; PrepareApexSepolicy();//准备APEX模块的SELinux策略 // Read the policy before potentially killing snapuserd. std::string policy; ReadPolicy(policy); //将策略文件读入内存字符串对应五步法的第1步 CleanupApexSepolicy();//清理临时APEX策略 //第三步snapuserd过渡阶段 LOG(ERROR) Init Selinux SetupSelinux C; auto snapuserd_helper SnapuserdSelinuxHelper::CreateIfNeeded();//创建snapuserd辅助对象 if (snapuserd_helper) { // Kill the old snapused to avoid audit messages. After this we cannot read from /system (or other dynamic partitions) until we call FinishTransition(). snapuserd_helper-StartTransition();// 终止旧snapuserd并重写设备映射表对应五步法的第2-3步 } //第四步策略生效阶段 LOG(ERROR) Init Selinux SetupSelinux D; LoadSelinuxPolicy(policy); //加载内存中的策略对应五步法的第4步 if (snapuserd_helper) { // Before enforcing, finish the pending snapuserd transition. snapuserd_helper-FinishTransition(); //重启snapuserd并绑定新设备对应五步法的第5步 snapuserd_helper nullptr; } //第五步强制模式激活阶段 // This restorecon is intentionally done before SelinuxSetEnforcement because the permissions needed to transition files from tmpfs to *_contexts_file context should not be granted to any process after selinux is set into enforcing mode. //安全上下文预恢复阶段释说明restorecon必须在强制模式前执行因为从tmpfs转换到*_contexts_file上下文需要特殊权限这些权限在强制模式下不应被授予。递归修复SELinux策略目录的安全上下文失败则触发致命错误/dev/selinux/包含策略文件和运行时状态其上下文正确性直接影响SELinux功能。 if (selinux_android_restorecon(/dev/selinux/, SELINUX_ANDROID_RESTORECON_RECURSE) -1) { PLOG(FATAL) restorecon failed of /dev/selinux failed; } LOG(ERROR) Init Selinux SetupSelinux E SelinuxSetEnforcement; //将SELinux从宽容模式切换为强制模式此后所有进程必须严格遵循策略规则 SelinuxSetEnforcement(); // Were in the kernel domain and want to transition to the init domain. File systems that store SELabels in their xattrs, such as ext4 do not need an explicit restorecon here, but other file systems do. In particular, this is needed for ramdisks such as the recovery image for A/B devices. //注释解释某些文件系统(如ramdisk)需要显式恢复上下文而ext4等支持xattr的文件系统可自动处理。对/system/bin/init执行非递归的上下文修复(0表示不递归)确保init进程域转换正确该操作特别针对A/B设备的恢复镜像场景。 if (selinux_android_restorecon(/system/bin/init, 0) -1) { PLOG(FATAL) restorecon failed of /system/bin/init failed; } //第六步进入init进程的第二阶段 LOG(ERROR) Init Selinux SetupSelinux F; setenv(kEnvSelinuxStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(), 1);//设置环境变量主要是更新时间戳 const char* path /system/bin/init; const char* args[] {path, second_stage, nullptr}; execv(path, const_castchar**(args)); //启动system/bin/init并传递second_stage参数 // execv() only returns if an error happened, in which case we panic and never return from this function. PLOG(FATAL) execv(\ path \) failed; return 1; }2.3 init进程如何激活selinux模式//system/system/core/init/selinux.cpp void SelinuxSetEnforcement() { bool kernel_enforcing (security_getenforce() 1); //获取kernel的selinux状态 bool is_enforcing IsEnforcing(); //获取init的selinux状态 LOG(ERROR) Init Selinux SelinuxSetEnforcement kernel_enforcing is kernel_enforcing; LOG(ERROR) Init Selinux SelinuxSetEnforcement kernel_enforcing is is_enforcing; //如果kernel和init的selinux状态不一致 if (kernel_enforcing ! is_enforcing) { //设置selinux状态 if (security_setenforce(is_enforcing)) { PLOG(FATAL) security_setenforce( (is_enforcing ? true : false) ) failed; } } if (auto result WriteFile(/sys/fs/selinux/checkreqprot, 0); !result.ok()) { LOG(FATAL) Unable to write to /sys/fs/selinux/checkreqprot: result.error(); } }SelinuxSetEnforcement函数的逻辑非常重要这里获取了init进程的selinux配置在获取了kernel层的selinux配置如果两者不一致那么就通过security_setenforce去设置kernel层的selinux配置如果设置失败打印失败日志。为什么要做这样的判断因为各种渠道更改selinux状态最后都体现在init进程这里但是实际生效的控制还得是kernel层因此上层改了状态之后需要同步到kernel层更新状态。1) kernel的selinux状态如何获取根据如上逻辑kernel的selinux状态是调用security_getenforce函数如下代码//external/selinux/libselinux/src/getenforce.c int security_getenforce(void) { int fd, ret, enforce 0; char path[PATH_MAX]; char buf[20]; if (!selinux_mnt) { errno ENOENT; return -1; } //流程1打开设备节点 snprintf(path, sizeof path, %s/enforce, selinux_mnt); fd open(path, O_RDONLY | O_CLOEXEC); if (fd 0) return -1; memset(buf, 0, sizeof buf); //流程2读取设备节点数据 ret read(fd, buf, sizeof buf - 1); close(fd); if (ret 0) return -1; if (sscanf(buf, %d, enforce) ! 1) return -1; return !!enforce; }可以清晰的看到android init进程通过设备文件selinux/enforce和linux kernel进行交互。详细可以回到本文第一章《enforce的终极解密》。A 疑问一adb shell setenforce/getenforce命令的底层逻辑setenfoce和getenforce命令最后都是调用了如下两个函数通过selinux/enforce文件去设置linux kernel层去设置状态2init进程的selinux状态如何获取根据如上逻辑init进程是调用IsEnforcing函数来确定init这边应该设置宽容模式还是强制模式改函数其实做了一些扩展如下代码//定义枚举表示当前selinux状态宽容模式、强制模式 enum EnforcingStatus { SELINUX_PERMISSIVE, SELINUX_ENFORCING }; //通过属性来设置当前selinux状态 EnforcingStatus StatusFromProperty() { //默认强制模式 EnforcingStatus status SELINUX_ENFORCING; //遍历kernel传递上来的参数 ImportKernelCmdline([](const std::string key, const std::string value) { //如果找到键值对androidboot.selinuxpermissive表示设置selinux状态为宽容模式 if (key androidboot.selinux value permissive) { status SELINUX_PERMISSIVE; LOG(ERROR) Init Selinux StatusFromProperty A set status is permissive; } }); //如果kernel参数没有找到宽容模式的设置继续在ImportBootconfig中查找 if (status SELINUX_ENFORCING) { ImportBootconfig([](const std::string key, const std::string value) { //如果找到键值对androidboot.selinuxpermissive表示设置selinux状态为宽容模式 if (key androidboot.selinux value permissive) { status SELINUX_PERMISSIVE; LOG(ERROR) Init Selinux StatusFromProperty B set status is permissive; } }); } LOG(ERROR) Init Selinux StatusFromProperty C status is status; return status; } bool IsEnforcing() { //如果宏开启进入判断注意在init/Android.bp中user版本此宏被设置为0debug版本此宏被设置为1 if (ALLOW_PERMISSIVE_SELINUX) { //如果是debug版本androidboot.selinuxpermissive满足那么返回false表示设置为宽容模式 return StatusFromProperty() SELINUX_ENFORCING; } //如果是user版本默认返回true表示设置为强制模式 return true; }可以进行如下总结默认情况下init进程设置selinux模式为强制模式IsEnforcing函数默认返回true特殊情况下init进程提供方式可以改变selinux模式只要编译指定宏控ALLOW_PERMISSIVE_SELINUX即可改策略ALLOW_PERMISSIVE_SELINUX宏控配置就通过StatusFromProperty函数来获取需要设置的selinux模式该函数从启动参数和启动配置中获取A 疑问一init如何从启动命令/启动配置获取selinux状态B 疑问二ALLOW_PERMISSIVE_SELINUX宏控是如何被设置4、案例之user版本在init selinux中强制宽容模式无法开机参考Android 关闭SE权限后编译user版本无法开机开机直接进入FastBoot模式文档在init selinux.cpp的直接强制返回false会使user版本进入fastboot模式需要配置CONFIG_SECURITY_SELINUX_DEVELOP宏根据如上分析要同时满足kernelCONFIG_SECURITY_SELINUX_DEVELOPy宏控配置和selinux.cpp ALLOW_PERMISSIVE_SELINUX1宏控配置和androidboot.selinuxpermissive即可。当然不需要三个条件都满足后面两个条件可以合并所以如下改法步骤一kernel配置CONFIG_SECURITY_SELINUX_DEVELOPy注意在高通A14 发现多个项目上此宏默认是开启的有些不可思议步骤二init进程强制permissive模式除了上述暴力强制返回false之外还可以温柔一点按照selinux.cpp原有判断逻辑配置kernel cmd参数

相关文章:

Android Init 系列专题【篇二:Selinux启动流程】

Android Init 系列专题【总篇:深入浅出】https://blog.csdn.net/qq_27672101/article/details/144153376 Android Init 系列专题【篇一:fstab分区表挂载】https://blog.csdn.net/qq_27672101/article/details/146104979 Android Init 系列专题【篇二&a…...

用JSP+Servlet实现图书管理系统:从登录验证到CRUD完整流程

基于JSPServlet的图书管理系统实战开发指南 在当今企业级应用开发中,Java Web技术栈依然是构建稳健后台系统的首选方案之一。本文将带您从零开始,通过开发一个功能完整的图书管理系统,深入掌握JSPServlet的核心技术组合。不同于简单的CRUD示例…...

计算机毕业设计:Python智慧出行数据分析系统 Django框架 可视化 数据大屏 数据分析 大数据 机器学习 深度学习(建议收藏)✅

1、项目介绍 技术栈:Python语言、Django框架、ECharts可视化库、数据大屏技术。 功能模块: 首页模块数据大屏模块数据分析模块数据查看模块登录模块后台管理模块订单管理模块用户管理模块 项目介绍:滴滴出行数据分析平台基于Django框架开发&a…...

计算机毕业设计:Python城市出行数据驾驶舱与预测系统 Django框架 可视化 数据分析 PyEcharts 交通 深度学习(建议收藏)✅

1、项目介绍 技术栈:Python 3.x、Django 5.0.7、MySQL、HTML5CSS3JavaScript、ECharts、SimpleUI、Pandas、PyEcharts、K-Means聚类、随机森林分类。 功能模块: 用户管理模块数据可视化模块分析预测模块数据管理模块后台管理模块系统基础模块 项目介绍&a…...

nbdev终极指南:如何用Jupyter Notebook创建专业级软件项目

nbdev终极指南:如何用Jupyter Notebook创建专业级软件项目 【免费下载链接】nbdev Create delightful software with Jupyter Notebooks 项目地址: https://gitcode.com/gh_mirrors/nb/nbdev nbdev是一个革命性的笔记本驱动开发平台,让开发者能够…...

Lisk SDK安全最佳实践:保护区块链应用免受攻击的10个技巧

Lisk SDK安全最佳实践:保护区块链应用免受攻击的10个技巧 【免费下载链接】lisk-sdk 🔩 Lisk software development kit 项目地址: https://gitcode.com/gh_mirrors/li/lisk-sdk Lisk SDK是一款强大的区块链应用开发工具包,专为构建安…...

obsidian-skills投资者管理:高效管理投资者关系的终极指南

obsidian-skills投资者管理:高效管理投资者关系的终极指南 【免费下载链接】obsidian-skills Agent skills for Obsidian. Teach your agent to use Markdown, Bases, JSON Canvas, and use the CLI. 项目地址: https://gitcode.com/GitHub_Trending/ob/obsidian-…...

Oh-My-Posh 多会话管理终极指南:在不同终端中保持一致的完美体验

Oh-My-Posh 多会话管理终极指南:在不同终端中保持一致的完美体验 【免费下载链接】oh-my-posh2 A prompt theming engine for Powershell 项目地址: https://gitcode.com/gh_mirrors/oh/oh-my-posh2 Oh-My-Posh 是一款强大的 PowerShell 提示符主题引擎&…...

IDMPhotoBrowser:iOS开发者的终极照片浏览器解决方案

IDMPhotoBrowser:iOS开发者的终极照片浏览器解决方案 【免费下载链接】IDMPhotoBrowser Photo Browser / Viewer inspired by Facebooks and Tweetbots with ARC support, swipe-to-dismiss, image progress and more 项目地址: https://gitcode.com/gh_mirrors/i…...

Infect安全风险评估:了解病毒对Android设备的实际影响

Infect安全风险评估:了解病毒对Android设备的实际影响 【免费下载链接】infect Infect Any Android Device With Virus From Link In Termux 项目地址: https://gitcode.com/gh_mirrors/in/infect 在当今移动设备安全领域,了解恶意软件的实际影响…...

如何快速上手libcds:10分钟掌握并发数据结构基础

如何快速上手libcds:10分钟掌握并发数据结构基础 【免费下载链接】libcds A C library of Concurrent Data Structures 项目地址: https://gitcode.com/gh_mirrors/li/libcds libcds是一个强大的C并发数据结构库,专为多线程环境设计,提…...

Globe.gl性能优化秘籍:如何高效处理大规模卫星数据可视化

Globe.gl性能优化秘籍:如何高效处理大规模卫星数据可视化 【免费下载链接】globe.gl UI component for Globe Data Visualization using ThreeJS/WebGL 项目地址: https://gitcode.com/gh_mirrors/gl/globe.gl Globe.gl是一个基于ThreeJS/WebGL的3D地球数据可…...

Windows Defender Remover:系统安全组件深度管理完全指南

Windows Defender Remover:系统安全组件深度管理完全指南 【免费下载链接】windows-defender-remover A tool which is uses to remove Windows Defender in Windows 8.x, Windows 10 (every version) and Windows 11. 项目地址: https://gitcode.com/gh_mirrors/…...

高级特性:探索PyTorch/XLA的Pallas内核和Flash Attention实现

高级特性:探索PyTorch/XLA的Pallas内核和Flash Attention实现 【免费下载链接】xla Enabling PyTorch on XLA Devices (e.g. Google TPU) 项目地址: https://gitcode.com/gh_mirrors/xla/xla PyTorch/XLA是一个强大的开源项目,它使PyTorch能够在X…...

效率提升利器:快马一键生成网络配置脚本与故障排查模拟环境

最近在准备计算机三级网络技术考试,发现手动搭建实验环境和编写配置脚本特别耗时。为了提升学习效率,我用InsCode(快马)平台开发了一个网络技术练习工具,分享下实现思路和使用体验。 核心功能设计 这个工具主要解决三个痛点:配置脚…...

深入剖析watchdog机制:从soft lockup到Hard LOCKUP的检测与应对

1. 什么是watchdog机制? 想象一下你养了一只忠诚的狗狗,它的任务就是定时检查你是否还活着。如果你长时间不动,它就会叫醒你或者采取其他措施。Linux内核中的watchdog机制就是这样一个"看门狗",它的职责是监控系统是否正…...

终极实战指南:Godot PCK解包器深度解析与高效资源提取

终极实战指南:Godot PCK解包器深度解析与高效资源提取 【免费下载链接】godot-unpacker godot .pck unpacker 项目地址: https://gitcode.com/gh_mirrors/go/godot-unpacker 在游戏开发与逆向工程领域,Godot引擎的PCK文件格式一直是技术爱好者关注…...

java新手福音:免下载jdk1.8,在快马平台写出你的第一个程序

作为一个刚接触Java的新手,最头疼的就是环境配置了。记得我第一次学Java时,光是下载JDK、配置环境变量就折腾了大半天,还没开始写代码就已经被劝退了一半。直到发现了InsCode(快马)平台,才发现原来入门Java可以这么简单。 零配置开…...

闲置U盘秒变神器!Windows 11密码重置盘制作保姆级教程(含32/64位系统差异说明)

闲置U盘秒变系统急救神器:Windows 11密码重置盘全流程精解 那个抽屉角落积灰的旧U盘,可能比你想象中更有价值。当Windows 11的登录界面无情拒绝你输入的密码时,一个预先制作的密码重置盘就是打开数字大门的备用钥匙。不同于网上流传的简易教程…...

jsTree终极问题排查指南:10个开发者必须掌握的实用技巧

jsTree终极问题排查指南:10个开发者必须掌握的实用技巧 【免费下载链接】jstree jquery tree plugin 项目地址: https://gitcode.com/gh_mirrors/js/jstree jsTree是一款功能强大的jQuery树形插件,广泛应用于Web开发中构建交互式树形结构。本文将…...

终极指南:如何使用snabbt.js创建惊艳的Web动画效果

终极指南:如何使用snabbt.js创建惊艳的Web动画效果 【免费下载链接】snabbt.js Fast animations with javascript and CSS transforms 项目地址: https://gitcode.com/gh_mirrors/sn/snabbt.js 在当今的Web开发领域,snabbt.js作为一款极简主义的J…...

Windows 11上运行Android应用的3大核心优势:WSA完全指南

Windows 11上运行Android应用的3大核心优势:WSA完全指南 【免费下载链接】WSA Developer-related issues and feature requests for Windows Subsystem for Android 项目地址: https://gitcode.com/gh_mirrors/ws/WSA 想在Windows电脑上直接使用你最喜欢的An…...

Koa2调试终极指南:10个高效定位代码问题的技巧

Koa2调试终极指南:10个高效定位代码问题的技巧 【免费下载链接】koa2-note 《Koa2进阶学习笔记》已完结🎄🎄🎄 项目地址: https://gitcode.com/gh_mirrors/ko/koa2-note GitHub 加速计划 / ko / koa2-note 项目中的《Koa2进…...

Keil MDK调试时Watch窗口变量不刷新?别急,这3个设置项你检查了吗?

Keil MDK调试时Watch窗口变量不刷新?这3个关键设置项详解 调试嵌入式系统时,Watch窗口就像开发者的"第三只眼",能实时洞察程序运行状态。但当你发现变量值像被冻住一样纹丝不动时,那种抓狂的感觉我太熟悉了——三年前我…...

PlugY:重新定义暗黑破坏神2单机体验的技术突破

PlugY:重新定义暗黑破坏神2单机体验的技术突破 【免费下载链接】PlugY PlugY, The Survival Kit - Plug-in for Diablo II Lord of Destruction 项目地址: https://gitcode.com/gh_mirrors/pl/PlugY 暗黑破坏神2作为ARPG游戏的里程碑之作,其单机模…...

Habitat入门教程:如何构建你的第一个自动化应用包

Habitat入门教程:如何构建你的第一个自动化应用包 【免费下载链接】habitat Modern applications with built-in automation 项目地址: https://gitcode.com/gh_mirrors/hab/habitat Habitat是一个现代化的应用自动化平台,它通过内置的自动化功能…...

家庭物联网中枢:OpenClaw+Phi-3-vision实现智能家居视觉控制

家庭物联网中枢:OpenClawPhi-3-vision实现智能家居视觉控制 1. 为什么需要本地化的智能家居方案 去年装修新房时,我面临一个两难选择:要么使用成熟的云端智能家居平台,牺牲部分隐私;要么完全手动控制,失去…...

FuzzingPaper项目代码实现原理:如何高效管理海量学术论文

FuzzingPaper项目代码实现原理:如何高效管理海量学术论文 【免费下载链接】FuzzingPaper Recent Fuzzing Paper 项目地址: https://gitcode.com/gh_mirrors/fu/FuzzingPaper FuzzingPaper是一个专注于模糊测试(Fuzzing)领域学术论文管…...

jsTree完整生态系统指南:插件、主题和工具全解析

jsTree完整生态系统指南:插件、主题和工具全解析 【免费下载链接】jstree jquery tree plugin 项目地址: https://gitcode.com/gh_mirrors/js/jstree jsTree是一个功能强大的jQuery树形插件,专为现代Web应用设计,提供了完整的树形结构…...

终极指南:如何在Koa2中构建高性能GraphQL API

终极指南:如何在Koa2中构建高性能GraphQL API 【免费下载链接】koa2-note 《Koa2进阶学习笔记》已完结🎄🎄🎄 项目地址: https://gitcode.com/gh_mirrors/ko/koa2-note Koa2作为一款轻量级Node.js框架,凭借其优…...