NotePublic/Software/Development/System/Android/Android_开发简明实用技术.md

241 lines
8.3 KiB
Markdown
Raw Normal View History

# 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 };
```