diff options
author | 2024-05-15 12:47:46 +0000 | |
---|---|---|
committer | 2024-05-20 22:18:25 +0000 | |
commit | def4e4323d03e8ffd6517886fade38944b33f686 (patch) | |
tree | cf518868e35c327aa3318fe225b33839acd69f78 | |
parent | 6431d4afddc338a3e8a997f341df5a23d54efbc7 (diff) |
Skip user consent for subsequent reports
Bug: 340439309
Test: atest android.bugreport.cts_root.BugreportManagerTest
Change-Id: I1e6cabe599a3f52b4877ac1026ed4401fa86e6db
-rw-r--r-- | cmds/dumpstate/DumpstateService.cpp | 13 | ||||
-rw-r--r-- | cmds/dumpstate/DumpstateService.h | 3 | ||||
-rw-r--r-- | cmds/dumpstate/binder/android/os/IDumpstate.aidl | 4 | ||||
-rw-r--r-- | cmds/dumpstate/dumpstate.cpp | 83 | ||||
-rw-r--r-- | cmds/dumpstate/dumpstate.h | 9 | ||||
-rw-r--r-- | cmds/dumpstate/tests/dumpstate_smoke_test.cpp | 8 | ||||
-rw-r--r-- | cmds/dumpstate/tests/dumpstate_test.cpp | 16 |
7 files changed, 79 insertions, 57 deletions
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp index ba0a38aad9..a8d12a1a91 100644 --- a/cmds/dumpstate/DumpstateService.cpp +++ b/cmds/dumpstate/DumpstateService.cpp @@ -39,6 +39,7 @@ struct DumpstateInfo { std::string calling_package; int32_t user_id = -1; bool keep_bugreport_on_retrieval = false; + bool skip_user_consent = false; }; static binder::Status exception(uint32_t code, const std::string& msg, @@ -62,7 +63,8 @@ static binder::Status exception(uint32_t code, const std::string& msg, [[noreturn]] static void* dumpstate_thread_retrieve(void* data) { std::unique_ptr<DumpstateInfo> ds_info(static_cast<DumpstateInfo*>(data)); - ds_info->ds->Retrieve(ds_info->calling_uid, ds_info->calling_package, ds_info->keep_bugreport_on_retrieval); + ds_info->ds->Retrieve(ds_info->calling_uid, ds_info->calling_package, + ds_info->keep_bugreport_on_retrieval, ds_info->skip_user_consent); MYLOGD("Finished retrieving a bugreport. Exiting.\n"); exit(0); } @@ -116,7 +118,8 @@ binder::Status DumpstateService::startBugreport(int32_t calling_uid, int bugreport_mode, int bugreport_flags, const sp<IDumpstateListener>& listener, - bool is_screenshot_requested) { + bool is_screenshot_requested, + bool skip_user_consent) { MYLOGI("startBugreport() with mode: %d\n", bugreport_mode); // Ensure there is only one bugreport in progress at a time. @@ -151,7 +154,7 @@ binder::Status DumpstateService::startBugreport(int32_t calling_uid, std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>(); options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_flags, - bugreport_fd, screenshot_fd, is_screenshot_requested); + bugreport_fd, screenshot_fd, is_screenshot_requested, skip_user_consent); if (bugreport_fd.get() == -1 || (options->do_screenshot && screenshot_fd.get() == -1)) { MYLOGE("Invalid filedescriptor"); @@ -207,6 +210,7 @@ binder::Status DumpstateService::retrieveBugreport( android::base::unique_fd bugreport_fd, const std::string& bugreport_file, const bool keep_bugreport_on_retrieval, + const bool skip_user_consent, const sp<IDumpstateListener>& listener) { ds_ = &(Dumpstate::GetInstance()); @@ -216,6 +220,7 @@ binder::Status DumpstateService::retrieveBugreport( ds_info->calling_package = calling_package; ds_info->user_id = user_id; ds_info->keep_bugreport_on_retrieval = keep_bugreport_on_retrieval; + ds_info->skip_user_consent = skip_user_consent; ds_->listener_ = listener; std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>(); // Use a /dev/null FD when initializing options since none is provided. @@ -223,7 +228,7 @@ binder::Status DumpstateService::retrieveBugreport( TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY | O_CLOEXEC))); options->Initialize(Dumpstate::BugreportMode::BUGREPORT_DEFAULT, - 0, bugreport_fd, devnull_fd, false); + 0, bugreport_fd, devnull_fd, false, skip_user_consent); if (bugreport_fd.get() == -1) { MYLOGE("Invalid filedescriptor"); diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h index 7b76c36380..c99f70eb1b 100644 --- a/cmds/dumpstate/DumpstateService.h +++ b/cmds/dumpstate/DumpstateService.h @@ -44,7 +44,7 @@ class DumpstateService : public BinderService<DumpstateService>, public BnDumpst android::base::unique_fd bugreport_fd, android::base::unique_fd screenshot_fd, int bugreport_mode, int bugreport_flags, const sp<IDumpstateListener>& listener, - bool is_screenshot_requested) override; + bool is_screenshot_requested, bool skip_user_consent) override; binder::Status retrieveBugreport(int32_t calling_uid, const std::string& calling_package, @@ -52,6 +52,7 @@ class DumpstateService : public BinderService<DumpstateService>, public BnDumpst android::base::unique_fd bugreport_fd, const std::string& bugreport_file, const bool keep_bugreport_on_retrieval, + const bool skip_user_consent, const sp<IDumpstateListener>& listener) override; diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl index 97c470e08c..3b8fde9f51 100644 --- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl +++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl @@ -96,7 +96,8 @@ interface IDumpstate { void startBugreport(int callingUid, @utf8InCpp String callingPackage, FileDescriptor bugreportFd, FileDescriptor screenshotFd, int bugreportMode, int bugreportFlags, - IDumpstateListener listener, boolean isScreenshotRequested); + IDumpstateListener listener, boolean isScreenshotRequested, + boolean skipUserConsent); /** * Cancels the bugreport currently in progress. @@ -130,5 +131,6 @@ interface IDumpstate { FileDescriptor bugreportFd, @utf8InCpp String bugreportFile, boolean keepBugreportOnRetrieval, + boolean skipUserConsent, IDumpstateListener listener); } diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 6b9a0a0e7e..d5125f01d6 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -2902,9 +2902,11 @@ void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode, int bugreport_flags, const android::base::unique_fd& bugreport_fd_in, const android::base::unique_fd& screenshot_fd_in, - bool is_screenshot_requested) { + bool is_screenshot_requested, + bool skip_user_consent) { this->use_predumped_ui_data = bugreport_flags & BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA; this->is_consent_deferred = bugreport_flags & BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT; + this->skip_user_consent = skip_user_consent; // Duplicate the fds because the passed in fds don't outlive the binder transaction. bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0)); screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0)); @@ -2992,46 +2994,52 @@ Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& call } Dumpstate::RunStatus Dumpstate::Retrieve(int32_t calling_uid, const std::string& calling_package, - const bool keep_bugreport_on_retrieval) { + const bool keep_bugreport_on_retrieval, + const bool skip_user_consent) { Dumpstate::RunStatus status = RetrieveInternal(calling_uid, calling_package, - keep_bugreport_on_retrieval); + keep_bugreport_on_retrieval, + skip_user_consent); HandleRunStatus(status); return status; } Dumpstate::RunStatus Dumpstate::RetrieveInternal(int32_t calling_uid, const std::string& calling_package, - const bool keep_bugreport_on_retrieval) { - consent_callback_ = new ConsentCallback(); - const String16 incidentcompanion("incidentcompanion"); - sp<android::IBinder> ics( - defaultServiceManager()->checkService(incidentcompanion)); - android::String16 package(calling_package.c_str()); - if (ics != nullptr) { - MYLOGD("Checking user consent via incidentcompanion service\n"); - android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport( - calling_uid, package, String16(), String16(), - 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get()); - } else { - MYLOGD( - "Unable to check user consent; incidentcompanion service unavailable\n"); - return RunStatus::USER_CONSENT_TIMED_OUT; - } - UserConsentResult consent_result = consent_callback_->getResult(); - int timeout_ms = 30 * 1000; - while (consent_result == UserConsentResult::UNAVAILABLE && - consent_callback_->getElapsedTimeMs() < timeout_ms) { - sleep(1); - consent_result = consent_callback_->getResult(); - } - if (consent_result == UserConsentResult::DENIED) { - return RunStatus::USER_CONSENT_DENIED; - } - if (consent_result == UserConsentResult::UNAVAILABLE) { - MYLOGD("Canceling user consent request via incidentcompanion service\n"); - android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization( - consent_callback_.get()); - return RunStatus::USER_CONSENT_TIMED_OUT; + const bool keep_bugreport_on_retrieval, + const bool skip_user_consent) { + if (!android::app::admin::flags::onboarding_consentless_bugreports() || !skip_user_consent) { + consent_callback_ = new ConsentCallback(); + const String16 incidentcompanion("incidentcompanion"); + sp<android::IBinder> ics( + defaultServiceManager()->checkService(incidentcompanion)); + android::String16 package(calling_package.c_str()); + if (ics != nullptr) { + MYLOGD("Checking user consent via incidentcompanion service\n"); + + android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport( + calling_uid, package, String16(), String16(), + 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get()); + } else { + MYLOGD( + "Unable to check user consent; incidentcompanion service unavailable\n"); + return RunStatus::USER_CONSENT_TIMED_OUT; + } + UserConsentResult consent_result = consent_callback_->getResult(); + int timeout_ms = 30 * 1000; + while (consent_result == UserConsentResult::UNAVAILABLE && + consent_callback_->getElapsedTimeMs() < timeout_ms) { + sleep(1); + consent_result = consent_callback_->getResult(); + } + if (consent_result == UserConsentResult::DENIED) { + return RunStatus::USER_CONSENT_DENIED; + } + if (consent_result == UserConsentResult::UNAVAILABLE) { + MYLOGD("Canceling user consent request via incidentcompanion service\n"); + android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization( + consent_callback_.get()); + return RunStatus::USER_CONSENT_TIMED_OUT; + } } bool copy_succeeded = @@ -3510,7 +3518,9 @@ void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) { void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) { if (multiuser_get_app_id(calling_uid) == AID_SHELL || - !CalledByApi() || options_->is_consent_deferred) { + !CalledByApi() || options_->is_consent_deferred || + (android::app::admin::flags::onboarding_consentless_bugreports() && + options_->skip_user_consent)) { // No need to get consent for shell triggered dumpstates, or not // through bugreporting API (i.e. no fd to copy back), or when consent // is deferred. @@ -3596,7 +3606,8 @@ Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid // If the caller has asked to copy the bugreport over to their directory, we need explicit // user consent (unless the caller is Shell). UserConsentResult consent_result; - if (multiuser_get_app_id(calling_uid) == AID_SHELL) { + if (multiuser_get_app_id(calling_uid) == AID_SHELL || (options_->skip_user_consent + && android::app::admin::flags::onboarding_consentless_bugreports())) { consent_result = UserConsentResult::APPROVED; } else { consent_result = consent_callback_->getResult(); diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index 46d949e303..fcb8cf3c07 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -364,7 +364,7 @@ class Dumpstate { * Initialize() dumpstate before calling this method. */ RunStatus Retrieve(int32_t calling_uid, const std::string& calling_package, - const bool keep_bugreport_on_retrieval); + const bool keep_bugreport_on_retrieval, const bool skip_user_consent); @@ -412,6 +412,7 @@ class Dumpstate { bool do_screenshot = false; bool is_screenshot_copied = false; bool is_consent_deferred = false; + bool skip_user_consent = false; bool is_remote_mode = false; bool show_header_only = false; bool telephony_only = false; @@ -448,7 +449,8 @@ class Dumpstate { void Initialize(BugreportMode bugreport_mode, int bugreport_flags, const android::base::unique_fd& bugreport_fd, const android::base::unique_fd& screenshot_fd, - bool is_screenshot_requested); + bool is_screenshot_requested, + bool skip_user_consent); /* Returns true if the options set so far are consistent. */ bool ValidateOptions() const; @@ -564,7 +566,8 @@ class Dumpstate { private: RunStatus RunInternal(int32_t calling_uid, const std::string& calling_package); RunStatus RetrieveInternal(int32_t calling_uid, const std::string& calling_package, - const bool keep_bugreport_on_retrieval); + const bool keep_bugreport_on_retrieval, + const bool skip_user_consent); RunStatus DumpstateDefaultAfterCritical(); RunStatus dumpstate(); diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp index ccf64fe54e..a29923a4c1 100644 --- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp @@ -507,7 +507,7 @@ TEST_F(DumpstateBinderTest, Baseline) { ds_binder->startBugreport(123, "com.example.package", std::move(bugreport_fd), std::move(screenshot_fd), Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, flags, listener, - true); + true, false); // startBugreport is an async call. Verify binder call succeeded first, then wait till listener // gets expected callbacks. EXPECT_TRUE(status.isOk()); @@ -545,7 +545,7 @@ TEST_F(DumpstateBinderTest, ServiceDies_OnInvalidInput) { android::binder::Status status = ds_binder->startBugreport(123, "com.example.package", std::move(bugreport_fd), std::move(screenshot_fd), 2000, // invalid bugreport mode - flags, listener, false); + flags, listener, false, false); EXPECT_EQ(listener->getErrorCode(), IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT); // The service should have died, freeing itself up for a new invocation. @@ -579,7 +579,7 @@ TEST_F(DumpstateBinderTest, SimultaneousBugreportsNotAllowed) { ds_binder->startBugreport(123, "com.example.package", std::move(bugreport_fd), std::move(screenshot_fd), Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, flags, listener1, - true); + true, false); EXPECT_TRUE(status.isOk()); // try to make another call to startBugreport. This should fail. @@ -587,7 +587,7 @@ TEST_F(DumpstateBinderTest, SimultaneousBugreportsNotAllowed) { status = ds_binder->startBugreport(123, "com.example.package", std::move(bugreport_fd2), std::move(screenshot_fd2), Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, flags, - listener2, true); + listener2, true, false); EXPECT_FALSE(status.isOk()); WaitTillExecutionComplete(listener2.get()); EXPECT_EQ(listener2->getErrorCode(), diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp index 2afabed813..18c2f94432 100644 --- a/cmds/dumpstate/tests/dumpstate_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_test.cpp @@ -239,7 +239,7 @@ TEST_F(DumpOptionsTest, InitializeAdbShellBugreport) { } TEST_F(DumpOptionsTest, InitializeFullBugReport) { - options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, 0, fd, fd, true); + options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, 0, fd, fd, true, false); EXPECT_TRUE(options_.do_screenshot); // Other options retain default values @@ -253,7 +253,7 @@ TEST_F(DumpOptionsTest, InitializeFullBugReport) { } TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) { - options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, 0, fd, fd, true); + options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, 0, fd, fd, true, false); EXPECT_TRUE(options_.do_progress_updates); EXPECT_TRUE(options_.do_screenshot); @@ -267,7 +267,7 @@ TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) { } TEST_F(DumpOptionsTest, InitializeRemoteBugReport) { - options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, 0, fd, fd, false); + options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, 0, fd, fd, false, false); EXPECT_TRUE(options_.is_remote_mode); EXPECT_FALSE(options_.do_vibrate); EXPECT_FALSE(options_.do_screenshot); @@ -281,7 +281,7 @@ TEST_F(DumpOptionsTest, InitializeRemoteBugReport) { } TEST_F(DumpOptionsTest, InitializeWearBugReport) { - options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, 0, fd, fd, true); + options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, 0, fd, fd, true, false); EXPECT_TRUE(options_.do_screenshot); EXPECT_TRUE(options_.do_progress_updates); @@ -296,7 +296,7 @@ TEST_F(DumpOptionsTest, InitializeWearBugReport) { } TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) { - options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, 0, fd, fd, false); + options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, 0, fd, fd, false, false); EXPECT_FALSE(options_.do_screenshot); EXPECT_TRUE(options_.telephony_only); EXPECT_TRUE(options_.do_progress_updates); @@ -311,7 +311,7 @@ TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) { } TEST_F(DumpOptionsTest, InitializeWifiBugReport) { - options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, 0, fd, fd, false); + options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, 0, fd, fd, false, false); EXPECT_FALSE(options_.do_screenshot); EXPECT_TRUE(options_.wifi_only); @@ -491,12 +491,12 @@ TEST_F(DumpOptionsTest, InitializeBugreportFlags) { int flags = Dumpstate::BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA | Dumpstate::BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT; options_.Initialize( - Dumpstate::BugreportMode::BUGREPORT_FULL, flags, fd, fd, true); + Dumpstate::BugreportMode::BUGREPORT_FULL, flags, fd, fd, true, false); EXPECT_TRUE(options_.is_consent_deferred); EXPECT_TRUE(options_.use_predumped_ui_data); options_.Initialize( - Dumpstate::BugreportMode::BUGREPORT_FULL, 0, fd, fd, true); + Dumpstate::BugreportMode::BUGREPORT_FULL, 0, fd, fd, true, false); EXPECT_FALSE(options_.is_consent_deferred); EXPECT_FALSE(options_.use_predumped_ui_data); } |