文章目录
- LEETCODE
- 拉取代码
- git branch命令
- Camera分析LOG开关
- 查找包含字符串的文件
- 查询当前磁盘容量
- 编译命令
- 关闭开机向导
- 替换系统文件
- 动态开启framework日志
- 替换库文件调试脚本
- 按时间命名文件
- 修改编译的虚拟内存
- dump数据
- 堆栈打印
- 追踪出错地址
- Ubuntu下安装最新OpenJdk1.8
- Fastboot
- Ubuntu上ADB devices找不到设备
- ubuntu配置adb环境变量
- Jack故障处理
- 拉取多媒体库
- git下git diff用法
- 根据进程名字杀死进程
- 虚拟机挂载虚拟磁盘
- 修改用户名和邮箱
- 生成秘钥
- 计算函数执行时间
- 如何打开pr_debug调试信息
- 查看 读写SD卡权限
- C++替换字符串
- 读取二进制文件
- CTS命令
- Init.rc妙用及语法说明
- HIDL 接口
- Android SELinux avc dennied权限问题解决方法
- 新设备节点增加访问权限
- 新目录增加访问权限
- 新建.te安全策略文件方法
- 如何配置策略
LEETCODE
hasmap
unordered_map<int, int> map
int index, value;
map.find(value) != map.end()
map[index] = value;
vector
vector<int> result;
int index, value;
result.push_back(value);
reverse(result.begin(),result.end());
stack
stack<int> stack;
int index, value;
stack.empty();
stack.push(value);
stack.top();
stack.pop();
拉取代码
单独下载一个project
git clone http://myrepo.xxx.com/project/.git ,这样在当前目录下得到一个project子目录
例如下载alps/frameworks/av
<project name="mtk_N/alps/external/skia" path="alps/external/skia" />
对应的命令为:
git clone ssh://xxxx@myrepo.xxx.com:29418/mtk_N/alps/external/skia/.git alps/external/skia
git branch -a,列出所有分支名称如下:
remotes/origin/dev
remotes/origin/release
git checkout origin/dev -b dev,作用是checkout远程的dev分支,在本地起名为dev分支,并切换到本地的dev分支
下载整个代码库
repo init -u ssh://yourname@myrepo.xxx.com:29418/mtk_N/alps/manifest -b <BRANCH> -m <MANIFEST>
这里-m和-b的含义是:
注意到manifest.git本身也是一个git project
-b指定的是使用这个git project的哪个branch
-m指定的是,下载该git project中的哪个文件(应该是首先切换了branch,然后再下载该文件)。
开始抓取代码
repo sync
选项:
-j : 多任务,一般8核心可以开到16任务,过多会起反作用
-c: 只下载当前分支代码
-d: 让工程回退到manifest指定的版本
-f: 如果某个工程同步失败,继续同步
批量创建本地分支
repo start [–all | …]
刚克隆下来的代码是没有分支的,repo start实际是对git checkout –b 命令的封装。为指定的项目或所有项目(若使用—all参数),以清单文件中为设定的分支,创建特性分支。这条指令与git checkout –b 还是有很大的区别的,git checkout –b 是在当前所在的分支的基础上创建特性分支,而repo start是在清单文件设定分支的基础上创建特性分支。
Example:
repo start stable --all
git branch命令
查看分支
–list < pattern> 匹配查找,展示名称符合pattern的分支
-a 所有分支:本地分支,远程追踪分支
-r 远程追踪分支
–contains < commit> 包含某次提交的所有分支
创建分支
git branch < branchName>
-t –track
git branch -t b1 b2 以b2为upstream创建b1分支
重命名分支
-m –move < old> < new>
跟踪分支
-u
–set-upstream-to
删除分支
-d 删除分支
-D 强制删除
-rd 删除远程跟踪分支
本地删除远程分支
Pushing an empty < src> allows you to delete the < dst> ref from the remote repository.
git push 的src参数为空会删除远程分支
git push –prune 没有本地对应分支的远程分支
git push -d 删除远程分支
Camera分析LOG开关
打开拍照相关的log
//查看相机信息
adb shell setprop vendor.debug.camera.log 1
//查看拍照信息
adb shell setprop vendor.debug.camera.capture.log 1
//查看HAL3A信息
adb shell setprop vendor.debug.hal3av3.log 1
//查看feature信息
adb shell setprop vendor.debug.camera.featuresetting.log 1
查找包含字符串的文件
find . -name *.h -type f -print | xargs grep "libaudio_param_parser" --color
grep -rn "libaudio_param_parser" *
查询当前磁盘容量
du -sh : 查看当前目录总共占的容量。而不单独列出各子项占用的容量
du -lh --max-depth=1 : 查看当前目录下一级子文件和子目录占用的磁盘容量。
编译命令
sudo apt-get install libswitch-perl
make -j4 2>&1|tee make.log
关闭开机向导
adb shell pm disable com.google.android.setupwizard
替换系统文件
最新的adb 工具包才支持adb disable-verity命令,如果是Linux开发环境,则可使用工程编译结果目录out/host/linux-x86/bi下的adb执行文件
adb root
adb disable-verity
adb reboot
adb root
adb remount
动态开启framework日志
//必须是usedebug版本才可以
adb shell setprop log.tag.AudioService.MOD D
adb shell setprop log.tag.AudioService.VOL D
adb shell setprop log.tag.AudioManager D
adb shell stop
adb shell start
替换库文件调试脚本
#!/bin/sh
echo "mm"
mmm vendor/mediatek/proprietary/hardware/audio/nxp/
echo "root"
adb root
adb remount
echo "push"
adb push out/target/product/tk6757_66_n1/system/lib/libtfa9891_interface.so /system/lib/
adb push out/target/product/tk6757_66_n1/system/lib64/libtfa9891_interface.so /system/lib64/
echo "reboot sleep"
adb reboot
sleep 30
echo "root"
adb root
adb remount
echo "logcat"
adb logcat | grep Tfa98xxx
按时间命名文件
#!/bin/sh
echo "mm"
mmm speex/
adb push out/target/product/tk6757_66_n1/system/bin/speextest /system/bin/
adb push /mnt/hgfs/share_linux/采访功能/8k/echo.wav /sdcard/
adb push /mnt/hgfs/share_linux/采访功能/8k/ref.wav /sdcard/
adb shell rm /sdcard/out.pcm
echo "bin"
adb shell speextest
adb pull /sdcard/out.pcm /mnt/hgfs/share_linux/采访功能/8K_out_$(date -d "today" +"%Y%m%d_%H%M%S").pcm
echo "end"
修改编译的虚拟内存
alps/prebuilts/sdk/tools/jack_server_setup.mk
ifneq ($(ANDROID_JACK_VM_ARGS),)
jack_vm_args := $(ANDROID_JACK_VM_ARGS) -Xmx4096m
else
jack_vm_args := -Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4096m
endif
available_jack_jars := $(wildcard $(LOCAL_PATH)/jacks/jack-*.jar)
dump数据
void AudioTrackDump::dump(const char *filepath, void *buffer, int count, const char *property)
{
int ret;
char value[256];
property_get(property, value, "0");
int bflag = atoi(value);
if (bflag) {
ret = checkPath(filepath);
if (ret < 0) {
ALOGE("dump fail!!!");
} else {
FILE *fp = fopen(filepath, "ab+");
if (fp != NULL) {
fwrite(buffer, 1, count, fp);
fclose(fp);
} else {
ALOGE("dump %s fail", property);
}
}
}
}
int AudioTrackDump::checkPath(const char *path)
{
char tmp[256];
int i = 0;
while (*path) {
tmp[i] = *path;
if (*path == '/' && i) {
tmp[i] = '\0';
if (access(tmp, F_OK) != 0) {
if (mkdir(tmp, 0770) == -1) {
ALOGE("mkdir error! %s",(char*)strerror(errno));
return -1;
}
}
tmp[i] = '/';
}
i++;
path++;
}
return 0;
}
堆栈打印
Linux Kernel
Kernel里最简单,直接有几现成的函数可以使用:
dump_stack() 这个函数打出当前堆栈和函数调用backtrace后接着运行WARN_ON(x) 这个函数跟dump_stack打出来。
打印出来的结果都在kernel log命令就可以看到了
Native C++
Android在新版(至少5.0, 6.0)里加入了CallStack类,这个类可以打出当前的backtrace。用法很简单:
1. 前面确保包含头文件 #include “utils/CallStack.h”;
2. Android.mk的库依赖列表(LOCAL_SHARED_LIBRARIES)里包含libutils,一般都已经包含了;
3. 然后在要打印堆栈处加入android::CallStack cs(“haha”);“haha”是在logcat输出的TAG,这里可以自己定义。
如果上下文已经在android namespace里,”android::”前缀就不必加了。Native C++的输出log可以在logcat里看到。
注意,在网上的一些文档里说要这么用:
```
CallStack stack;
stack.update();
stack.dump();
```
这样做已经不行了,在新版Android里编译不过。
Java
Java最详细,连文件名和行号都打出来了:
Exception e = new Exception("haha");
e.printStackTrace();
追踪出错地址
prebuilts/tools/gcc-sdk/addr2line -e out/target/product/z4dtg/obj/EXECUTABLES/xxxxx_intermediates/LINKED/xxxxxxxx 0x00007165
Ubuntu下安装最新OpenJdk1.8
1、sudo add-apt-repository ppa:openjdk-r/ppa
2、sudo apt-get update
3、sudo apt-get install openjdk-8-jdk
4、执行:sudo update-alternatives –config java,选择java的版本
5、执行:sudo update-alternatives –config javac,选择javac的版本
Fastboot
adb reboot bootloader
fastboot devices
fastboot oem unlock
fastboot oem unlock-go
fastboot flash boot boot.img
fastboot flash system system.img
fastboot reboot
Ubuntu上ADB devices找不到设备
1. 用lsusb命令查询usb设备id,其中Device 027是我的手机设备,usb id为2717。
2. 进入~/.android/目录,创建adb_usb.ini文件;
3. 编辑adb_usb.ini文件,将设备的usb id添加到文件里
4. adb kill-server杀死adb服务;
5. 最后,用adb devices重新查找设备,就可以找到了;
ubuntu配置adb环境变量
1、sudo gedit ~/.bashrc
2、将下面的两句加到上面打开的文件里
export ANDROID_HOME=/home/sdk文件路径
export PATH=$PATH:$ANDROID_HOME/platform-tools
3、重启电脑,大功告成!!
Jack故障处理
//编译卡住
./prebuilts/sdk/tools/jack-admin kill-server
./prebuilts/sdk/tools/jack-admin stop-server
./prebuilts/sdk/tools/jack-admin start-server
//Out of memory
修改文件jack_server_setup.mk under prebuilts\sdk\tools
ANDROID_JACK_VM_ARGS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4g"
./prebuilts/sdk/tools/jack-admin stop-server
./prebuilts/sdk/tools/jack-admin start-server
拉取多媒体库
adb shell content query --uri content://media/external/file > external_file.txt
adb shell content query --uri content://media/external/images/media > external_images.txt
adb shell content query --uri content://media/external/audio/media > external_audio.txt
adb shell content query --uri content://media/external/video/media > external_video.txt
adb shell content query --uri content://media/external/video/thumbnails > external_thumbnails.txt
git下git diff用法
1、生成patch(在代码修改后没有commit之前的状态执行,进入想生成patch的目录即可)
git diff > patch_3
2、打patch,方法和linux的diff一样
#patch -p0 < patch_3
git apply patch_3 //也可用这个命令打patch
根据进程名字杀死进程
ps -ef | grep procedure_name | grep -v grep | awk '{print $2}' | xargs kill -9
虚拟机挂载虚拟磁盘
mkdir workspace
mkdir workspace2
sudo gedit /etc/fstab
/dev/sdb1 /home/user/workspace2 ext4 defaults 0 0
/dev/sdc1 /home/user/workspace ext4 defaults 0 0
修改用户名和邮箱
sudo git config --global user.name "yourname"
sudo git config --global user.email yourname@xxx.com.cn
生成秘钥
ssh-keygen
计算函数执行时间
方式一
#include<time.h>
nsecs_t start = systemTime(SYSTEM_TIME_MONOTONIC);
nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
MY_LOGD("consumingTime = %f", double((end-start)/1000000));
方式二
auto start = std::chrono::steady_clock::now();
auto end = std::chrono::steady_clock::now();
std::chrono::duration<double> diff = end - start;
uint64_t finalsize = sstat.st_size;
ALOGV("Got a file over MTP. Time: %fs, Size: %" PRIu64 ", Rate: %f bytes/s",
diff.count(), finalsize, ((double) finalsize) / diff.count());
如何打开pr_debug调试信息
$cat /proc/sys/kernel/printk
7 4 1 7
$echo 8 > /proc/sys/kernel/printk
$cat /proc/sys/kernel/printk
8 4 1 7
查看 读写SD卡权限
判断APP运行时权限如下:
adb remount;//挂载
adb shell;//进入shell
ps | grep fmradio;//查找FMRadio的PID,前提是手机打开FMRadio,插入耳机
cd proc/4830;//进入PID对应的信息文件中
cat status;//查看进程信息
发现此时,FMRadio对于的组权限如下:
com.android.fmradio Groups: 1013 3002 3003 9997 50010
com.android.soundrecorder Groups: 1015 1023 3003 9997 50105
根据系统权限的定义,有兴趣的同学可以去看一下这个文件
system/core/include/private/android_filesystem_config.h
分析这些Gid发现:
1015 为sdcard_rw,1023 为media_rw权限
源码文件:frameworks/base/data/etc/platform.xml
这个文件中定义了底层权限组GID和高层权限名字之间的对应关系
其实,在这个文件已经定义过了
手机数据区文件:data/system/packages.xml
这个文件由PackageManagerService.Java生成,里面记录了系统当中安装的APK的所有属性,权限等信息。L之前,当系统中的APK安装、删除、升级时,文件就会被更新。L之后,重启才会重新扫描更新该文件。
C++替换字符串
std::string srt2 = (const char*)path;
std::string tmps2 = "/mnt/media_rw/";
if(srt2.find("/storage/") != std::string::npos &&
srt2.find("/storage/emulated/") == std::string::npos){
tmps2 = tmps2 + srt2.substr(9);
path.set(tmps2.c_str());
}
- 截取子串
s.substr(pos, n) 截取s中从pos开始(包括0)的n个字符的子串,并返回
s.substr(pos) 截取s中从从pos开始(包括0)到末尾的所有字符的子串,并返回
- 替换子串
s.replace(pos, n, s1) 用s1替换s中从pos开始(包括0)的n个字符的子串
- 查找子串
s.find(s1) 查找s中第一次出现s1的位置,并返回(包括0)
s.rfind(s1) 查找s中最后次出现s1的位置,并返回(包括0)
s.find_first_of(s1) 查找在s1中任意一个字符在s中第一次出现的位置,并返回(包括0)
s.find_last_of(s1) 查找在s1中任意一个字符在s中最后一次出现的位置,并返回(包括0)
s.fin_first_not_of(s1) 查找s中第一个不属于s1中的字符的位置,并返回(包括0)
s.fin_last_not_of(s1) 查找s中最后一个不属于s1中的字符的位置,并返回(包括0)
读取二进制文件
#include <iostream>
#include <fstream>
filebuf *pbuf;
ifstream filestr;
int size = 0;
char * buffer = NULL;
filestr.open ("test.cng", ios::binary);
if (filestr.fail()){
return;
}
pbuf = filestr.rdbuf();
size = pbuf->pubseekoff(0, ios::end, ios::in);
pbuf->pubseekpos (0, ios::in);
buffer = new char[size];
pbuf->sgetn(buffer, size);
filestr.close();
delete []buffer;
CTS命令
无法执行CTS命令
去out 目錄下將out/host/linux-x86/bin/aapt放到某個目錄下(如:/tools/bin/aapt),將該目錄(如:/tools/bin/aapt) 添加到 PATH 中去。
export PATH=$PATH:~/workspace/tp706_p/alps/out/host/linux-x86/bin
执行GTS测试
run gts -s 0123456789ABCDEF -m GtsMediaTestCases -t com.google.android.media.gts.WidevineH264PlaybackTests#testClearWithUHD30 --abi arm64-v8a --skip-preconditions
执行GSI测试
run cts-on-gsi -s 3901A18303900273 -m CtsMediaTestCases -t android.media.cts.RingtoneManagerTest#testStopPreviousRingtone --abi arm64-v8a --skip-preconditions
测试命令
full run 全部测试命令:run cts --plan CTS -s device serial
测试自己添加的计划命令: run cts --subplan name
测试整个 package 命令: run cts -m package_name
测试单项命令:run cts -m package_name -t module_name+case_name
继续测试命令:run cts -r session_ID
查看命令
查看测试结果命令 : l r
查看测试时间多长命令: l i
查看多少个设备连接命令: l d
查看当前测试窗口正在执行的命令: l c
查看有多少个 module 的命令:l m
其他命令或者参数
强制退出命令 kill
禁止重启命令 --disable-reboot
跳过预设环境命令 --skip-preconditions
跳过某项 package 命令 --exclude-filter+package_name
只测试某项 package 命令 --include-filter+ package_name
测试某台样机的参数 -s 或--serial+serial_name
几台样机同时测试的命令 --shards+number
以上都是写简单常用的命令,用 run cts –help-all 可以显示其他更详细的命令
Init.rc妙用及语法说明
Service
service < name> < pathname> [ < argument> ]*
< option>
< option>
常用Options(用于修饰service)
1、critical 表示这是一个关键的service,4分钟内退出4次,则系统重启进入recovery mode。
2、disabled 这个服务不会随着它的类启动而自动启动,必须明确指定服务名称启动。
3、setenv 设置环境变量。
4、socket [ [ [ ] ] ] 创建一个socket接口/dev/socket/,使本地service和java可以通信。详见
http://blog.csdn.net/eliot_shao/article/details/53159989 。
5、user 执行service之前改变用户名。
6、group [ ]* 执行service之前改变用户组。
7、oneshot 当service退出后不会重启。
8、class 为service指定一个类名,具有相同类名的service可以一起启动和停止。
9、onrestart 启动一个Command,当service重新启动的时候。
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart healthd
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart drm
Actions
on < trigger>
< command>
< command>
< command>
常用Triggers说明:
1、boot eg: on boot 这是第一个触发的,当init进程启动时候。
on boot
export PATH /sbin:/system/sbin:/system/bin
export LD_LIBRARY_PATH /system/lib
mkdir /dev
mkdir /proc
mkdir /sys
2、= when the property is set to the specific value
on property:vts.native_server.on=1
stop audioserver
on property:vts.native_server.on=0
start audioserver
service audioserver /system/bin/audioserver
class core
user audioserver
3、device-added- device-removed-
当一个设备节点被删除或者添加的时候,触发。
on device-added-/dev/compass=1
start akmd
on device-removed-/dev/compass=0
stop akmd
service akmd /sbin/akmd
disabled
user akmd
group akmd
4、service-exited- 当制定的service退出的时候触发。
Commands
1、exec [ ]* Fork and execute a program ().
2、export
export PATH /sbin:/system/sbin:/system/bin
3、import 解析init配置文件,扩展当前的init.rc配置
4、chdir 改变当前的工作路径
5、chmod 改变文件的访问权限
6、chown 改变文件拥有者和组
7、class_start 启动某个class
on nonencrypted
class_start main
class_start late_start
8、class_stop 停止某个class
9、enable 使能一个service 如果他是disable的。
10、insmod 安装模块
11、mkdir [mode] [owner] [group] 创建文件夹
12、mount [ ]* 挂载设备到某个目录
13、setenforce 0|1 设置SELinux system-wide的状态
14、setprop 设置system property
15、start 启动service
16、stop 停止service
17、wait [ ] 等待某个文件的出现
18、write 向文件写入字符串
write /proc/cpu/alignment 4
HIDL 接口
软件包位于 hardware/interfaces 或 vendor/ 目录下(少数例外情况除外)。hardware/interfaces 顶层会直接映射到 android.hardware 软件包命名空间;版本是软件包(而不是接口)命名空间下的子目录。
hidl-gen 编译器会将 .hal 文件编译成一组 .h 和 .cpp 文件。这些自动生成的文件可用来编译客户端/服务器实现链接到的共享库。用于编译此共享库的 Android.bp 文件由 hardware/interfaces/update-makefiles.sh 脚本自动生成。每次将新软件包添加到 hardware/interfaces 或在现有软件包中添加/移除 .hal 文件时,您都必须重新运行该脚本,以确保生成的共享库是最新的。
HIDL 软件包中自动生成的文件会链接到与软件包同名的单个共享库(例如 android.hardware.samples@1.0)。该共享库还会导出单个标头 IFoo.h,用于包含在客户端和服务器中。绑定式模式使用 hidl-gen 编译器并以 IFoo.hal 接口文件作为输入,它具有以下自动生成的文件:
)
Android SELinux avc dennied权限问题解决方法
https://blog.csdn.net/tung214/article/details/72734086
1、调试确认SELinux问题
为了澄清是否因为SELinux导致的问题,可先执行:
setenforce 0 (临时禁用掉SELinux)
getenforce (得到结果为Permissive)
如果问题消失了,基本可以确认是SELinux造成的权限问题,需要通过正规的方式来解决权限问题。
遇到权限问题,在logcat或者kernel的log中一定会打印avc denied提示缺少什么权限,可以通过命令过滤出所有的avc denied,再根据这些log各个击破:
cat /proc/kmsg | grep avc
或
dmesg | grep avc
例如:
audit(0.0:67): avc: denied { write } for path="/dev/block/vold/93:96" dev="tmpfs" ino=1263 scontext=u:r:kernel:s0 tcontext=u:object_r:block_device:s0 tclass=blk_file permissive=0
可以看到有avc denied,且最后有permissive=0,表示不允许。
2、复合权限
有时候avc denied的log不是一次性暴露所有权限问题,要等解决一个权限问题之后,才会暴露另外一个权限问题。比如提示缺少某个目录的read权限,加入read之后,才显示缺少write权限,要一次次一次试,一次一次加,时间成本极大。
针对dir缺少的任何权限,建议赋予create_dir_perms,基本涵盖对dir的所有权限,比如:
{ open search write read rename create rmdir getattr }等等。
针对file缺少的任何权限,建议赋予rwx_file_perms,基本涵盖对file的所有权限,比如:
包含{ open read write open execute getattr create ioctl }等等。
3、万能公式
通过这四个案例,我们可以总结出一般规律,
以第案例4为例:
audit(1441759284.810:5): avc: denied { read } for pid=1494 comm="sdcard" name="0" dev="nandk" ino=245281 scontext=u:r:sdcardd:s0 tcontext=u:object_r:system_data_file:s0 tclass=dir permissive=0
某个scontext对某个tclass类型的tcontext缺乏某个权限,我们需要允许这个权限:
我们的log重新排列一下,
scontext = u:r:sdcardd
tcontex t= u:object_r:system_data_file:s0
tclass = dir
avc: denied { read }
得到万能套用公式如下:
在scontext所指的.te文件(例如sdcardd.te)中加入类似如下allowe内容:
allow sdcardd system_data_file:dir read; 或者
allow sdcardd system_data_file:dir rw_dir_perms;
新设备节点增加访问权限
驱动创建了一个新的设备节点,即使权限是777,android层也是没有访问权限的。
下面以一个/dev/wifi_bt节点为示范,让此节点被用户空间的system_server进程访问。
- 编辑devicesoftwinner/astar-common/sepolicy/device.te,仿照这个文件里的写法,定义一个dev_type类型的wifi_bt_device设备:
type misc_block_device, dev_type;
type private_block_device, dev_type;
//新增
type wf_bt_device, dev_type;
- 编辑file_contexts.te,将/dev/wf_bt节点声明为第1步定义的wf_bt_device:
/dev/block/by-name/misc u:object_r:misc_block_device:s0
/dev/block/by-name/alog u:object_r:log_block_device:s0
/dev/block/by-name/private u:object_r:private_block_device:s0
// 新增
/dev/wf_bt u:object_r:wf_bt_device:s0
- 在system_server.te,根据dmesg | grep avc允许system_server对wf_bt_device这个节点可读可写:
allow system_server qtaguid_proc:file rw_file_perms;
allow system_server qtaguid_device:chr_file rw_file_perms;
//新增
allow system_server wf_bt_device:chr_file rw_file_perms;
其他进程如需访问/dev/wf_bt节点,依样画葫芦,增加对wf_bt_device的权限即可。
新目录增加访问权限
创建了一个新的目录,即使权限是777,android层也是没有访问权限的。
下面以一个/data/audio_param目录为示范,让此节点被用户空间的system_server进程访问。
- 编辑devicesoftwinner/astar-common/sepolicy/file.te,仿照这个文件里的写法,定义一个dev_type类型的data_audioparma_file设备:
type misc_block_device, dev_type;
type private_block_device, dev_type;
//新增
type data_audioparma_file, file_type, data_file_type, core_data_file_type;
- 编辑file_contexts.te,将/data/audio_param目录声明为第1步定义的data_audioparma_file:
/dev/block/by-name/misc u:object_r:misc_block_device:s0
/dev/block/by-name/alog u:object_r:log_block_device:s0
/dev/block/by-name/private u:object_r:private_block_device:s0
// 新增
/data/audio_param(/.*)? u:object_r:data_audioparma_file:s0
- 在system_server.te,根据dmesg | grep avc允许system_server对 /data/audio_param这个目录可读可写:
allow system_server qtaguid_proc:file rw_file_perms;
allow system_server qtaguid_device:chr_file rw_file_perms;
//新增
allow system_server data_audioparma_file:dir create_dir_perms;
allow system_server data_audioparma_file:file create_file_perms;
新建.te安全策略文件方法
以上基本是对已经存在的进程增加权限,但对第三方进程改如何新增一个全新的te文件并赋予权限呢?
以写mac地址的setmacaddr执行文件为例(这个执行档android原生不存在,自行添加的):
在init.xxx.rc中如下服务:
service engsetmacaddr /system/bin/setmacaddr /data/misc/wifi/wifimac.txt
class main
disabled
oneshot
- 在device/softwinner/astar-common/sepolicy/file_contexts中,参考其他进程声明一个scontext:
/system/bin/install-recovery.sh u:object_r:install_recovery_exec:s0
/system/bin/dex2oat u:object_r:dex2oat_exec:s0
/system/bin/patchoat u:object_r:dex2oat_exec:s0
/system/bin/setmacaddr u:object_r:engsetmacaddr_exec:s0
指定setmacaddr的路径,并指定一个名字,一定要以service名+_exec结尾
2.参考其.te文件在device/softwinner/astar-common/sepolicy/file_contexts 创建engsetmacaddr.te文件,内容如下:
type engsetmacaddr, domain;
type engsetmacaddr_exec, exec_type, file_type;
init_daemon_domain(engsetmacaddr)
allow engsetmacaddr vfat:dir { search write add_name create};
allow engsetmacaddr vfat:file { create read write open };
allow engsetmacaddr engsetmacaddr:capability dac_override;
allow engsetmacaddr shell_exec:file { execute read open execute_no_trans};
allow engsetmacaddr system_data_file:dir { write add_name remove_name };
allow engsetmacaddr system_data_file:file { create execute_no_trans write open setattr};
allow engsetmacaddr system_file:file { execute_no_trans};
以上赋予的权限全部是根据avc denied的log缺什么一步一步补什么来的。
如何配置策略
https://blog.csdn.net/tww85/article/details/52451606
编译出来的策略文件在哪?
ODM策略编译出来的策略文件在out/…/vendor/etc/selinux目录下
vendor_file_contexts vendor_hwservice_contexts vendor_property_contexts vendor_seapp_contexts vndservice_contexts
原生策略编译出来的策略文件在out/…/system/etc/selinux目录下
plat_file_contexts plat_hwservice_contexts plat_property_contexts plat_seapp_contexts plat_service_contexts
需要先了解系统针对客体和主体提供了哪些设置属性和操作。
external/sepolicy/security_classes 定义了客体的基本类型,比如下面的
# for userspace object managers
class security
class process
class system
class capability
#//file-related classes
class filesystem
class file
class dir
class fd
class lnk_file
class chr_file
class blk_file
class sock_file
external/sepolicy/access_vectors 文件列出来各种客体类型所拥有的属性,比如下面的file类型和dir 类型,类型间可以有集成关系。
common file
{
ioctl
read
write
create
getattr
setattr
lock
relabelfrom
relabelto
append
unlink
link
rename
execute
swapon
quotaon
mounton
}
class dir
inherits file
{
add_name
remove_name
reparent
search
rmdir
open
audit_access
execmod
}
external/sepolicy/global_macros全局宏变量定义文件,也就是用一个宏变量同时表示几个属性。如下例子
define(`x_file_perms', `{ getattr execute execute_no_trans }')
define(`r_file_perms', `{ getattr open read ioctl lock }')
define(`w_file_perms', `{ open append write }')
define(`rx_file_perms', `{ r_file_perms x_file_perms }')
define(`ra_file_perms', `{ r_file_perms append }')
define(`rw_file_perms', `{ r_file_perms w_file_perms }')
define(`rwx_file_perms', `{ rw_file_perms x_file_perms }')
define(`link_file_perms', `{ getattr link unlink rename }')
define(`create_file_perms', `{ create setattr rw_file_perms link_file_perms }')
external/sepolicy/te_macros 宏规则变量定义文件,也就是用一个变量来表示连续执行几条规则。如下例子
define(`domain_trans', `
// Old domain may exec the file and transition to the new domain.
allow $1 $2:file { getattr open read execute };
allow $1 $3:process transition;
//New domain is entered by executing the file.
allow $3 $2:file { entrypoint open read execute getattr };
//New domain can send SIGCHLD to its caller.
allow $3 $1:process sigchld;
//Enable AT_SECURE, i.e. libc secure mode.
dontaudit $1 $3:process noatsecure;
//XXX dontaudit candidate but requires further study.
allow $1 $3:process { siginh rlimitinh };
')
external/sepolicy/file_contexts 文件安全上下文定义文件。就是说对于一个文件或者目录,它的安全上下文应该在这里定义,如果没有定义,那么默认和父目录的安全上下文一样。
比如说我们在data目录下建了一个log目录存放系统运行时的log,在file.te中新增data_log_file,log目录的安全上下文是
u:object_r:data_log_file:s0
那么就应该在file_contexts文件里做如下定义:
/data/log(/.*)?u:object_r:data_log_file:s0
external/sepolicy/property_contexts 属性安全上下文定义文件。比如说在propety.te中新加了一个persist.log. * 开头的属性,那么就需要给它添加对应的安全上下文,如果不添加或者添加的上下文不对,那么在的某个进程里写入时就写不进去。比如做了如下定义,那么是具有system_prop域安全上下文,只能在system进程里修改值,在shell里是不能访问的。
persist.log. u:object_r:system_prop:s0
如果希望在shell里能修改值,就应该这么写
persist.log. u:object_r:shell_prop:s0
当然如果通过修改相关*.te 文件也能实现,但是不是很规范。
external/sepolicy/property.te 文件允许我们定义自己的prop 类型域,还有seapp_contexts、service_contexts 文件等,都是类似的,都可以根据需要修改。