2016-03-15 55 views
2

我的應用程序針對紮根的Android設備,它具有root權限並且需要訪問目錄/dev/input,但它爲什麼會拋出opendir failed, Permission denied甚至/dev/input已經是chmod777爲什麼我的Android應用程序(具有root權限)無法訪問/ dev/input?

我用下面的代碼來獲得root權限:

Process root = Runtime.getRuntime().exec("su"); 

並使用下面的代碼來改變/dev/input權限:

Shell.runCommand("chmod 777 /dev/input"); 

兩個以上兩個步驟是成功的,但爲什麼我的應用程序仍然無法訪問它?從搜索中,有人說應用程序的運行時權限與文件系統中文件的權限無關。 Android運行時的權限系統是什麼?我如何讓應用程序能夠訪問/dev/input

增加:

我的測試環境是安卓5.1.1,代碼的主要部分是:

jint Java_com_foo_funnyapp_Native_scanInputDevicesJNI(JNIEnv* env, jclass clazz) 
{ 
    const char *dirname = "/dev/input"; 

    DIR *dir; 
    dir = opendir(dirname); // opendir failed, Permission denied 
    if(dir == NULL) 
     return -1; 

    ...... 

    return 0; 
} 

SELinux的錯誤從/prog/kmsg

<36>[19700411_05:32:43.957165]@0 type=1400 audit(8631163.939:1105): avc: denied { write } for pid=15706 comm="app_process64_o" name="[email protected]@boot.art" dev="mmcblk0p43" ino=442379 scontext=u:r:shell:s0 tcontext=u:object_r:dalvikcache_data_file:s0 tclass=file permissive=0 
<11>[19700411_05:32:44.118202]@0 init: untracked pid 15674 exited with status 0 
<11>[19700411_05:32:44.202288]@0 init: untracked pid 15704 exited with status 224 
<36>[19700411_05:32:44.225334]@0 type=1400 audit(8631164.209:1106): avc: denied { read } for pid=15734 comm="Thread-111" name="input" dev="tmpfs" ino=12525 scontext=u:r:untrusted_app:s0 tcontext=u:object_r:input_device:s0 tclass=dir permissive=0 
<36>[19700411_05:32:44.332135]@0 type=1400 audit(8631164.319:1107): avc: denied { write } for pid=15742 comm="app_process64_o" name="[email protected]@boot.art" dev="mmcblk0p43" ino=442379 scontext=u:r:shell:s0 tcontext=u:object_r:dalvikcache_data_file:s0 tclass=file permissive=0 
+1

無論你想要做什麼都可能是一個壞主意。您可能會碰到selinux而不是unix樣式的權限問題。 –

+0

檢查'dmesg'(或'cat/proc/kmsg')的輸出是否存在selinux錯誤消息。另外,運行「su」不會改變當前進程的權限,所以從你的問題來看,你是否真的以root身份運行並不是完全清楚。 – fadden

+0

@ChrisStratton,謝謝你指出!但是我能夠修改我的應用的SELinux策略嗎?從搜索中看,我看不到,因爲SELinux策略被刻錄到操作系統映像中。但有一個奇怪的現象是,我安裝並運行Google Play中的另一個應用程序,它可以訪問我所知道的/ dev/input,然後我的應用程序就可以訪問/ dev/input。我不知道該應用程序做了什麼。 – Suge

回答

3

正如有人指出,在評論中,除了Linux文件權限之外,現代Android還有許多額外的防禦層。其中之一是SELinux。

即使使用提升的權限,解決SELinux的問題是rather complex - 它是專門爲防止這種情況而設計的。所有Android SELinux設置都存儲在修改後的sepolicy格式的單個文件中。該文件是隻讀系統映像的一部分,修補它基本上等同於生根設備。幾乎所有的人都是超級用戶應用程序的開發人員,比如SuperSu的作者或this one

與其試圖自己克服SELinux,我建議您利用已安裝的su應用程序所做的任何操作。例如,SuperSu在不受限制的SELinux上下文中運行命令(見鏈接到上面的Chainfire的站點),就好像SELinux不存在它一樣。這使您可以通過su運行專門的二進制文件來克服SELinux,它爲您完成骯髒的工作。

不幸的是,很少有公共的高級API可用於這種純本地二進制文件。你可以使用Linux內核系統調用和一些C庫函數......就是這樣。幸運的是,如果您只想打開一堆受保護的文件,則不需要在本地幫助器二進制文件中移動大量邏輯。相反,你可以使用一個「開放的服務器」庫,如this one

Context context = ... 

try (FileDescriptorFactory factory = FileDescriptorFactory.create(context); 
    ParcelFileDescriptor fd = factory.open("/dev/input", 2)) 
{ 
    // the file descriptor is yours, as if you have gotten it by 
    // calling ParcelFileDescriptor#open 
    // You can use it from Java or pass to native code to read/write/ioctl on it 
    ... 
} catch (FactoryBrokenException oups) { 
    // most likely the root access being denied 
    ... 
} catch (IOException ioerr) { 
    ... 
} 

免責聲明:我是鏈接庫的作者。

「開放服務器」的概念很簡單:

  1. 普通Android應用程序創建一個Linux domain socket
  2. 普通Android應用程序通過系統將啓動二進制「蘇」
  3. 二進制連接到插座
  4. 該二進制文件讀取應用程序寫入套接字的文件的名稱並將其打開
  5. 二進制文件通過相同的套接字將文件的文件描述符發送到應用程序被稱爲"file descriptor passing"

這個絕招是怎麼回事,只要安裝工作「蘇」的應用程序成功地克服了SELinux和提供無限制的上下文命令正在通過它運行。我所知道的所有現代的都是。


編輯:這個答案已經寫在不久前。最新的Android sepolicy格式不再被視爲「修改」,它們的更改已成功實施(幽默地導致創建又一個後向不兼容的sepolicy格式)。上面鏈接的圖書館一般工作正常,但它的功能已被現代SEAndroid政策進一步限制,因此您可能對new iteration感興趣。由於事實上,除了在open期間的標準Unix檢查之外,SELinux策略對每個個體執行額外檢查read/write,使用共享內存和Linux管道仔細解決策略可能更明智,而不是通過原始描述符來電。

+0

我很驚訝得到這樣一個好的和詳細的答案,非常感謝你! – Suge

相關問題