1. 程式人生 > >Android之動態修改system/etc目錄下檔案的一種實現方式-SELinux

Android之動態修改system/etc目錄下檔案的一種實現方式-SELinux

在沒有root的前提下,system分割槽為只讀,若要動態修改該分割槽下的檔案,可以按照下面流程實現:

1.寫執行指令碼,這裡以修改system/etc/hosts檔案為例,在/device/mediatek/mt67xx目錄下建立名為modifyhosts.sh的檔案,檔案內容如下:

# 修改system分割槽為可讀寫
mount -o remount,rw /system

# 修改內容,可以執行拷貝、刪除、寫入等操作
echo 127.0.0.1 localhost > /etc/hosts

# 修改hosts檔案許可權
chmod 644 /etc/hosts

# 修改system分割槽為只讀
mount -o remount,ro /system

2.配置指令碼編譯後的路徑,在/device/mediatek/mt67xx/device.mk檔案中配置指令碼編譯後的路徑:注意:指令碼檔案字尾可以不要
PRODUCT_COPY_FILES += $(LOCAL_PATH)/modifyhosts.sh:system/bin/modifyhosts.sh

3.配置啟動指令碼的服務,/system/core/rootdir/init.rc檔案為系統啟動初始化檔案,最先載入,配置sh指令碼啟動服務:
service remount-sys /system/bin/modifyhosts.sh
# 這個服務不能通過啟動一類服務來啟動,只能單獨以名字來啟動
disabled
# 服務只執行一次,退出後不再重啟
oneshot

4.定義主體的type,在/external/sepolicy目錄下新建一個modifyhosts.te檔案,在該檔案中定義一個名為modifyhosts的domain以及名為modifyhosts_exec的type:
# 將domain設定為modifyhosts的屬性,表明modifyhosts是用來描述程序的安全上下文的
type modifyhosts, domain;
# 除錯時先加上下面這一句,它會打印出所有需要申請的許可權,除錯完成後刪除該語句。
permissive modifyhosts;
# 將exec_type和file_type設定為modifyhosts_exec的屬性,表明modifyhosts_exec是用來描述可執行檔案的安全上下文的
type modifyhosts_exec, exec_type, file_type;
init_daemon_domain(modifyhosts)

5.定義客體的type,remount-sys程序對應的可執行檔案是/system/bin/modifyhosts.sh,則在/external/sepolicy/file_contexts檔案中新增/system/bin/modifyhosts.sh檔案的安全上下文:
/system/bin/modifyhosts.sh u:object_r:modifyhosts_exec:s0

也就是說,客體/system/bin/modifyhosts.sh檔案的type是modifyhosts_exec。

6.新增SELinux許可權,由於不知道需要新增哪些許可權,故按上面5個步驟操作完後,可以先編譯版本刷機,之後在adb shell 下執行:

setprop ctl.start remount-sys
dmesg > /data/data/a.txt

匯出執行log到指定目錄下,根據log內容新增指定許可權,dmesg是列印kernel層log的命令。

log內容如下:

[  659.805760] .(0)[269:logd.auditd]type=1400 audit(1481859095.080:77): avc: denied { remount } for pid=5080 comm="mount" scontext=u:r:modifyhosts:s0 tcontext=u:object_r:labeledfs:s0 tclass=filesystem permissive=1

從log可知,需要為modifyhosts.te檔案新增許可權,SELinux許可權規則語句一般如下:
allow 主體的Type 客體的Type:操作 許可權1;
或者:
allow 主體的Type 客體的Type:操作 { 許可權1 許可權2 };

可以從log中獲取四個引數得出最後的規則:
allow modifyhosts labeledfs:filesystem { remount };

新增許可權後再次編譯版本,如果編譯失敗,且失敗原因如下:
libsepol.report_failure: neverallow on line 284 of external/sepolicy/domain.te (or line 5613 of policy.conf) violated by allow modifyhosts labeledfs:filesystem { remount };
libsepol.check_assertions: 1 neverallow failures occurred

這是因為系統在domain.te檔案中定義了全域性的neverallow策略,與modifyhosts.te中allow的策略有衝突,此時請確認該許可權是否是服務所必須的,如果是必須的可以在/external/sepolicy/domain.te檔案中有衝突的neverallow語句中新增自己為例外:
neverallow { domain -kernel -init -recovery -vold -zygote
    -modifyhosts # add by zhangyongfei
 } { fs_type -sdcard_type }:filesystem { mount remount relabelfrom relabelto };

7.通過前面6步之後就除錯好了,下面該在系統程式碼中新增真正呼叫該服務的程式碼了,這裡可以在系統服務(AMS、PMS等)中呼叫下面方法啟動該服務:
// remount-sys是在init.rc中自定義的服務名
SystemProperties.set("ctl.start","remount-sys");