From 256519a529fc7f742dd962d859ab1ab7bdc0b033 Mon Sep 17 00:00:00 2001 From: Wenhao Wang Date: Tue, 11 Jan 2022 22:29:18 -0800 Subject: [PATCH] Add logcat service to track logd access The LogcatManagerService monitors all privileged (in AID_LOG group) access to logd. Only Root and System Server can read the logd data without tracking. Whenever the logd recieve privileged read data request, the request is forwarded to the LogcatManagerService. The LogcatManagerService can approve or decline the request via binder RPC on logd service. The binder call is enforced by sepolicy. That means only LogcatManagerService can use the logd binder service. And only logd can use the logcat binder service. The next step will add user consent requirement for the logd access. Bug: 197901557 Test: Reboot the device, then run "adb logcat" multiple times both during the booting and after the booting. The control flow goes correctly as we expected. Ignore-AOSP-First: pending fix for logcat privacy issue Change-Id: I5e225b65357e7bfacd5c6c9cb4fab5f309803193 --- Android.bp | 1 + core/java/Android.bp | 5 + .../os/logcat/ILogcatManagerService.aidl | 26 ++++ core/java/android/os/logcat/OWNERS | 1 + libs/services/Android.bp | 1 + .../server/logcat/LogcatManagerService.java | 118 ++++++++++++++++++ .../java/com/android/server/logcat/OWNERS | 5 + .../java/com/android/server/SystemServer.java | 5 + 8 files changed, 162 insertions(+) create mode 100644 core/java/android/os/logcat/ILogcatManagerService.aidl create mode 100644 core/java/android/os/logcat/OWNERS create mode 100644 services/core/java/com/android/server/logcat/LogcatManagerService.java create mode 100644 services/core/java/com/android/server/logcat/OWNERS diff --git a/Android.bp b/Android.bp index d64951c3d98f2..03c01169e81f3 100644 --- a/Android.bp +++ b/Android.bp @@ -139,6 +139,7 @@ filegroup { ":libcamera_client_aidl", ":libcamera_client_framework_aidl", ":libupdate_engine_aidl", + ":logd_aidl", ":resourcemanager_aidl", ":storaged_aidl", ":vold_aidl", diff --git a/core/java/Android.bp b/core/java/Android.bp index c9cbef2c9e9a3..897bab429a877 100644 --- a/core/java/Android.bp +++ b/core/java/Android.bp @@ -121,6 +121,11 @@ filegroup { ], } +filegroup { + name: "ILogcatManagerService_aidl", + srcs: ["android/os/logcat/ILogcatManagerService.aidl"], +} + genrule { name: "statslog-framework-java-gen", tools: ["stats-log-api-gen"], diff --git a/core/java/android/os/logcat/ILogcatManagerService.aidl b/core/java/android/os/logcat/ILogcatManagerService.aidl new file mode 100644 index 0000000000000..68b5679919d69 --- /dev/null +++ b/core/java/android/os/logcat/ILogcatManagerService.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os.logcat; + +/** + * @hide + */ +interface ILogcatManagerService { + void startThread(in int uid, in int gid, in int pid, in int fd); + void finishThread(in int uid, in int gid, in int pid, in int fd); +} + diff --git a/core/java/android/os/logcat/OWNERS b/core/java/android/os/logcat/OWNERS new file mode 100644 index 0000000000000..cb21a6fafd7e1 --- /dev/null +++ b/core/java/android/os/logcat/OWNERS @@ -0,0 +1 @@ +include platform/frameworks/base:/services/core/java/com/android/server/logcat/OWNERS diff --git a/libs/services/Android.bp b/libs/services/Android.bp index bf2e764aae6ad..f656ebfc3b773 100644 --- a/libs/services/Android.bp +++ b/libs/services/Android.bp @@ -27,6 +27,7 @@ cc_library_shared { name: "libservices", srcs: [ ":IDropBoxManagerService.aidl", + ":ILogcatManagerService_aidl", "src/content/ComponentName.cpp", "src/os/DropBoxManager.cpp", ], diff --git a/services/core/java/com/android/server/logcat/LogcatManagerService.java b/services/core/java/com/android/server/logcat/LogcatManagerService.java new file mode 100644 index 0000000000000..ff6372aec3bd9 --- /dev/null +++ b/services/core/java/com/android/server/logcat/LogcatManagerService.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.logcat; + +import android.content.Context; +import android.os.ILogd; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.logcat.ILogcatManagerService; +import android.util.Slog; + +import com.android.server.SystemService; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Service responsible for manage the access to Logcat. + */ +public final class LogcatManagerService extends SystemService { + + private static final String TAG = "LogcatManagerService"; + private final Context mContext; + private final BinderService mBinderService; + private final ExecutorService mThreadExecutor; + private ILogd mLogdService; + + private final class BinderService extends ILogcatManagerService.Stub { + @Override + public void startThread(int uid, int gid, int pid, int fd) { + mThreadExecutor.execute(new LogdMonitor(uid, gid, pid, fd, true)); + } + + @Override + public void finishThread(int uid, int gid, int pid, int fd) { + // TODO This thread will be used to notify the AppOpsManager that + // the logd data access is finished. + mThreadExecutor.execute(new LogdMonitor(uid, gid, pid, fd, false)); + } + } + + private class LogdMonitor implements Runnable { + + private final int mUid; + private final int mGid; + private final int mPid; + private final int mFd; + private final boolean mStart; + + /** + * For starting a thread, the start value is true. + * For finishing a thread, the start value is false. + */ + LogdMonitor(int uid, int gid, int pid, int fd, boolean start) { + mUid = uid; + mGid = gid; + mPid = pid; + mFd = fd; + mStart = start; + } + + /** + * The current version grant the permission by default. + * And track the logd access. + * The next version will generate a prompt for users. + * The users decide whether the logd access is allowed. + */ + @Override + public void run() { + if (mLogdService == null) { + LogcatManagerService.this.addLogdService(); + } + + if (mStart) { + try { + mLogdService.approve(mUid, mGid, mPid, mFd); + } catch (RemoteException ex) { + Slog.e(TAG, "Fails to call remote functions ", ex); + } + } + } + } + + public LogcatManagerService(Context context) { + super(context); + mContext = context; + mBinderService = new BinderService(); + mThreadExecutor = Executors.newCachedThreadPool(); + } + + @Override + public void onStart() { + try { + publishBinderService("logcat", mBinderService); + } catch (Throwable t) { + Slog.e(TAG, "Could not start the LogcatManagerService.", t); + } + } + + private void addLogdService() { + mLogdService = ILogd.Stub.asInterface(ServiceManager.getService("logd")); + } + +} diff --git a/services/core/java/com/android/server/logcat/OWNERS b/services/core/java/com/android/server/logcat/OWNERS new file mode 100644 index 0000000000000..9588fa9d1f8e4 --- /dev/null +++ b/services/core/java/com/android/server/logcat/OWNERS @@ -0,0 +1,5 @@ +cbrubaker@google.com +eunjeongshin@google.com +jsharkey@google.com +vishwath@google.com +wenhaowang@google.com diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index ac90ceb1b8287..07dcd3d540fa6 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -137,6 +137,7 @@ import com.android.server.integrity.AppIntegrityManagerService; import com.android.server.lights.LightsService; import com.android.server.locales.LocaleManagerService; import com.android.server.location.LocationManagerService; +import com.android.server.logcat.LogcatManagerService; import com.android.server.media.MediaRouterService; import com.android.server.media.metrics.MediaMetricsManagerService; import com.android.server.media.projection.MediaProjectionManagerService; @@ -1632,6 +1633,10 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(AppIntegrityManagerService.class); t.traceEnd(); + t.traceBegin("StartLogcatManager"); + mSystemServiceManager.startService(LogcatManagerService.class); + t.traceEnd(); + } catch (Throwable e) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting core service");