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

news2026/4/6 20:59:35
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参数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2490306.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…