SEAndroid 解决案例

原文:http://blog.csdn.net/kongbaidepao/article/details/63254666

都是从网络上摘抄的总结下来备用,有些链接丢失了

通过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 //实际节点

 
 
  • 1
  • 2
  • 3

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

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 #

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
/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
  • 2
  • 3
  • 4
  • 5

1.3 在android/device/qcom/sepolicy/common/system_app.te,申请权限:

allow system_app sysfs_wingtk_leds:file rw_file_perms;
 
 
  • 1

PS:也可以为其他process申请相关的权限,如:system_server,在android/device/qcom/sepolicy/common/system_server.te


allow system_server sysfs_wingtk_leds:file rw_file_perms;
 
 
  • 1
  • 2

1.4 在AndroidManifest.xml,配置:android:sharedUserId=”android.uid.system”,该步时必须的,因为第三步是:

allow system_app sysfs_wingtk_leds:file rw_file_perms; //仅允许system_app进程访问.

 
 
  • 1
  • 2

经过以上四步,APP层就可以正常读写:/sys/class/leds/green/brightness为了更好地控制访问权限,如果存在APP层和framework层都要访问某个设备节点,笔者认为最好以此式来访问设备节点,即不让system_app进程访问,仅仅允许system_server进程来访问,如

allow system_server sysfs_wingtk_leds:file rw_file_perms;

 
 
  • 1
  • 2

缺点: 
需要在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;


 
 
  • 1
  • 2
  • 3
  • 4

2.2在 alps/mediatek/common/sepolicy/genfs_contexts,绑定proc_quick_gesture到对应的实际节点

 genfscon proc /touchscreen_feature/gesture_data   u:object_r:proc_quick_gesture:s0

 
 
  • 1
  • 2

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"
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

代码中就可以使用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); 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

五、为执行脚本进程添加权限

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权限
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

oneshot选项表示该服务只启动一次,而如果没有oneshot选项,这个可执行程序会一直存在–如果可执行程序被杀死,则会重新启动。 
disabled 表示禁用服务,此服务开机时不会自动启动,但是可以在应用程序中手动启动它。

5.2添加对应的selinux权限 
在device\mediatek\common\sepolicy\file_contexts 文件中添加bin服务对应的权限:

 /system/bin/cloudtestsuited u:object_r:fpsvcd_exec:s0  //此行设定所属域 
 
 
  • 1

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 };  
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

5.4 在device\mediatek\common\sepolicy\ 目录下新增一个权限文件fpsvcd.te:

type fpsvcd_exec , exec_type, file_type;  
type fpsvcd ,domain;  
init_daemon_domain(fpsvcd)  
...
...

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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);
            }
        }
    }


 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

六、 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;  
 
 
  • 1
  • 2

6.2我们再来看下system_data_file在file_contexts.te中的定义


/data(/.*)?     u:object_r:system_data_file:s0  

 
 
  • 1
  • 2
  • 3

6.3 而在file.te定义了system_data_file文件属于data_file_type类型,因此recovery也是不能操作data下面的文件


file.te:56:type system_data_file, file_type, data_file_type;  

 
 
  • 1
  • 2
  • 3

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 };  
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

七、添加 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;

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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;

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

7.3 在device/sprd/scx20/common/sepolicy/untrusted_app.te 文件中添加:


allow untrusted_app adc_device:chr_fileoperate;
 
 
  • 1
  • 2

operate为赋予的权限。

注:

mlstrustedsubject:这一attribute包含了所有能越过MLS检查的主体domain。

mlstrustedobject:这一attribute包含了所有能越过MLS检查的客体type

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值