Bootstrap

Android源码之init.rc文件详解(SELinux详解)

Android源码之init.rc文件详解

一、引言

.rc文件是 android系统一个十分重要的文件。
其是资源文件,包括比如对话框、菜单、图标、字符串等资源信息。
使用.rc资源文件的目的是为了对程序中用到的大量的资源进行统一的管理。 本文来了解文件的规则。

二、Android中init.rc文件简单介绍

init.rc脚本是由Android中linux的第一个用户级进程init进行解析的。

init.rc 文件并不是普通的配置文件,而是由一种被称为“Android初始化语言”(Android Init Language,这里简称为AIL)的脚本写成的文件。
init.rc脚本包括了启动脚本文件,主要完成一些初级的初始化,文件系统初始化

主要是:
1)设置一些环境变量
2)创建system、sdcard、data、cache等目录
3)把一些文件系统mount到一些目录去
4)设置一些文件的用户群组、权限
5)设置一些线程参数
6)设置TCP缓存大小

该文件在ROM中是只读的,即使有了root权限,可以修改该文件也没有。因为我们在根目录看到的文件只是内存文件的镜像。也就是说,android启动后,会将init.rc文件装载到内存。而修改init.rc文件的内容实际上只是修改内存中的init.rc文件的内容。一旦重启android,init.rc文件的内容又会恢复到最初的装载。想彻底修改init.rc文件内容的唯一方式是修改Android的ROM中的内核镜像(boot.img)。

如果想要修改启动过程只需要修改init.c或者init.rc里的内容即可。

init.c与init.rc在源码中的位置分别位于如下:

1.init.c : /system/core/init
2.init.rc : /system/core/rootdir

三、文件规则

类型

主要包含了四种类型的语句:
1、Action
2、Services
Action和services显式声明了一个语句块

3、Commands
4、Options.
commands和options属于最近声明的语句块。

在第一个语句块之前 的commands和options会被忽略.

基本规则

1、在init.rc文件中一条语句通常是占据一行。
2、单词之间是通过空格符来相隔的。
3、如果需要在单词内使用空格,那么得使用转义字符""。
4、末尾的反斜杠,是换行折叠符号,应该和下一行合并成一起来处理,与C语言中的含义是一致的。
5、以#号开头的为注释。

关键字

关键字位于语句块的首部,决定了这个语句块的种类

关键字含义
Action动作
trigger触发器。或者叫做触发条件
commands命令
services服务
1、触发器(trigger)

在"动作"(action)里面的,on后面跟着的字符串是触发器(trigger),trigger是一个用于匹配某种事件类型的字符串,它将对应的Action的执行。

触发器(trigger)有几种格式:

1、最简单的一种是一个单纯的字符串。比如“on boot”。这种简单的格式可以使用命令"trigger"来触发。
2、还有一种常见的格式是"on property : <属性>=<值>“。如果属性值在运行时设成了指定的值,则"块”(action)中的命令列表就会执行。

常见的格式:

格式含义
on early-init在初始化早期阶段触发
on init在初始化阶段触发
on late-init在初始化晚期阶段触发
on boot/charger当系统启动/充电时触发
on property当属性值满足条件时触发
2、动作(Action)

动作表示了一组命令(commands)组成。动作包括一个触发器,决定了何时运行这个动作。

注意:当触发器的条件满足时,这个动作会被增加到已被运行的队列尾。假设此动作在队列中已经存在,那么它将不会运行。

on  <trigger>      ## 触发条件
    <command>      ##执行命令
    <command1>     ##可以执行多个命令
3、commands(命令)

command是action的命令列表中的命令,或者是service中的选项 onrestart 的参数命令。

命令将在所属事件发生时被一个个地执行。

常见命令:

命令功能
exec [ ]* 运行指定路径下的程序,并传递參数
export 设置全局环境參数。此參数被设置后对全部进程都有效
ifup 使指定的网络接口"上线",相当激活指定的网络接口
hostname 设置主机名
chdir 改变工作文件夹
chmod 改变指定文件的读取权限
chown 改变指定文件的拥有和组名的属性
chroot 改变进行的根文件夹
class_start 启动指定类属的全部服务,假设服务已经启动,则不再反复启动
class_stop 停止指定类属的全部服务
domainname 设置域名
insmod 安装模块到指定路径
mkdir [mode] [owner] [group] 用指定參数创建一个文件夹,在默认情况下,创建的文件夹读取权限为755.username为root,组名为root
mount [ ]* 类似于linux的mount指令
setprop 设置属性及相应的值
setrlimit 设置资源的rlimit(资源限制)
start 假设指定的服务未启动,则启动它
stop 假设指定的服务当前正在执行,则停止它
symlink 创建一个符号链接
sysclktz <mins_west_of_gmt>设置系统基准时间
write \ [ ]* 往指定的文件写字符串
4、服务(services)

服务是指那些须要在系统初始化时就启动或退出时自己主动重新启动的程序.

service <name><pathname> [ <argument> ]*
    <option>
    <option>

解释一下各个参数:

参数含义
表示此服务的名称
此服务所在路径因为是可执行文件,所以一定有存储路径
[ ]*启动服务所带的参数
对此服务的约束选项
on property:sys.pdf.on=true
    start pdf_service

service pdf_service /vendor/bin/tutorial_pdf.sh
    disabled
    seclabel u:r:shell:s0
    oneshot

设置一个pdf_service服务对应可执行文件 tutorial_pdf.sh脚本 。设置为不自动启动disabled,设置为退出之后不重启oneshot。 seclabel u:r:shell:s0后文详解。

当属性 sys.pdf.on=true时,就会启动pdf_service这个服务

SystemProperties.set("sys.pdf.on", String.valueOf(true));

或者

SystemProperties.set("ctl.start","pdf_service");
5、选项(option)

options是Service的修订项。它们决定一个服务何时以及如何运行。

选项描述
critical据设备相关的关键服务,如果在4分钟内,此服务重复启动了4次,那么设备将会重启进入还原模式
disabled服务不会自动运行,必须显式地通过服务器来启动
setenv设置环境变量
socket [ [ ] ]在/dev/socket/下创建一个unix domain的socket,并传递创建的文件描述符fd给服务进程.其中type必须为dgram或stream,seqpacket
user在执行此服务之前先切换用户名。当前默认为root
group [ ]*类似于user,切换组名
oneshot当此服务退出时不会自动重启
class给服务指定一个类属,这样方便操作多个服务同时启动或停止.默认情况下为default
onrestart当服务重启时执行一条指令

seclabel u:r:shell:s0 详解

其中的seclabel指令用于设置SELinux(Security-Enhanced Linux)的安全上下文。下面,我将详细讲解seclabel u:r:shell:s0这条指令。

SELinux 简介

SELinux(Security-Enhanced Linux)是Linux内核的一个模块,用于提供强制访问控制安全策略。在Android系统中,SELinux用于控制不同进程之间的访问权限,以增强系统的安全性。SELinux有两种主要模式:Enforcing和Permissive。Enforcing模式下,SELinux会严格实施安全策略,如果进程违反了安全策略,将会被拒绝访问并可能终止运行。而Permissive模式下,虽然也会记录违反安全策略的事件,但不会阻止进程的运行。

通过ADB命令,用户可以查看和切换SELinux的模式。具体来说:

  • 查看SELinux状态‌:使用命令adb shell getenforce可以查看当前SELinux的状态,输出结果可以是Enforcing、Permissive。
  • 切换SELinux模式‌:
    • 切换到Permissive模式(相当于关闭SELinux的部分功能):使用命令adb shell setenforce 0可以将SELinux模式设置为Permissive模式。
    • 切换到Enforcing模式(恢复SELinux的正常功能):使用命令adb shell setenforce 1可以将SELinux模式设置回Enforcing模式。

这些操作对于调试和解决Android系统安全问题非常有用。例如,在开发过程中,开发者可能会暂时将SELinux设置为Permissive模式以便进行调试,然后在完成后恢复为Enforcing模式以确保系统的安全性

SELinux是一种安全模块,它通过强制访问控制策略来提高Linux系统的安全性。在SELinux中,所有的进程和文件都被分配了安全标签,这些标签定义了它们的安全属性和访问权限。

安全上下文(Security Context)

安全上下文是一个字符串,用于描述SELinux策略下的进程或文件的安全属性。它通常包含以下部分:

  • 用户(User:标识进程或文件所属的用户。
  • 角色(Role):标识进程或文件所属的角色,角色是基于用户的更细粒度的访问控制。
  • 类型(Type):标识进程或文件的类型,用于控制访问权限。
  • 安全级别(Sensitivity Level):标识进程或文件的安全级别,用于实现多级安全(MLS)策略。

seclabel u:r:shell:s0

  • u:代表用户(User)标识符。
  • r:代表角色(Role)标识符。
  • shell:是用户和角色的名称,表示这个进程或文件属于shell用户和角色。在SELinux中,shell通常是一个预定义的用户和角色,用于运行shell进程或与之相关的进程。
  • s0:是SELinux的安全级别(Sensitivity Level),s0是最低的安全级别。在多级安全策略中,s0通常用于普通进程和文件。

seclabel u:r:shell:s0这条指令的作用是将某个进程或文件的安全上下文设置为u:r:shell:s0。这意味着:

该进程或文件将以shell用户和角色的身份运行。
它的安全级别是s0,即最低的安全级别。
SELinux策略将根据这个安全上下文来控制该进程或文件的访问权限。

这样的设置有助于限制进程或文件的访问权限,防止它们访问或修改不应该访问或修改的资源,从而提高系统的安全性。

如果对你有帮助,就一键三连呗(关注+点赞+收藏),我会持续更新更多干货~~

;