【问题标题】:How do I detect if SELinux is enabled in an android application?如何检测是否在 android 应用程序中启用了 SELinux?
【发布时间】:2013-09-10 20:13:00
【问题描述】:

我正在尝试使用 Google 在我的 android 应用程序中发布的 SecureRandom 解决方法: http://android-developers.blogspot.com/2013/08/some-securerandom-thoughts.html

这项工作涉及写入(和读取)/dev/urandom。但是,三星似乎以一种阻止应用程序访问 /dev/urandom 的方式启用了 SELinux。

我没有这些设备之一,所以除了在 Android 市场上推出解决方法之外,我很难测试解决方案,但这似乎不是我能做的错误使用 try catch 块捕获。 File.canRead 和 canWrite 似乎也返回 true。您可以在以下类中的 supportedOnThisDevice 方法中看到我对解决方法的尝试: PRNGFixes.java

我正在寻找一种可靠的方法来检测我是否是这样的设备,如果是,请不要应用 Google SecureRandom 解决方法。

【问题讨论】:

    标签: android selinux


    【解决方案1】:

    这是我检查 SELinux 是否处于强制模式的方法 - 可以通过任何 Shell 脚本完成,而不依赖于 RootTools:

    private static boolean isSELinuxEnforcing() {
        try {
            CommandCapture command = new CommandCapture(1, "getenforce");
            RootTools.getShell(false).add(command).waitForFinish();
            boolean isSELinuxEnforcing = command.toString().trim().equalsIgnoreCase("enforcing");
            return isSELinuxEnforcing;
        } catch (Exception e) {
            // handle exception
        }
        return false;
    }
    

    【讨论】:

      【解决方案2】:

      我听说三星开始出货将 SELinux 策略设置为 Enforce 的设备,但我不知道这是否属实。据我所知,4.3 上的大多数设备仍将其设置为许可。

      根据谷歌的说法,"SELinux reinforcement is invisible to users and developers, and adds robustness to the existing Android security model while maintaining compatibility with existing applications." 所以你可能需要检查系统属性或通过 shell 测试才能确定。

      如果您可以让某人向您发送他们的 build.prop,您可以通过System.getProperty("ro.build.selinux") 比较他们的 ro.build.selinux 属性来捕获它, 但您还需要验证您是否能够更直接地访问它,以防它不可靠或 getProperty() 在未来的更新中被破坏。

      Root(SELinux 上的系统用户)是另一个可用选项,但无论哪种方式,基于 shell 的解决方案都可能是您的最佳选择。

      【讨论】:

        【解决方案3】:
        System.getProperty("ro.build.selinux")
        

        在三星 S4 Android 4.3 上不适用于我。所以我写了这个

        private static final int JELLY_BEAN_MR2 = 18;
        
        public static boolean isSELinuxSupported() {
                // Didnt' work
                //String selinuxStatus = System.getProperty(PROPERTY_SELINUX_STATUS);
                //return selinuxStatus.equals("1") ? true : false;
        
                String selinuxFlag = getSelinuxFlag();
        
                if (!StringUtils.isEmpty(selinuxFlag)) {
                    return selinuxFlag.equals("1") ? true : false;
                } else {
                    // 4.3 or later ?
                    if(Build.VERSION.SDK_INT >= JELLY_BEAN_MR2) {
                        return true;
                    }
                    else {
                        return false;
                    }
                }       
        }
        
        public static String getSelinuxFlag() {
                String selinux = null;
        
                try {
                    Class<?> c = Class.forName("android.os.SystemProperties");
                    Method get = c.getMethod("get", String.class);
                    selinux = (String) get.invoke(c, "ro.build.selinux");
                } catch (Exception ignored) {
                }
        
                return selinux;
        }
        

        【讨论】:

        • 这个方法的返回值是多少?
        • isSELinuxSupported 返回 true(如果 SELinux 存在)或 false
        • SELinux 在我的一些设备上强制执行,但 ro.build.selinux 没有价值,所以这不可靠。
        【解决方案4】:

        如果您可以访问框架

        import android.os.SELinux;
        
        SELinux.isSELinuxEnforced();
        

        【讨论】:

          【解决方案5】:

          从 Jellybean MR2 及更高版本开始,大多数设备都将在其设备上启用 SELinux,但如果您与 OEM 合作或从事平台工作,这可能不一定正确。

          我用来验证的方法是使用 getenforce shell 命令:

          public boolean isSeLinuxEnforcing() {
              StringBuffer output = new StringBuffer();
              Process p;
              try {
                  p = Runtime.getRuntime().exec("getenforce");
                  p.waitFor();
                  BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
                  String line = "";
                  while ((line = reader.readLine())!= null) {
                      output.append(line);
                  }
              } catch (Exception e) {
                  Log.e(TAG, "OS does not support getenforce");
                  // If getenforce is not available to the device, assume the device is not enforcing
                  e.printStackTrace();
                  return false;
              }
              String response = output.toString();
              if ("Enforcing".equals(response)) {
                  return true;
              } else if ("Permissive".equals(response)) {
                  return false;
              } else {
                  Log.e(TAG, "getenforce returned unexpected value, unable to determine selinux!");
                  // If getenforce is modified on this device, assume the device is not enforcing
                  return false;
              }
          }
          

          似乎大多数设备只有在在强制状态下运行时才为 selinux 编写系统属性。您还可以检查以下属性:ro.boot.selinux 以查看内核是否在当前构建中传入了许可参数。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-12-06
            • 1970-01-01
            • 1970-01-01
            • 2023-03-23
            • 2017-06-05
            • 1970-01-01
            • 1970-01-01
            • 2016-06-26
            相关资源
            最近更新 更多