都是从网络上摘抄的总结下来备用,有些链接丢失了
通过system server service 或者 init 启动的service 读写, 然后app 通过binder/socket 等方式连接APP 访问. 此类安全可靠, 并且可以在service 中做相关的安全审查, 推崇这种方法.
自Android L版本,Google对源码环境普遍启用SELinux安全访问机制,APP及framework层默认情况下再无权限访问设备节点如(sys/xxx,proc/xxx)
下面以三种常用操作角度阐述为system app进程或system server进程开放权限的方法
1) SEAndroid 为sys设备文件结点开放访问(读或写)权限的方法(如:/sys/class/leds/green/brightness)
2) SEAndroid 为proc设备文件结点开放访问(读或写)权限的方法(如:/proc/touchscreen_feature/gesture_data)
3) SEAndroid 为SystemProperties的自定义属性开放set(写)权限的方法
一、 SEAndroid 为sys设备文件结点开放访问(读或写)权限的方法 (如:/sys/class/leds/green/brightness)
如绿灯:/sys/class/leds/green/brightness,为APP层system app进程开放该节点访问权限(读或写)
/sys/class/leds/green/brightness //快捷方式
/sys/devices/soc.0/gpio-leds.66/leds/green/brightness //实际节点
MTK:alps/device/mediatek/common/sepolicy
QCOM:android/device/qcom/sepolicy/common
1.1 在android/device/qcom/sepolicy/common/file.te,定义selinux type:sysfs_wingtk_leds,如下:
type sysfs_wingtk_leds, fs_type, sysfs_type;
1.2 在android/device/qcom/sepolicy/common/file_contexts,绑定sysfs_wingtk_leds到对应的实际节点,注意是实际节点
获取实际节点可以通过 , ll -Z 命令就可以查到。
root@K31-t7:/sys/class/leds # ll -Z
lrwxrwxrwx root root u:object_r:sysfs:s0 flashlight -> ../../devices/soc.0/flashlight.64/leds/flashlight
lrwxrwxrwx root root u:object_r:sysfs:s0 green -> ../../devices/soc.0/gpio-leds.66/leds/green
lrwxrwxrwx root root u:object_r:sysfs:s0 lcd-backlight -> ../../devices/soc.0/1a00000.qcom,mdss_mdp/qcom,mdss_fb_primary.124/leds/lcd-backlight
lrwxrwxrwx root root u:object_r:sysfs:s0 mmc0:: -> ../../devices/soc.0/7824900.sdhci/leds/mmc0::
lrwxrwxrwx root root u:object_r:sysfs:s0 mmc1:: -> ../../devices/soc.0/7864900.sdhci/leds/mmc1::
lrwxrwxrwx root root u:object_r:sysfs:s0 red -> ../../devices/soc.0/gpio-leds.66/leds/red
lrwxrwxrwx root root u:object_r:sysfs:s0 torch-light0 -> ../../devices/soc.0/qcom,camera-led-flash.65/leds/torch-light0
root@K31-t7:/sys/class/leds #
/sys/devices/soc.0/gpio-leds.66/leds/green/brightness u:object_r:sysfs_wingtk_leds:s0
/sys/class/leds/green/brightness u:object_r:sysfs_wingtk_leds:s0
PS:可以把/sys/class/leds/green/brightness也声明下,该句不是必须的:
1.3 在android/device/qcom/sepolicy/common/system_app.te,申请权限:
allow system_app sysfs_wingtk_leds:file rw_file_perms;
PS:也可以为其他process申请相关的权限,如:system_server,在android/device/qcom/sepolicy/common/system_server.te
allow system_server sysfs_wingtk_leds:file rw_file_perms;
1.4 在AndroidManifest.xml,配置:android:sharedUserId=”android.uid.system”,该步时必须的,因为第三步是:
allow system_app sysfs_wingtk_leds:file rw_file_perms; //仅允许system_app进程访问.
经过以上四步,APP层就可以正常读写:/sys/class/leds/green/brightness为了更好地控制访问权限,如果存在APP层和framework层都要访问某个设备节点,笔者认为最好以此式来访问设备节点,即不让system_app进程访问,仅仅允许system_server进程来访问,如
allow system_server sysfs_wingtk_leds:file rw_file_perms;
缺点:
需要在framework层添加随系统启动的service,增加代码量
优点:
1.可以自由控制哪些应用可以访问,哪些应用禁止访问已经开放的设备节点,可以更好的保护安全问题
2.framework层和APP层都可以访问该设备节点.不用再另外进行权限申请
二、 proc设备文件结点开放访问(读或写)权限的方法(如:/proc/touchscreen_feature/gesture_data),以MTK平台为例
2.1在alps/mediatek/common/sepolicy/file.te 定义selinux type: proc_quick_gesture,如下:
type proc_quick_gesture, fs_type;
2.2在 alps/mediatek/common/sepolicy/genfs_contexts,绑定proc_quick_gesture到对应的实际节点
genfscon proc /touchscreen_feature/gesture_data u:object_r:proc_quick_gesture:s0
2.3 在alps/mediatek/common/sepolicy/common/system_app.te,申请权限
2.4 AndroidManifest.xml,配置:android:sharedUserId=”android.uid.system”, 设置为system_app进程就具备权限(读或写)访问/proc/touchscreen_feature/gesture_data等节点啦
三、 SystemProperties的自定义属性开放set(写)权限的方法( 问题描述 SystemProperties对自定义属性没有写权限,即set时提示没有权限,导致写不成功)
以”persist.backgrounddata.enable”为例介绍开放属性权限方法
以QCOM平台为例
3.1 android/device/qcom/sepolicy/common/property.te
type persist_backgrounddata_prop, property_type;
3.2 android/device/qcom/sepolicy/common/property_contexts
persist.backgrounddata.enable u:object_r:persist_backgrounddata_prop:s0
3.3 android/device/qcom/sepolicy/common/system_app.te,为system_app进程开放权限
allow system_app persist_backgrounddata_prop:property_service set;
3.4 在AndroidManifest.xml,配置:android:sharedUserId="android.uid.system"
代码中就可以使用SystemProperties.set(“persist.backgrounddata.enable”“, xx)设置属性了。
延伸阅读
如果通过以上步骤正确配置之后,你仍没有权限读写sys或proc节点,是不是DAN都碎了。再告诉你下,你需要到init.rc里面配置: chown system system 文件结点,然后chmod下文件结点。两个平台配置路径,项目不同略有差异
MTK:alps/device/mediatek/mt6735/init.mt6735.rc
QCOM:xx/xx/init.target.rc
四、 SEAndroid 访问 dev 节点
1. 首先确定需要访问该内核节点的进程(process),目前为我们是用 system_server访问
2. 打开文件AndroidL/android/external/sepolicy/file_contexts.be
/dev/wf_bt u:object_r:wf_bt_device:s0
wf_bt_device是自定义,其他左右两边的内容都和上面的范例一致。
3.:打开文件AndroidL/android/external/sepolicy/device.te
仿照这个文件里的写法,将刚刚第二步写的wf_bt_device声明为dev_type:
type wf_bt_device, dev_type;
4.AndroidL/android/external/sepolicy/目录下很多.te文件都是以进程名来结尾的,比如有针对surfaceflinger进程的surfaceflinger,有针对vold进程的vold.te,
刚刚从第一步得到,这个节点是由system_server进程来访问,所以,我们找到system_server.te打开,加入允许这个进程对/dev/wf_bt的读写权限,
allow system_server wf_bt_device:chr_file rw_file_perms;
这句话的意思是:允许system_server进程拥有对wf_bt_device的这个字符设备的读写权限。
改了这些之后,你就可以make installclean;make -j16编译image来验证权限是否获取成功。
fd =open("/dev/wf_bt",O_RDONLY | O_NOCTTY);
五、为执行脚本进程添加权限
http://blog.csdn.net/jiuxiaoyunwu/article/details/51220477
5.1 init.rc 或者 其他 init.project.rc
on post-fs-data //在此节点下添加如下代码
chmod 0777 /system/bin/cloudtestsuited
on init // 在此节点下添加如下代码
service cloudtestsuited /system/bin/cloudtestsuited
class main
oneshot
disabled
或者可以在init.rc中在声明service 前 添加一行代码,
on property:sys.service.silead=enabled
然后再apk中就可以执行如下代码,前提是apk具有platform签名,system权限
oneshot选项表示该服务只启动一次,而如果没有oneshot选项,这个可执行程序会一直存在–如果可执行程序被杀死,则会重新启动。
disabled 表示禁用服务,此服务开机时不会自动启动,但是可以在应用程序中手动启动它。
5.2添加对应的selinux权限
在device\mediatek\common\sepolicy\file_contexts 文件中添加bin服务对应的权限:
/system/bin/cloudtestsuited u:object_r:fpsvcd_exec:s0 //此行设定所属域
5.3 在device\mediatek\common\sepolicy\system_app.te 文件中添加bin服务对应的权限,
允许系统 app do:add for fp.apk create file under ‘/data/silead/’ file path
allow system_app fpsvcd_data_file:dir { create write add_name remove_name read open search};
allow system_app fpsvcd_data_file:file { unlink getattr create write open read };
add for starting cloudtestsuited in apk
allow system_app fpsvcd_tmpfs:file { read write open getattr };
allow system_app fpsvcd_exec:file { getattr read execute open execute_no_trans };
allow system_app fpsvcd:dir { read open };
allow system_app tmpfs:dir { read write getattr };
5.4 在device\mediatek\common\sepolicy\ 目录下新增一个权限文件fpsvcd.te:
type fpsvcd_exec , exec_type, file_type;
type fpsvcd ,domain;
init_daemon_domain(fpsvcd)
...
...
5.5 启动服务
SystemProperties.set("sys.service.silead","enabled");
或者
private void startCloudServer() {
new Thread(new Runnable() {
@Override
public void run() {
try {
Log.v(Const.TAG_LOG, TAG
+ " startCloudServer->getRuntime cloudtestsuited");
//String[] cmd = new String[] { "su", "-c", "cloudtestsuited" };
String[] cmd = new String[] { "sh", "-c", "cloudtestsuited" };
//Process proc = Runtime.getRuntime().exec(cmd);
//proc.waitFor();
excuteCmd_multiThread(cmd);
} catch (Exception e) {
Log.e(Const.TAG_LOG, TAG
+ " startCloudServer occurs exception, ", e);
}
try {
Log.v(Const.TAG_LOG, TAG
+ " startCloudServer->SystemProperties cloudtestsuited");
//SystemProperties.set("ctl.start", "ztstartsileadcloudtest");
} catch (Exception e) {
Log.e(Const.TAG_LOG, TAG
+ " startCloudServer occurs exception, ", e);
}
}
}).start();
}
private void excuteCmd_multiThread(String[] cmd) {
try {
Process proc = Runtime.getRuntime().exec(cmd);
Thread errorThread = new Thread(new InputStreamRunnable(
proc.getErrorStream(), "ErrorStream"));
errorThread.start();
Thread outputThread = new Thread(new InputStreamRunnable(
proc.getInputStream(), "OutputStream"));
outputThread.start();
proc.waitFor();
} catch (InterruptedException e) {
Log.e(Const.TAG_LOG, TAG
+ " excuteCmd_multiThread occurs InterruptedException, ", e);
} catch (IOException e) {
Log.e(Const.TAG_LOG, TAG
+ " excuteCmd_multiThread occurs IOException, ", e);
}
}
private class InputStreamRunnable implements Runnable {
BufferedReader bReader = null;
String type = null;
public InputStreamRunnable(InputStream is, String typeCode) {
try {
type = typeCode;
bReader = new BufferedReader(new InputStreamReader(
new BufferedInputStream(is), "UTF-8"));
} catch (Exception e) {
Log.e(Const.TAG_LOG, TAG
+ " InputStreamRunnable occurs exception, ", e);
}
}
@Override
public void run() {
String line;
int lineNum = 0;
try {
while ((line = bReader.readLine()) != null) {
if ("ErrorStream".equals(type)) {
Log.e("FpCloudServer ERROR", line);
} else if ("OutputStream".equals(type)) {
Log.i("FpCloudServer Output", line);
} else {
Log.v("FpCloudServer debug", line);
}
lineNum++;
}
if (bReader != null) {
bReader.close();
}
} catch (Exception e) {
Log.e(Const.TAG_LOG, TAG
+ " InputStreamRunnable run occurs exception, ", e);
}
}
}
六、 recovery 操作 download 目录
6.1 recovery.te 中的定义
neverallow recovery data_file_type:file { no_w_file_perms no_x_file_perms };
neverallow recovery data_file_type:dir no_w_dir_perms;
6.2我们再来看下system_data_file在file_contexts.te中的定义
/data(/.*)? u:object_r:system_data_file:s0
6.3 而在file.te定义了system_data_file文件属于data_file_type类型,因此recovery也是不能操作data下面的文件
file.te:56:type system_data_file, file_type, data_file_type;
6.4 解决办法:在我们可以自己定义自己的file类型,我们可以定义data/download属于download_data_file类型
(1) filecontext.te 定义
/data/download(/.*)? u:object_r:download_data_file:s0
(2)然后在file.te中定义download_data_file类型
type download_data_file, file_type;
(3) 然后在recovery.te中增加对download_data_file的权限
allow recovery download_data_file:dir { write search remove_name };
allow recovery download_data_file:file { read getattr unlink };
(4)另外我们还需在一个systemapp中先下载升级包,所以需要在system_app.te中增加对如下权限:
allow system_app download_data_file:dir { search write add_name getattr remove_name };
allow system_app download_data_file:file { create read write open getattr unlink };
(5)但是最后还是失败了,为什么呢,因为一开始没有data/download这个目录,而是我们再app中自己下载的时候创建的目录,所以是system_data_file类型的。那么我们就需要在一开始就有data/download目录,所以在init.rc中添加如下代码:
mkdir /data/download 0771 system system
(6)最后我们还需要在uncrypt.te中增加如下,因为data目录有可能需要进行加密处理。
allow uncrypt download_data_file:dir { search getattr };
allow uncrypt download_data_file:file { getattr read open };
七、添加 device type 操作
http://blog.csdn.net/lushengchu_luis/article/details/52775740
无意中看到网上这篇文章,在device.te加入type serial_device, dev_type, mlstrustedobject;这一行,问题迎刃而解
第三方签名APP,在SElinux下,如何获得对一个内核节点的访问权限
在android6.0中,出于安全考虑,不允许第三方签名的app被分配mlstrustedsubject:
7.1 在external/sepolicy/untrusted_app.te文件中:
# Do not allow untrusted_app to be assignedmlstrustedsubject.
# This would undermine the per-user isolation model being
# enforced via levelFrom=user in seapp_contexts and the mls
# constraints. As there is no direct way tospecify a neverallow
# on attribute assignment, this relies on the fact that fork
# permission only makes sense within a domain (hence should
# never be granted to any other domain withinmlstrustedsubject)
# and untrusted_app is allowed fork permission to itself.
neverallow untrusted_app mlstrustedsubject:process fork;
7.2 所以在使用第三方签名app时,希望第三方签名app某个进程能够对内核节点进行操作,可按如下修改:
1.在device/sprd/scx20/common/sepolicy/file_contexts 文件中添加:
/dev/abc u:object_r:abc_device:s0
2.在device/sprd/scx20/common/sepolicy/device.te 文件中添加:
type abc_device, dev_type, mlstrustedobject;
7.3 在device/sprd/scx20/common/sepolicy/untrusted_app.te 文件中添加:
allow untrusted_app adc_device:chr_fileoperate;
operate为赋予的权限。
注:
mlstrustedsubject:这一attribute包含了所有能越过MLS检查的主体domain。
mlstrustedobject:这一attribute包含了所有能越过MLS检查的客体type。