Set packages.list context to packages_list_file.

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
This commit is contained in:
Florian Mayer
2019-03-21 13:57:42 +00:00
parent 90cd3d6d48
commit d4db997a81
3 changed files with 85 additions and 0 deletions

View File

@@ -38,6 +38,13 @@ public class SELinux {
private static final int SELINUX_ANDROID_RESTORECON_FORCE = 8;
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.

View File

@@ -24,10 +24,30 @@
#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, ...) {

View 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()];