【问题标题】:Android permission denied when reading /proc/self/exe from non-main thread从非主线程读取 /proc/self/exe 时,Android 权限被拒绝
【发布时间】:2015-04-19 21:07:26
【问题描述】:

我正在尝试获取 /proc/self/exe 的规范路径。当我在主线程上执行此操作时,它可以工作,当我在另一个线程上执行此操作时,它会因 IOException:“Permission denied”而崩溃:

                   DBG  E  Thread: main
                        E  Path: /system/bin/app_process32
                        E  Thread: Thread-21656
            System.err  W  java.io.IOException: Permission denied
                        W      at java.io.File.canonicalizePath(Native Method)
                        W      at java.io.File.getCanonicalPath(File.java:414)
                        W      at java.io.File.getCanonicalFile(File.java:428)
                        W      at com.quanturium.testbugprocselfexe.MyActivity.getPathOfExecutable(MyActivity.java:36)
                        W      at com.quanturium.testbugprocselfexe.MyActivity.access$000(MyActivity.java:12)
                        W      at com.quanturium.testbugprocselfexe.MyActivity$1.run(MyActivity.java:26)
                        W      at java.lang.Thread.run(Thread.java:818)

代码:

@Override
protected void onCreate (Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    getPathOfExecutable(); // Works as expected

    new Thread(new Runnable() {
        @Override
        public void run ()
        {
            getPathOfExecutable(); // Trigger the IOException: Permission denied
        }
    }).start();
}

private void getPathOfExecutable()
{
    try
    {
        Log.e("DBG", "Thread: " + Thread.currentThread().getName());
        Log.e("DBG", "Path: " + new File("/proc/self/exe").getCanonicalFile().getPath());
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}

只有在 build.gradle 文件中将 debuggable 配置为 false 时才会发生此错误

试用代码:https://github.com/quanturium/TestBugProcSelfExe

这是一个错误还是预期的行为?获取当前可执行文件路径的解决方法是什么?

【问题讨论】:

  • 每当我遇到权限问题时,尽管权限不同,logcat 都会在打印异常之前准确提到缺少哪个权限。异常上方 10 行左右的内容是什么?
  • 不,这是整个错误
  • 这可能是整个错误,但是当我遇到issues reading Alarm names 时,有一个不同的日志条目与告诉我需要READ_EXTERNAL_STORAGE 权限的错误分开。
  • 相信我,这就是一切。
  • canonicalizePath() 方法,以几个包装器为模,是这样的:android.googlesource.com/platform/libcore/+/lollipop-release/…(假设您使用的是 Android 5.0)。我的猜测是 readlink() 因某种原因失败(“self”是一个符号链接),但我不知道为什么会这样。

标签: java android linux system


【解决方案1】:

代码会阻塞吗?如果没有,则在主线程中运行它应该没有任何后果。但是,您可以从另一个线程执行此操作,方法是:

Context.runOnUiThread(new Runnable() {
    getPathOfExecutable();
});

这是我能想到的最干净的解决方法,没有编辑文件的权限(无论如何,如果不在主线程上运行代码,您就无法获得路径),因为您具有 r/w 权限/proc/self/exe。

这很奇怪,我还在研究android上不同线程的权限差异。

如果你可以让它在主线程中工作,我的意见是只在主线程中进行,不要太担心优化,因为不同线程的性能没有什么不同。

【讨论】:

  • 是的,这段代码可以工作,但在主线程上执行。怀疑 canRead() 在主线程上返回 true,在另一个线程上返回 false。
  • 嗯,ls -al /process/self/exe 的输出是什么?链接指向的文件上的相同命令的输出也是?
  • 它确实也使用此代码在主线程上运行(这就是我问它是否阻塞的原因)。我不确定为什么权限因线程而异,所以这可能是最好的方法。
  • lrwxrwxrwx u0_a416 u0_a416 2015-02-20 16:36 exe -> /system/bin/toolbox 不确定我理解你的第二个问题。
  • /proc/self/exe 的权限似乎不错。请注意 /proc/self/exe 是指向 /system/bin/toolbox 的链接? ls -al /system/bin/toolbox 的输出是什么?
【解决方案2】:

获取当前可执行文件路径的解决方法是什么?

由于每个 Android 应用都是从 Zygote 派生出来的,Zygote 是 /system/bin/app_process 在系统启动时创建的虚拟机时的第一个 Java vm 进程。

如果您尝试从您的 Android 应用中读取 /proc/self/exe,实际的可执行文件将是 /system/bin/app_process。即使您在应用程序的主线程之外阅读此内容,结果也是一样的,并且理论上不会出现权限错误。

你问的问题有点奇怪,我在Android 2.3.3上用下面的代码测试过,效果很好。

new Thread() {

    /* (non-Javadoc)
     * @see java.lang.Thread#run()
     */
    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        try {
            Log.d(TAG, new File("/proc/self/exe").getCanonicalFile().getPath());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}.start();

【讨论】:

  • 我想在使用原生 C 的 JNI 库中将其作为命令行读取。java 中也发生了同样的错误(IO 权限被拒绝),我决定将 java 放入其中以简化。是的,它适用于 android 2.3。有人建议 SE Linux 可能是原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
  • 2017-09-06
  • 2016-12-18
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多