一、问题背景设备需要在 Android 启动完成后自动设置以太网 eth0 的 MAC 地址。MAC 地址和写入标志通过 app 设置到系统属性- persist.etherinte.mac - MAC 地址- persist.etherintel.mac.write - 写入标志二、遇到的问题1. 子进程权限丢失Android init 启动的服务在创建子进程时默认不继承父进程的 Linux capability 权限。NET_ADMIN、NET_RAW 等网络权限无法传递给 shell 脚本或子进程。2. SELinux 域转换失败init 启动服务时需要正确的 SELinux domain transition。服务进程必须有自己的 SELinux 类型定义否则被拒绝访问。3. neverallow 规则限制Android SELinux 策略中有严格的 neverallow 规则不允许普通 domain 使用 entrypoint 权限必须通过 init_daemon_domain() 宏处理。三、最终解决方案采用 init service C 程序 SELinux 策略 的完整方案1. C 程序 (setaddressmac.c)单进程、无 fork直接使用 ioctl 设置 MAC 地址读取 Android 系统属性获取 MAC。2. init.rc 配置service setmac_service /system/bin/setmacclass mainuser rootgroup rootcapabilities NET_ADMIN NET_RAWseclabel u:r:vendor_init:s0disabledon property:sys.boot_completed1start setmac_service关键点- capabilities NET_ADMIN NET_RAW - 授予网络操作权限- seclabel u:r:vendor_init:s0 - 解决 SELinux 域转换问题- disabled start 触发 - 延迟到 boot_completed 时执行3. SELinux 策略 (setmac.te)type setmac, domain;type setmac_exec, exec_type, file_type, system_file_type;allow init setmac_exec:file { getattr open read execute map };allow setmac self:capability { net_admin net_raw };4. 文件标签 (file_contexts)/system/bin/setmac u:object_r:setmac_exec:s0四、修改文件清单┌───────────────────────────────┬───────────────────────────────────────┐│ 文件路径 │ 作用 │├───────────────────────────────┼───────────────────────────────────────┤│ init.rk3562.rc │ service 定义和 boot_completed trigger │├───────────────────────────────┼───────────────────────────────────────┤│ sepolicy_vendor/setmac.te │ SELinux 权限规则 │├───────────────────────────────┼───────────────────────────────────────┤│ sepolicy_vendor/file_contexts │ setmac 二进制文件标签 │└───────────────────────────────┴───────────────────────────────────────┘五、验证结果# 服务正常启动init: Service setmac_service (pid 1970) exited with status 0# MAC 地址正确设置ip link show eth0 | grep etherlink/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff# 网络正常连接DHCP 获取 IP: 192.168.66.104Ethernet CONNECTED, validation passed六、关键经验1. 不用 shell 脚本 - shell 子进程会丢失 capability 权限2. C 程序直接操作 - 单进程持有权限无子进程问题3. seclabel 指定 vendor_init - 解决 SELinux 域转换问题4. capabilities 直接授予 - init.rc 中的 capabilities 直接绑定到进程5. 注意 neverallow 规则 - 不要在 te 文件中添加会被 neverallow 阻止的权限