Pass caller information in cancelBugreport.
In preparation for a broader set of apps using BugreportManager, we
enforce that only the app which started a bugreport is allowed to cancel
it.
Bug: 161393541
Test: atest BugreportManagerTestCases
Test: manual with two apps triggering/cancelling BRs
Change-Id: I10bdc9ff2a5746e2dc1e7d63876219bb34fad3b9
Merged-In: I10bdc9ff2a5746e2dc1e7d63876219bb34fad3b9
(cherry picked from commit 00c2a7563cc60021cc6f34b90dda81f63508d3c4)
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index bfcc058..ba25a5a 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -39,8 +39,13 @@
std::string calling_package;
};
-static binder::Status exception(uint32_t code, const std::string& msg) {
- MYLOGE("%s (%d) ", msg.c_str(), code);
+static binder::Status exception(uint32_t code, const std::string& msg,
+ const std::string& extra_msg = "") {
+ if (extra_msg.empty()) {
+ MYLOGE("%s (%d) ", msg.c_str(), code);
+ } else {
+ MYLOGE("%s %s (%d) ", msg.c_str(), extra_msg.c_str(), code);
+ }
return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
}
@@ -60,7 +65,7 @@
} // namespace
-DumpstateService::DumpstateService() : ds_(nullptr) {
+DumpstateService::DumpstateService() : ds_(nullptr), calling_uid_(-1), calling_package_() {
}
char const* DumpstateService::getServiceName() {
@@ -131,6 +136,10 @@
ds_->SetOptions(std::move(options));
ds_->listener_ = listener;
+ // Track caller info for cancellation purposes.
+ calling_uid_ = calling_uid;
+ calling_package_ = calling_package;
+
DumpstateInfo* ds_info = new DumpstateInfo();
ds_info->ds = ds_;
ds_info->calling_uid = calling_uid;
@@ -149,8 +158,20 @@
return binder::Status::ok();
}
-binder::Status DumpstateService::cancelBugreport() {
+binder::Status DumpstateService::cancelBugreport(int32_t calling_uid,
+ const std::string& calling_package) {
std::lock_guard<std::mutex> lock(lock_);
+ if (calling_uid != calling_uid_ || calling_package != calling_package_) {
+ // Note: we use a SecurityException to prevent BugreportManagerServiceImpl from killing the
+ // report in progress (from another caller).
+ return exception(
+ binder::Status::EX_SECURITY,
+ StringPrintf("Cancellation requested by %d/%s does not match report in "
+ "progress",
+ calling_uid, calling_package.c_str()),
+ // Sharing the owner of the BR is a (minor) leak, so leave it out of the app's exception
+ StringPrintf("started by %d/%s", calling_uid_, calling_package_.c_str()));
+ }
ds_->Cancel();
return binder::Status::ok();
}
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index ac8d3ac..3ec8471 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -44,8 +44,7 @@
const sp<IDumpstateListener>& listener,
bool is_screenshot_requested) override;
- // No-op
- binder::Status cancelBugreport();
+ binder::Status cancelBugreport(int32_t calling_uid, const std::string& calling_package);
private:
// Dumpstate object which contains all the bugreporting logic.
@@ -53,6 +52,8 @@
// one bugreport.
// This service does not own this object.
Dumpstate* ds_;
+ int32_t calling_uid_;
+ std::string calling_package_;
std::mutex lock_;
};
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index ba008bb..0793f0b 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2016, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,9 +19,9 @@
import android.os.IDumpstateListener;
/**
- * Binder interface for the currently running dumpstate process.
- * {@hide}
- */
+ * Binder interface for the currently running dumpstate process.
+ * {@hide}
+ */
interface IDumpstate {
// NOTE: If you add to or change these modes, please also change the corresponding enums
@@ -49,10 +49,10 @@
// Default mode.
const int BUGREPORT_MODE_DEFAULT = 6;
- /*
+ /**
* Starts a bugreport in the background.
*
- *<p>Shows the user a dialog to get consent for sharing the bugreport with the calling
+ * <p>Shows the user a dialog to get consent for sharing the bugreport with the calling
* application. If they deny {@link IDumpstateListener#onError} will be called. If they
* consent and bugreport generation is successful artifacts will be copied to the given fds and
* {@link IDumpstateListener#onFinished} will be called. If there
@@ -71,8 +71,15 @@
int bugreportMode, IDumpstateListener listener,
boolean isScreenshotRequested);
- /*
+ /**
* Cancels the bugreport currently in progress.
+ *
+ * <p>The caller must match the original caller of {@link #startBugreport} in order for the
+ * report to actually be cancelled. A {@link SecurityException} is reported if a mismatch is
+ * detected.
+ *
+ * @param callingUid UID of the original application that requested the cancellation.
+ * @param callingPackage package of the original application that requested the cancellation.
*/
- void cancelBugreport();
+ void cancelBugreport(int callingUid, @utf8InCpp String callingPackage);
}