OSDN Git Service

Set packages.list context to packages_list_file.
authorFlorian Mayer <fmayer@google.com>
Thu, 21 Mar 2019 13:57:42 +0000 (13:57 +0000)
committerFlorian Mayer <fmayer@google.com>
Wed, 3 Apr 2019 17:28:16 +0000 (18:28 +0100)
Bug: 123186697

Test: adb shell su root ls -lZd /data/system/packages.list
-rw-r----- 1 system package_info u:object_r:packages_list_file:s0 35816 2019-04-02 14:17 /data/system/packages.list

Change-Id: I62ae03b5c2acf6c703f2e4c6f49cc68825e3a785

core/java/android/os/SELinux.java
core/jni/android_os_SELinux.cpp
services/core/java/com/android/server/pm/Settings.java

index 8ffafe4..f007dff 100644 (file)
@@ -39,6 +39,13 @@ public class SELinux {
     private static final int SELINUX_ANDROID_RESTORECON_DATADATA = 16;
 
     /**
+     * Get context associated with path by file_contexts.
+     * @param path path to the regular file to get the security context for.
+     * @return a String representing the security context or null on failure.
+     */
+    public static final native String fileSelabelLookup(String path);
+
+    /**
      * Determine whether SELinux is disabled or enabled.
      * @return a boolean indicating whether SELinux is enabled.
      */
index 8cb1078..236ee61 100644 (file)
 #include "selinux/android.h"
 #include <errno.h>
 #include <memory>
+#include <atomic>
 #include <nativehelper/ScopedLocalRef.h>
 #include <nativehelper/ScopedUtfChars.h>
 
 namespace android {
+namespace {
+std::atomic<selabel_handle*> sehandle{nullptr};
+
+selabel_handle* GetSELabelHandle() {
+    selabel_handle* h = sehandle.load();
+    if (h != nullptr) {
+        return h;
+    }
+
+    h = selinux_android_file_context_handle();
+    selabel_handle* expected = nullptr;
+    if (!sehandle.compare_exchange_strong(expected, h)) {
+        selabel_close(h);
+        return sehandle.load();
+    }
+    return h;
+}
+
+}
 
 struct SecurityContext_Delete {
     void operator()(security_context_t p) const {
@@ -60,6 +80,44 @@ static jboolean isSELinuxEnforced(JNIEnv *env, jobject) {
     return (security_getenforce() == 1) ? true : false;
 }
 
+static jstring fileSelabelLookup(JNIEnv* env, jobject, jstring pathStr) {
+    if (isSELinuxDisabled) {
+        ALOGE("fileSelabelLookup => SELinux is disabled");
+        return NULL;
+    }
+
+    if (pathStr == NULL) {
+      ALOGE("fileSelabelLookup => got null path.");
+      jniThrowNullPointerException(
+          env, "Trying to get security context of a null path.");
+      return NULL;
+    }
+
+    ScopedUtfChars path(env, pathStr);
+    const char* path_c_str = path.c_str();
+    if (path_c_str == NULL) {
+        ALOGE("fileSelabelLookup => Got null path");
+        jniThrowNullPointerException(
+            env, "Trying to get security context of a null path.");
+        return NULL;
+    }
+
+    auto* selabel_handle = GetSELabelHandle();
+    if (selabel_handle == NULL) {
+        ALOGE("fileSelabelLookup => Failed to get SEHandle");
+        return NULL;
+    }
+
+    security_context_t tmp = NULL;
+    if (selabel_lookup(selabel_handle, &tmp, path_c_str, S_IFREG) != 0) {
+      ALOGE("fileSelabelLookup => selabel_lookup for %s failed: %d", path_c_str, errno);
+      return NULL;
+    }
+
+    Unique_SecurityContext context(tmp);
+    return env->NewStringUTF(context.get());
+}
+
 static jstring getFdConInner(JNIEnv *env, jobject fileDescriptor, bool isSocket) {
     if (isSELinuxDisabled) {
         return NULL;
@@ -354,6 +412,7 @@ static const JNINativeMethod method_table[] = {
     { "native_restorecon"        , "(Ljava/lang/String;I)Z"                       , (void*)native_restorecon},
     { "setFileContext"           , "(Ljava/lang/String;Ljava/lang/String;)Z"      , (void*)setFileCon       },
     { "setFSCreateContext"       , "(Ljava/lang/String;)Z"                        , (void*)setFSCreateCon   },
+    { "fileSelabelLookup"        , "(Ljava/lang/String;)Ljava/lang/String;"       , (void*)fileSelabelLookup},
 };
 
 static int log_callback(int type, const char *fmt, ...) {
index 6a1f223..f0f9f72 100644 (file)
@@ -60,6 +60,7 @@ import android.os.Message;
 import android.os.PatternMatcher;
 import android.os.PersistableBundle;
 import android.os.Process;
+import android.os.SELinux;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -2650,6 +2651,24 @@ public final class Settings {
     }
 
     void writePackageListLPr(int creatingUserId) {
+        String filename = mPackageListFilename.getAbsolutePath();
+        String ctx = SELinux.fileSelabelLookup(filename);
+        if (ctx == null) {
+            Slog.wtf(TAG, "Failed to get SELinux context for " +
+                mPackageListFilename.getAbsolutePath());
+        }
+
+        if (!SELinux.setFSCreateContext(ctx)) {
+            Slog.wtf(TAG, "Failed to set packages.list SELinux context");
+        }
+        try {
+            writePackageListLPrInternal(creatingUserId);
+        } finally {
+            SELinux.setFSCreateContext(null);
+        }
+    }
+
+    private void writePackageListLPrInternal(int creatingUserId) {
         // Only derive GIDs for active users (not dying)
         final List<UserInfo> users = UserManagerService.getInstance().getUsers(true);
         int[] userIds = new int[users.size()];