1. 程式人生 > >Android 7.1 SElinux許可權問題解決方案——編寫APP,通過暗碼讀取TP fw版本

Android 7.1 SElinux許可權問題解決方案——編寫APP,通過暗碼讀取TP fw版本

1.在底層,建立節點並給予訪問節點的許可權
2.在頂層新增暗碼和呼叫的函式
3.編寫app ReadHwid
4.編寫app完後,發現通過電話撥號鍵 暗碼*#850208# 顯示:TP SW Version hello world!
5.許可權解決方案
附加知識點

1、在底層,建立節點並給予訪問節點的許可權

kernel/msm-3.18/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c

	__ATTR(buildid, (S_IRUGO | S_IWUSR | S_IWGRP),
			synaptics_rmi4_f01_buildid_show,
			synaptics_rmi4_store_error),
static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev,struct device_attribute *attr, char *buf)
{
	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
	return snprintf(buf, PAGE_SIZE, "firmware_id:%u\n",
			rmi4_data->firmware_id);
}
static inline ssize_t synaptics_rmi4_store_error(struct device *dev,struct device_attribute *attr, const char *buf, size_t count)
{
	dev_warn(dev, "%s Attempted to write to read-only attribute %s\n",
			__func__, attr->attr.name);
	return -EPERM;
}

解析:buildid // 為節點名
S_IRUGO | S_IWUSR | S_IWGRP //使用者可讀|使用者可寫|小組使用者可讀可寫許可權
synaptics_rmi4_f01_buildid_show //顯示函式,cat該檔案時,此函式被呼叫
synaptics_rmi4_store_error //寫函式,echo內容到該檔案時,此函式被呼叫

通過adb可以檢視到節點和TP FW的版本號:
在這裡插入圖片描述

2、在頂層新增暗碼和呼叫的函式 /Halo/packages/apps/Dialer/src/com/android/dialer/SpecialCharSequenceMgr.java

@@ -81,6 +81,7 @@public class SpecialCharSequenceMgr {
     private static final String PRL_VERSION_DISPLAY = "*#0000#";
 
     private static final int IMEI_14_DIGIT = 14;
+    private static final String HWVESION = "*#850208#";
@@ -159,7 +160,8 @@ public class SpecialCharSequenceMgr {
                 || handleQSensorTest(context,dialString)
                 || handleEngineerTest(context, dialString)
                 || handleDeadCode(context, dialString)
-                || handleSecretCode(context, dialString)) {
+                || handleSecretCode(context, dialString)
+                               || handleRead_hwid(context, dialString)) {
             return true;
         }
@@ -459,24 +461,40 @@public class SpecialCharSequenceMgr {
         }
         return false;
     }
+       private static boolean handleRead_hwid(Context context, String input) {
+               if (input.equals(HWVESION)) {
+                       Log.d(TAG, "handleRead_hwid() sending intent to handleRead_hwid app");
+                       Intent handleRead_hwid = new Intent();
+                       try {
+                               ComponentName mComponentName = new ComponentName(
+                                               "com.android.ReadHwid",
+                                               "com.android.ReadHwid.ReadHwid");
+                               handleRead_hwid.setComponent(mComponentName);
+                               context.startActivity(handleRead_hwid);
+                       } catch (ActivityNotFoundException e) {
+                               Log.e(TAG, "startActivity() failed: " + e);
+                       }
+                       return true;
+               }
+               return false;
+       }

3、編寫app ReadHwid

Halo/packages/apps/ReadHwid

--- a/Android.mk
+++ b/Android.mk
@@ -7,7 +7,7 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_PACKAGE_NAME := ReadHwid
-
+LOCAL_CERTIFICATE := platform
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.ReadHwid"
+    android:sharedUserId="android.uid.system"
--- a/src/com/android/ReadHwid/ReadHwid.java
+++ b/src/com/android/ReadHwid/ReadHwid.java
@@ -22,12 +22,11 @@ public class ReadHwid extends Activity {
         FileReader fr ;
         
         try {
-            File readFile = new File("/sys/bus/i2c/devices/12-004a/plugin_tag");
+            File readFile = new File("/sys/bus/i2c/devices/12-004b/input/input3/buildid");
            if (!readFile.exists()) {
                readFile = new File("/proc/gt1x_cfg");
-               if (!readFile.exists()) {
-                   readFile = new File("/sys/bus/i2c/devices/12-0038/ftstpfwver");
-               }
+       
+       
            }

4.編寫完後,發現通過電話撥號鍵 暗碼*#850208# 顯示:TP SW Version hello world!

顯然沒有讀出來buildid 。
cmdline 檢視,adb臨時賦予許可權,adb 中設定selinux為permission模式:
在這裡插入圖片描述
再撥號*#850208# 介面顯示 :TP SW Version firmware_id : 2810726
在這裡插入圖片描述
從而知道是因為ansroid selinux許可權問題。

C:\Users\550134>adb shell
G0335D:/ # dmesg | grep avc
出現錯誤的kernel log:
[  476.686110] type=1400 audit(4216828.505:1596): avc: denied { read } for pid=4240 comm="ndroid.ReadHwid" name="buildid" dev="sysfs" ino=38920 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:sysfs:s0 tclass=file permissive=0
檢視logcat log:
02-17 04:04:08.399  4715  4715 W ndroid.ReadHwid: type=1400 audit(0.0:1600): avc: denied { read } for name="buildid" dev="sysfs" ino=38920 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:sysfs:s0 tclass=file permissive=0
02-17 04:04:08.405  4715  4715 W System.err: java.io.FileNotFoundException: /sys/bus/i2c/devices/12-004b/input/input3/buildid (Permission denied)

也可以使用命令ps -Z 檢視程序的安全上下文,結果com.android.ReadHwid 是untrusted app
在這裡插入圖片描述
我們要做就是賦予使用者能訪問com.android.ReadHwid 的讀寫許可權。有兩種方案,1)將untrusted app變為系統app,然後賦予讀寫許可權 1)直接給這個untrusted app, com.android.ReadHwid 給讀寫許可權

解析:
setenforce 0 //設定SELinux 成為permissive模式(SELinux開啟,但對違反selinux規則的行為只記錄,不會阻止)
setenforce 1 //設定SELinux 成為enforcing模式 (SELinux開啟)
getenforce //獲取SELinux狀態(permissive,enforcing,disabled)

avc: denied { read } //表示沒有讀許可權
comm=“ndroid.ReadHwid” //程序名
scontext=u:r:untrusted_app //源型別為 不信任的app
tcontext=u:object_r:sysfs //目標型別為sysfs
tclass=file //訪問型別

5、許可權解決方案:

方案一:要將untrusted app 變為system app 需要進行兩處修改

1)、在AndroidMainefest.xml中配置,新增語句:android:sharedUserId=”android.uid.system”; //將untrusted APP 配置為系統APP 。G0335D_2/Halo/packages/app/ReadHwid/AndroidManifest.xml
2)、LOCAL_CERTIFICATE := platform //使用platform實現簽名 。G0335D_2/Halo/packages/app/ReadHwid/Android.mk
變為系統app,adb 檢視:
在這裡插入圖片描述
補充:SELinux(或SEAndroid)將app劃分為主要三種類型(根據user不同,也有其他的domain型別):
(1)untrusted_app 第三方app,沒有Android平臺簽名,沒有system許可權
(2)platform_app有Android平臺簽名,沒有system許可權
(3)system_app有Android平臺簽名和system許可權
系統應用使用platform金鑰進行簽名,預設情況下,在Android原始碼中一共有四種金鑰:platform、share、media、testkey。
platform:核心平臺上的所有包(e.g: System UI、Setting、Phone、Bluetooth等)使用platform金鑰簽名。
share:搜尋和聯絡人相關的包使用shared金鑰簽名。
media:相簿和媒體相關的包使用media金鑰簽名。
testkey(releasekey):沒有顯示在自身makefile檔案中指定金鑰的包使用testkey(releasekey)金鑰簽名。
3)、新增讀寫許可權,需要修改以下四個檔案

(1)device/qcom/sepolicy/common/file.te
+#for TP FW id
+type sysfs_buildid, fs_type, sysfs_type;

(2)device/qcom/sepolicy/common/file_contexts
+# for TP fw id
+/sys/devices/soc/75ba000.i2c/i2c-12/12-004b/input/input3/buildid u:object_r:sysfs_buildid:s0

(3)device/qcom/sepolicy/common/system_app.te
+allow system_app sysfs_buildid:file rw_file_perms;

(4)system/core/rootdir/init.rc
+#for TP FW id
+chown system system /sys/devices/soc/75ba000.i2c/i2c-12/12-004b/input/input3/buildid

解析:allow 源型別 目標型別:訪問型別 {操作許可權};
file.te //定義目標型別sysfs_buildid 否則會出現sysfs_buildid無法識別。
file_contexts // 檔案上下文,將實際節點和目標型別繫結
system_app.te //系統應用,system_app程序能夠擁有對sysfs_buildid的這個字元裝置的讀寫許可權
system_server.te //系統應用服務,使得目標型別(type)和 源型別(domain) 繫結,並賦予目標型別讀寫許可權
init.rc //賦予系統程序可以訪問節點的許可權

補充點:app 對應的te檔案修改
system_app -> device/qcom/sepolicy/common/system_app.te
untrusted_app ->device/qcom/sepolicy/common/
platform_app ->device/qcom/sepolicy/common/platform_app.te

方案二:直接給這個untrusted app, com.android.ReadHwid 給讀寫許可權

(1)device/qcom/sepolicy/common/file.te
+#for TP FW id
+type sysfs_buildid, fs_type, sysfs_type;
(2)device/qcom/sepolicy/common/file_contexts
+# for TP fw id
+/sys/devices/soc/75ba000.i2c/i2c-12/12-004b/input/input3/buildid u:object_r:sysfs_buildid:s0
(3)device/qcom/sepolicy/common/untrusted_app.te
+#for TP FW id
+allow untrusted_app sysfs_buildid:file rw_file_perms;
(5)system/core/rootdir/init.rc
+#for TP FW id
+chown system system /sys/devices/soc/75ba000.i2c/i2c-12/12-004b/input/input3/buildid

附加知識點

TP synaptics 節點路徑是相等的
在這裡插入圖片描述
該路徑下所有節點
在這裡插入圖片描述