241 lines
8.3 KiB
Markdown
241 lines
8.3 KiB
Markdown
# Android 开发简明实用技术
|
||
|
||
## 1.常用命令
|
||
|
||
### 1.1.Build 命令
|
||
|
||
```bash
|
||
make -j<n> | tee mout.log
|
||
# 快速生成镜像
|
||
make bootimage
|
||
make systemimage
|
||
make vendor
|
||
# 更新 API
|
||
make update-api
|
||
# 生成可发布的 SDK
|
||
make sdk
|
||
# 重新生成 system 镜像
|
||
make snod
|
||
# 重新生成 vendor 镜像
|
||
make vnod
|
||
# 重新生成 product 镜像
|
||
make pnod
|
||
# 清除 out 目录下对应板文件夹中的内容
|
||
make installclean
|
||
```
|
||
|
||
### 1.2.ADB 命令
|
||
|
||
```bash
|
||
adb root
|
||
# 关闭在调试环境下的 dm-verity 检查,允许对调试系统执行 adb remount 操作,重启后生效
|
||
adb disable-verity
|
||
adb remount
|
||
adb shell
|
||
adb kill-server
|
||
```
|
||
|
||
### 1.3.Display 信息
|
||
|
||
```bash
|
||
dumpsys display
|
||
```
|
||
|
||
### 1.4.Input 信息
|
||
|
||
```bash
|
||
dumpsys input
|
||
```
|
||
|
||
## 2.Bootargs
|
||
|
||
```ini
|
||
# 设置 SELinux 为强制模式,代表 SELinux 运作中,且会执行实际的限制
|
||
androidboot.selinux=enforcing
|
||
# 设置 SELinux 为宽容模式,代表 SELinux 运作中,但只会记录警告讯息并,不执行实际的限制
|
||
androidboot.selinux=permissive
|
||
# 设置 SELinux 为关闭模式,代表 SELinux 不会实际运作
|
||
androidboot.selinux=disabled
|
||
```
|
||
|
||
## 3.自动运行服务
|
||
|
||
首先在该程序的目录下创建并编写 demo init rc 文件,参考模板如下:
|
||
|
||
```rc
|
||
service <service name> /path/to/demo
|
||
class <class>
|
||
user <user>
|
||
group <group>
|
||
```
|
||
|
||
class:指所在的分类,主要有 core 等。
|
||
|
||
user 和 group 指以该 user 和 group 运行程序。
|
||
|
||
之后在该程序的 Android.mk 文件中增加:
|
||
|
||
```mk
|
||
LOCAL_INIT_RC := <demo init rc file>
|
||
```
|
||
|
||
或在 Android.bp 文件中增加:
|
||
|
||
```json
|
||
init_rc: ["<demo init rc file>"]
|
||
```
|
||
|
||
## 4.SEAndroid
|
||
|
||
SEAndroid 是在 Android 系统中基于 SELinux 推出的强制访问控制模型,来完善自主访问模型中只要取得 root 权限就可以为所欲为的情况。SEAndroid 有:强制、宽容 和 关闭三种模式。
|
||
|
||
一般可通过一下命令临时关闭 SEAndroid:
|
||
|
||
```bash
|
||
adb root
|
||
adb shell setenforce 0
|
||
```
|
||
|
||
或通过修改 Bootargs 从而在系统一启动时就设定好 SELinux 的工作模式,详见 Bootargs 部分。
|
||
|
||
SEAndroid 工作大致分为两部分:设置 Security Context 和根据 Security Context 做权限控制。如果没有为程序设置 Security Context 该程序将无法自动加载。
|
||
|
||
### 4.1.Security Context
|
||
|
||
我们可以通过 ls -Z 来查看文件的 Security Context 或者通过 ps -Z 来查看进程的 Security Context。
|
||
|
||
Security Context 由四部分组成,每一部分用冒号隔开,来看一个例子:
|
||
|
||
```bash
|
||
u:r:init:s0
|
||
u:object_r:rootfs:s0
|
||
```
|
||
|
||
* 第一部分 u 代表用户,在 SeAndroid 中只有一个用户,就是 u;
|
||
* 第二部分 r 或者 object_r 代表用户的角色,如果角色是 r 代表的是进程,如果角色是 object_r 代表的是文件;
|
||
* 第三部分 init 或者 rootfs 等,代表类型或者域,一般管文件的这部分叫类型,管进程的这部分叫域。不同的域拥有不同的权限;
|
||
* 第四部分 s0 代表安全等级,我们不用关注。
|
||
|
||
文件 Security Context 定义在 file_contexts 中:
|
||
|
||
```bash
|
||
# file_contexts
|
||
/(vendor|system/vendor)/bin/demo u:object_r:demo_exec:s0
|
||
```
|
||
|
||
### 4.2.根据 Security Context 做权限控制
|
||
|
||
主要是编写 Policy 文件了,最常见的 Policy 就是 TE 文件,TE 文件定义了程序由 init 创建后所处的域,需要的权限及权限转换规则。以下是一个 TE 文件示例:
|
||
|
||
TE 文件的主要语法格式如下:
|
||
|
||
```bash
|
||
<rule name> <source context> <target context>:<target class> <permission set>
|
||
```
|
||
|
||
其中:
|
||
|
||
* rule name:规则名称,主要有 allow、dontaudit、auditallow 和 neverallow
|
||
* source context:源类型,主要作用是用来填写一个域(domain)
|
||
* target context:目标的类型的安全上下文
|
||
* target class:类别,目标(客体)是哪种类别,主要有 file、dir、socket、SEAndroid 还有 Binder 等,在这些基础上又细分出设备字符类型(chr_file),链接文件(lnk_file)等。可以通过 ls -l 查看文件类型
|
||
* permission set:动作集
|
||
|
||
解读为:为 source context 设置一个规则,该规则是对 target context 的 class 进行 permission set 的操作,如:
|
||
|
||
```bash
|
||
allow demo sysfs:file { create open read write };
|
||
```
|
||
|
||
用中文来表述是:允许 demo 域里的进程或服务对类型为 sysfs 的类别为文件(file)进行 create、open、read 和 write 操作。
|
||
|
||
permission set 是与 class 相关联的,常见组合如下:
|
||
|
||
| Class | Permission |
|
||
|------------|------------|
|
||
| file | ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton |
|
||
| directory | add_name remove_name reparent search rmdir open audit_access execmod |
|
||
| socket | ioctl read write create getattr setattr lock relabelfrom relabelto append bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind |
|
||
| filesystem | mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget |
|
||
| process | fork transition sigchld sigkill sigstop signull signal ptrace getsched setsched getsession getpgid setpgid getcap setcap share getattr setexec setfscreate noatsecure siginh setrlimit rlimitinh dyntransition setcurrent execmem execstack execheap setkeycreate setsockcreate |
|
||
| security | compute_av compute_create compute_member check_context load_policy compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot read_policy |
|
||
| capability | chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control setfcap |
|
||
| tcp_socket | create connect name_connect lock append bind name_bind listen accept recvfrom sendto read write getattr setattr getopt setopt |
|
||
| sock_file | open read write |
|
||
| chr_file | create open read write map ioctl |
|
||
|
||
### 4.3.TE 宏
|
||
|
||
为便于编写 TE 文件,系统提供了一些 TE 宏,这些宏依然是由基本的 TE 语句组成。
|
||
|
||
常用 TE 宏如下:
|
||
|
||
* net_domain(domain):Allow a base set of permissions required for network access.
|
||
* unix_socket_connect(clientdomain, socket, serverdomain):Allow a local socket connection from clientdomain via socket to serverdomain.
|
||
|
||
### 4.4.TE 文件编写指导
|
||
|
||
通常很难知道一个程序需要哪些权限,所以一般根据经验知识先设置一些基本权限。然后通过 dmesg 和 logcat 查看该程序的 avc denied,这些 log 会指示出一些重要信息:
|
||
|
||
```bash
|
||
avc: denied { <permission> } ... scontext=<source context> tcontext=<target context> tclass=<target class> ...
|
||
```
|
||
|
||
此时根据上面的信息继续编写 TE 文件即可。
|
||
|
||
### 4.5.调试指导
|
||
|
||
为程序编写完 TE 文件后,可在 init 中自动加载该程序或使用如下命令其中程序:
|
||
|
||
```bash
|
||
setprop ctl.start <service name>
|
||
```
|
||
|
||
其中 service name 即为 init rc 文件中的服务名称。
|
||
|
||
然后可通过:
|
||
|
||
```bash
|
||
ps -A | grep <app name>
|
||
```
|
||
|
||
命令查看程序是否已经运行,如果没有运行或运行出现了问题可通过一下命令获取 log:
|
||
|
||
```bash
|
||
dmesg | grep <service name>
|
||
logcat | grep <service name>
|
||
```
|
||
|
||
### 4.6.TE 文件模板
|
||
|
||
一下根据程序所需的谋一单一功能提供了一些 TE 文件模板。
|
||
|
||
### 4.6.1.Sysfs 访问权限
|
||
|
||
```bash
|
||
type demo, domain;
|
||
type demo_exec, exec_type, vendor_file_type, file_type;
|
||
init_daemon_domain(demo)
|
||
|
||
allow demo self:capability { sys_admin };
|
||
allow demo sysfs:file { create open read write };
|
||
allow demo device:dir { create open read write };
|
||
```
|
||
|
||
### 4.6.2.Socket 访问权限
|
||
|
||
```bash
|
||
type demo, domain;
|
||
type demo_exec, exec_type, vendor_file_type, file_type;
|
||
init_daemon_domain(demo)
|
||
|
||
net_domain(demo)
|
||
unix_socket_connect(demo, netd, netd)
|
||
|
||
allow demo self:capability { net_admin net_raw net_bind_service };
|
||
allow demo device:dir { create open read write ioctl };
|
||
allow demo self:tcp_socket { create connect name_connect lock append bind name_bind listen accept recvfrom sendto read write getattr setattr getopt setopt };
|
||
allow demo port:tcp_socket { create connect name_connect lock append bind name_bind listen accept recvfrom sendto read write getattr setattr getopt setopt };
|
||
allow demo fwmarkd_socket:sock_file { write };
|
||
```
|