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
This commit is contained in:
Wenhao Wang 2022-01-11 22:29:18 -08:00
parent 5af00f9e0f
commit 256519a529
8 changed files with 162 additions and 0 deletions

View File

@ -139,6 +139,7 @@ filegroup {
":libcamera_client_aidl",
":libcamera_client_framework_aidl",
":libupdate_engine_aidl",
":logd_aidl",
":resourcemanager_aidl",
":storaged_aidl",
":vold_aidl",

View File

@ -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"],

View File

@ -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);
}

View File

@ -0,0 +1 @@
include platform/frameworks/base:/services/core/java/com/android/server/logcat/OWNERS

View File

@ -27,6 +27,7 @@ cc_library_shared {
name: "libservices",
srcs: [
":IDropBoxManagerService.aidl",
":ILogcatManagerService_aidl",
"src/content/ComponentName.cpp",
"src/os/DropBoxManager.cpp",
],

View File

@ -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"));
}
}

View File

@ -0,0 +1,5 @@
cbrubaker@google.com
eunjeongshin@google.com
jsharkey@google.com
vishwath@google.com
wenhaowang@google.com

View File

@ -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");