Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么可以';t我的Android应用程序(具有root权限)访问/dev/input?_Android_Linux_Android Ndk_Root_Selinux - Fatal编程技术网

为什么可以';t我的Android应用程序(具有root权限)访问/dev/input?

为什么可以';t我的Android应用程序(具有root权限)访问/dev/input?,android,linux,android-ndk,root,selinux,Android,Linux,Android Ndk,Root,Selinux,我的应用程序针对有根的Android设备,它有根权限,需要访问目录/dev/input,但为什么它抛出opendir失败,权限被拒绝甚至/dev/input已经被chmod转到777 我使用下面的代码获取根权限: Process root = Runtime.getRuntime().exec("su"); 并使用下面的代码更改/dev/input的权限: Shell.runCommand("chmod 777 /dev/input"); 上面两个步骤都成功了,但是为什么我的应用程序仍然不能

我的应用程序针对有根的Android设备,它有根权限,需要访问目录
/dev/input
,但为什么它抛出
opendir失败,权限被拒绝
甚至
/dev/input
已经被
chmod
转到
777

我使用下面的代码获取根权限:

Process root = Runtime.getRuntime().exec("su");
并使用下面的代码更改
/dev/input
的权限:

Shell.runCommand("chmod 777 /dev/input");
上面两个步骤都成功了,但是为什么我的应用程序仍然不能访问它呢?通过搜索,有人说应用程序的运行时权限与文件系统中文件的权限无关。安卓运行时的权限系统是什么?如何使应用程序能够访问
/dev/input

添加:

我的测试环境是Android 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;
}
来自
/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="system@framework@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="system@framework@boot.art" dev="mmcblk0p43" ino=442379 scontext=u:r:shell:s0 tcontext=u:object_r:dalvikcache_data_file:s0 tclass=file permissive=0
[19700411\u 05:32:43.957165]@0 type=1400审核(8631163.939:1105):avc:denied{write}for pid=15706 comm=“app_process64\u o”name=”system@framework@boot.art“dev=“mmcblk0p43”ino=442379 scontext=u:r:shell:s0 tcontext=u:object\u r:dalvikache\u data\u file:s0 tclass=file permissive=0
[19700411_05:32:44.118202]@0初始:未跟踪的pid 15674已退出,状态为0
[19700411_05:32:44.202288]@0初始:未跟踪的pid 15704已退出,状态为224
[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\u app:s0tcontext=u:object\r:input\u设备:s0tclass=dir permissive=0
[19700411_05:32:44.332135]@0 type=1400 audit(8631164.319:1107):avc:denied{write}for pid=15742 comm=“app_process64_o”name=”system@framework@boot.art“dev=“mmcblk0p43”ino=442379 scontext=u:r:shell:s0 tcontext=u:object\u r:dalvikache\u data\u file:s0 tclass=file permissive=0

正如评论中所指出的,现代Android除了Linux文件权限外,还有许多额外的防御层。其中之一是塞利努克斯

即使拥有提升的特权,围绕SELinux工作也是——它是专门为防止这种情况而设计的。所有Android SELinux设置都存储在一个修改格式的文件中。该文件是只读系统映像的一部分,对其进行修补基本上等于对设备进行根处理。几乎只有从事这项工作的人是超级用户应用程序的开发人员,比如《超级用户》或《超级用户》的作者

我建议您不要试图自己克服SELinux,而是利用已安装的su应用程序所做的一切。例如,SuperSu在不受限制的SELinux上下文中运行传递给它的命令(请参见上面链接到Chainfire的站点),本质上就好像SELinux不存在一样。这允许您通过su运行专门的二进制文件来克服SELinux,这会为您带来麻烦

遗憾的是,可用于此类纯本机二进制文件的公共高级API非常少。您可以使用Linux内核系统调用和一些C库函数。。。就这样。幸运的是,如果您只想打开一堆受保护的文件,那么就不需要在原生助手二进制文件中移动大量逻辑。相反,您可以使用“开放服务器”库,例如:

免责声明:我是链接库的作者

“开放服务器”的概念非常简单:

  • 普通Android应用程序创建一个
  • 普通Android应用程序通过系统“su”发布二进制文件
  • 二进制文件连接到套接字
  • 二进制文件读取应用程序写入套接字的文件名并打开它们
  • 二进制文件通过同一个套接字将所述文件的文件描述符发送到应用程序(该技术也称为)
  • 只要安装的“su”应用程序成功地克服了SELinux,并为通过它运行的命令提供了不受限制的上下文,这种巧妙的技巧就会奏效。我所知道的所有现代的都有



    编辑:这个答案是不久前写的。最新的Android sepolicy格式不再被视为“修改”,它们的更改已经成功地向上游移动(幽默地导致创建了另一种向后不兼容的sepolicy格式)。上面链接的库总体上仍然可以正常工作,但它的功能受到现代SEAndroid政策的进一步限制,因此您可能对它的功能感兴趣。由于SELinux策略对每个
    /
    执行额外的检查,除了在
    打开
    期间执行标准的Unix检查之外,更明智的做法是使用共享内存和Linux管道仔细处理策略,而不是将原始描述符传递给调用者。

    无论你想做什么都可能是个坏主意。您可能遇到selinux而不是unix风格的权限问题。请检查
    dmesg
    (或
    cat/proc/kmsg
    )的输出以了解selinux错误消息。此外,运行“su”不会改变当前进程的权限,因此您的问题并不完全清楚您是否实际以root用户身份运行。@ChrisStratton,谢谢您指出!但是我能为我的应用修改SELinux策略吗?从搜索结果来看,似乎我不能,因为SELinux策略被烧录到操作系统映像中。但有一个奇怪的现象是,在我安装并运行了另一个来自GooglePlay的应用程序后,我知道它可以访问/dev/input,然后我的应用程序就可以访问/dev/input了。我不知道那个应用程序做了什么。@fadden,谢谢你的回答。我已经在帖子内容中添加了主代码和错误消息。看起来它是
    SELinux
    阻止了我的访问,但我如何修改它?我知道Google Play中还有另一个应用程序需要访问
    /dev/input
    ,在我安装并运行它之后,我的应用程序能够访问它,主要的技术是什么?我很惊讶得到这么好的详细答案,非常感谢!
    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) {
        ...
    }