1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "Log.h" 18 19 #include "Broadcaster.h" 20 21 #include "IncidentService.h" 22 23 #include <android/os/DropBoxManager.h> 24 #include <binder/IServiceManager.h> 25 #include <thread> 26 27 namespace android { 28 namespace os { 29 namespace incidentd { 30 31 using android::os::IIncidentCompanion; 32 using binder::Status; 33 34 // ============================================================ 35 Broadcaster::ConsentListener::ConsentListener(const sp<Broadcaster>& broadcaster, 36 const ReportId& reportId) 37 :mBroadcaster(broadcaster), 38 mId(reportId) { 39 } 40 41 Broadcaster::ConsentListener::~ConsentListener() { 42 } 43 44 Status Broadcaster::ConsentListener::onReportApproved() { 45 mBroadcaster->report_approved(mId); 46 return Status::ok(); 47 } 48 49 Status Broadcaster::ConsentListener::onReportDenied() { 50 mBroadcaster->report_denied(mId); 51 return Status::ok(); 52 } 53 54 // ============================================================ 55 Broadcaster::ReportId::ReportId() 56 :id(), 57 pkg(), 58 cls() { 59 } 60 61 Broadcaster::ReportId::ReportId(const ReportId& that) 62 :id(that.id), 63 pkg(that.pkg), 64 cls(that.cls) { 65 } 66 67 Broadcaster::ReportId::ReportId(const string& i, const string& p, const string& c) 68 :id(i), 69 pkg(p), 70 cls(c) { 71 } 72 73 Broadcaster::ReportId::~ReportId() { 74 } 75 76 bool Broadcaster::ReportId::operator<(const ReportId& that) const { 77 if (id < that.id) { 78 return true; 79 } 80 if (id > that.id) { 81 return false; 82 } 83 if (pkg < that.pkg) { 84 return true; 85 } 86 if (pkg > that.pkg) { 87 return false; 88 } 89 if (cls < that.cls) { 90 return true; 91 } 92 return false; 93 } 94 95 // ============================================================ 96 Broadcaster::ReportStatus::ReportStatus() 97 :approval_sent(false), 98 ready_sent(false), 99 listener(nullptr) { 100 } 101 102 Broadcaster::ReportStatus::ReportStatus(const ReportStatus& that) 103 :approval_sent(that.approval_sent), 104 ready_sent(that.ready_sent), 105 listener(that.listener) { 106 } 107 108 Broadcaster::ReportStatus::~ReportStatus() { 109 } 110 111 // ============================================================ 112 Broadcaster::Broadcaster(const sp<WorkDirectory>& workDirectory) 113 :mReportHandler(), 114 mWorkDirectory(workDirectory) { 115 } 116 117 void Broadcaster::setHandler(const sp<ReportHandler>& handler) { 118 mReportHandler = handler; 119 } 120 121 void Broadcaster::reset() { 122 unique_lock<mutex> lock(mLock); 123 mLastSent = 0; 124 mHistory.clear(); 125 // Could cancel the listeners, but this happens when 126 // the system process crashes, so don't bother. 127 } 128 129 void Broadcaster::clearBroadcasts(const string& pkg, const string& cls, const string& id) { 130 unique_lock<mutex> lock(mLock); 131 132 map<ReportId,ReportStatus>::const_iterator found = mHistory.find(ReportId(id, pkg, cls)); 133 if (found != mHistory.end()) { 134 if (found->second.listener != nullptr) { 135 sp<IIncidentCompanion> ics = get_incident_companion(); 136 if (ics != nullptr) { 137 ics->cancelAuthorization(found->second.listener); 138 } 139 } 140 mHistory.erase(found); 141 } 142 } 143 144 void Broadcaster::clearPackageBroadcasts(const string& pkg) { 145 unique_lock<mutex> lock(mLock); 146 147 map<ReportId,ReportStatus>::iterator it = mHistory.begin(); 148 while (it != mHistory.end()) { 149 if (it->first.pkg == pkg) { 150 if (it->second.listener != nullptr) { 151 sp<IIncidentCompanion> ics = get_incident_companion(); 152 if (ics != nullptr) { 153 ics->cancelAuthorization(it->second.listener); 154 } 155 } 156 it = mHistory.erase(it); 157 } else { 158 it++; 159 } 160 } 161 } 162 163 Broadcaster::broadcast_status_t Broadcaster::sendBroadcasts() { 164 int err; 165 int64_t lastSent = get_last_sent(); 166 167 vector<sp<ReportFile>> files; 168 mWorkDirectory->getReports(&files, 0); //lastSent); 169 170 // Don't send multiple broadcasts to the same receiver. 171 set<ReportId> reportReadyBroadcasts; 172 173 for (const sp<ReportFile>& file: files) { 174 err = file->loadEnvelope(); 175 if (err != NO_ERROR) { 176 ALOGW("Error (%s) loading envelope from %s", strerror(-err), 177 file->getEnvelopeFileName().c_str()); 178 continue; 179 } 180 181 const ReportFileProto& envelope = file->getEnvelope(); 182 183 if (!envelope.completed()) { 184 ALOGI("Incident report not completed skipping it: %s", 185 file->getEnvelopeFileName().c_str()); 186 continue; 187 } 188 189 // When one of the broadcast functions in this loop fails, it's almost 190 // certainly because the system process is crashing or has crashed. Rather 191 // than continuing to pound on the system process and potentially make things 192 // worse, we bail right away, return BROADCASTS_BACKOFF, and we will try 193 // again later. In the meantime, if the system process did crash, it might 194 // clear out mHistory, which means we'll be back here again to send the 195 // backlog. 196 size_t reportCount = envelope.report_size(); 197 bool hasApprovalPending = false; 198 for (int reportIndex = 0; reportIndex < reportCount; reportIndex++) { 199 200 const ReportFileProto_Report& report = envelope.report(reportIndex); 201 status_t err; 202 if (report.privacy_policy() == PRIVACY_POLICY_AUTOMATIC || report.share_approved()) { 203 // It's privacy policy is AUTO, or it's been approved, 204 // so send the actual broadcast. 205 if (!was_ready_sent(file->getId(), report.pkg(), report.cls())) { 206 if (report.pkg() == DROPBOX_SENTINEL.getPackageName() 207 && report.cls() == DROPBOX_SENTINEL.getClassName()) { 208 IncidentReportArgs args; 209 get_args_from_report(&args, report); 210 err = send_to_dropbox(file, args); 211 if (err != NO_ERROR) { 212 return BROADCASTS_BACKOFF; 213 } 214 } else { 215 reportReadyBroadcasts.insert(ReportId(file->getId(), report.pkg(), 216 report.cls())); 217 } 218 } 219 } else { 220 // It's not approved yet, so send the approval. 221 if (!was_approval_sent(file->getId(), report.pkg(), report.cls())) { 222 err = send_approval_broadcasts(file->getId(), report.pkg(), report.cls()); 223 if (err != NO_ERROR) { 224 return BROADCASTS_BACKOFF; 225 } 226 hasApprovalPending = true; 227 } 228 } 229 } 230 231 lastSent = file->getTimestampNs(); 232 if (!hasApprovalPending) { 233 set_last_sent(lastSent); 234 } 235 } 236 237 for (const ReportId& report: reportReadyBroadcasts) { 238 err = send_report_ready_broadcasts(report.id, report.pkg, report.cls); 239 if (err != NO_ERROR) { 240 return BROADCASTS_BACKOFF; 241 } 242 } 243 244 return mWorkDirectory->hasMore(lastSent) ? BROADCASTS_REPEAT : BROADCASTS_FINISHED; 245 } 246 247 void Broadcaster::set_last_sent(int64_t timestamp) { 248 unique_lock<mutex> lock(mLock); 249 mLastSent = timestamp; 250 } 251 252 int64_t Broadcaster::get_last_sent() { 253 unique_lock<mutex> lock(mLock); 254 return mLastSent; 255 } 256 257 /* 258 void Broadcaster::printReportStatuses() const { 259 ALOGD("mHistory {"); 260 for (map<ReportId,ReportStatus>::const_iterator it = mHistory.begin(); 261 it != mHistory.end(); it++) { 262 ALOGD(" [%s %s] --> [%d %d]", it->first.id.c_str(), it->first.pkg.c_str(), 263 it->second.approval_sent, it->second.ready_sent); 264 } 265 ALOGD("}"); 266 } 267 */ 268 269 bool Broadcaster::was_approval_sent(const string& id, const string& pkg, const string& cls) { 270 unique_lock<mutex> lock(mLock); 271 map<ReportId,ReportStatus>::const_iterator found = mHistory.find(ReportId(id, pkg, cls)); 272 if (found != mHistory.end()) { 273 return found->second.approval_sent; 274 } 275 return false; 276 } 277 278 void Broadcaster::set_approval_sent(const string& id, const string& pkg, const string& cls, 279 const sp<ConsentListener>& listener) { 280 unique_lock<mutex> lock(mLock); 281 ReportStatus& reportStatus = mHistory[ReportId(id, pkg, cls)]; 282 reportStatus.approval_sent = true; 283 reportStatus.listener = listener; 284 } 285 286 bool Broadcaster::was_ready_sent(const string& id, const string& pkg, const string& cls) { 287 unique_lock<mutex> lock(mLock); 288 map<ReportId,ReportStatus>::const_iterator found = mHistory.find(ReportId(id, pkg, cls)); 289 if (found != mHistory.end()) { 290 return found->second.ready_sent; 291 } 292 return false; 293 } 294 295 void Broadcaster::set_ready_sent(const string& id, const string& pkg, const string& cls) { 296 unique_lock<mutex> lock(mLock); 297 mHistory[ReportId(id, pkg, cls)].ready_sent = true; 298 } 299 300 status_t Broadcaster::send_approval_broadcasts(const string& id, const string& pkg, 301 const string& cls) { 302 sp<IIncidentCompanion> ics = get_incident_companion(); 303 if (ics == nullptr) { 304 return NAME_NOT_FOUND; 305 } 306 307 sp<ConsentListener> listener = new ConsentListener(this, ReportId(id, pkg, cls)); 308 309 ALOGI("send_approval_broadcasts for %s %s/%s", id.c_str(), pkg.c_str(), cls.c_str()); 310 311 Status status = ics->authorizeReport(0, String16(pkg.c_str()), 312 String16(cls.c_str()), String16(id.c_str()), 0, listener); 313 314 if (!status.isOk()) { 315 // authorizeReport is oneway, so any error is a transaction error. 316 return status.transactionError(); 317 } 318 319 set_approval_sent(id, pkg, cls, listener); 320 321 return NO_ERROR; 322 } 323 324 void Broadcaster::report_approved(const ReportId& reportId) { 325 status_t err; 326 327 // Kick off broadcaster to do send the ready broadcasts. 328 ALOGI("The user approved the report, so kicking off another broadcast pass. %s %s/%s", 329 reportId.id.c_str(), reportId.pkg.c_str(), reportId.cls.c_str()); 330 sp<ReportFile> file = mWorkDirectory->getReport(reportId.pkg, reportId.cls, reportId.id, 331 nullptr); 332 if (file != nullptr) { 333 err = file->loadEnvelope(); 334 if (err != NO_ERROR) { 335 return; 336 } 337 338 err = file->markApproved(reportId.pkg, reportId.cls); 339 if (err != NO_ERROR) { 340 ALOGI("Couldn't find report that was just approved: %s %s/%s", 341 reportId.id.c_str(), reportId.pkg.c_str(), reportId.cls.c_str()); 342 return; 343 } 344 345 file->saveEnvelope(); 346 if (err != NO_ERROR) { 347 return; 348 } 349 } 350 mReportHandler->scheduleSendBacklog(); 351 } 352 353 void Broadcaster::report_denied(const ReportId& reportId) { 354 // The user didn't approve the report, so remove it from the WorkDirectory. 355 ALOGI("The user denied the report, so deleting it. %s %s/%s", 356 reportId.id.c_str(), reportId.pkg.c_str(), reportId.cls.c_str()); 357 sp<ReportFile> file = mWorkDirectory->getReport(reportId.pkg, reportId.cls, reportId.id, 358 nullptr); 359 if (file != nullptr) { 360 mWorkDirectory->commit(file, reportId.pkg, reportId.cls); 361 } 362 } 363 364 status_t Broadcaster::send_report_ready_broadcasts(const string& id, const string& pkg, 365 const string& cls) { 366 sp<IIncidentCompanion> ics = get_incident_companion(); 367 if (ics == nullptr) { 368 return NAME_NOT_FOUND; 369 } 370 371 ALOGI("send_report_ready_broadcasts for %s %s/%s", id.c_str(), pkg.c_str(), cls.c_str()); 372 373 Status status = ics->sendReportReadyBroadcast(String16(pkg.c_str()), String16(cls.c_str())); 374 375 if (!status.isOk()) { 376 // sendReportReadyBroadcast is oneway, so any error is a transaction error. 377 return status.transactionError(); 378 } 379 380 set_ready_sent(id, pkg, cls); 381 382 return NO_ERROR; 383 } 384 385 status_t Broadcaster::send_to_dropbox(const sp<ReportFile>& file, 386 const IncidentReportArgs& args) { 387 status_t err; 388 389 sp<DropBoxManager> dropbox = new DropBoxManager(); 390 if (dropbox == nullptr) { 391 ALOGW("Can't reach dropbox now, so we won't be able to write the incident report to there"); 392 return NO_ERROR; 393 } 394 395 int fds[2]; 396 if (pipe(fds) != 0) { 397 ALOGW("Error opening pipe to filter incident report: %s", file->getDataFileName().c_str()); 398 return NO_ERROR; 399 } 400 401 int readFd = fds[0]; 402 int writeFd = fds[1]; 403 404 // spawn a thread to write the data. Release the writeFd ownership to the thread. 405 thread th([file, writeFd, args]() { file->startFilteringData(writeFd, args); }); 406 407 th.detach(); 408 409 // Takes ownership of readFd. 410 Status status = dropbox->addFile(String16("incident"), readFd, 0); 411 if (!status.isOk()) { 412 // TODO: This may or may not leak the readFd, depending on where it failed. 413 // Not sure how to fix this given the dropbox API. 414 ALOGW("Error sending incident report to dropbox."); 415 return -errno; 416 } 417 418 // On successful write, tell the working directory that this file is done. 419 mWorkDirectory->commit(file, DROPBOX_SENTINEL.getPackageName(), 420 DROPBOX_SENTINEL.getClassName()); 421 422 // Don't need to call set_ready_sent, because we just removed it from the ReportFile, 423 // so we'll never hear about it again. 424 425 return NO_ERROR; 426 } 427 428 sp<IIncidentCompanion> Broadcaster::get_incident_companion() { 429 sp<IBinder> binder = defaultServiceManager()->getService(String16("incidentcompanion")); 430 if (binder == nullptr) { 431 ALOGI("Can not find IIncidentCompanion service to send broadcast. Will try again later."); 432 return nullptr; 433 } 434 435 sp<IIncidentCompanion> ics = interface_cast<IIncidentCompanion>(binder); 436 if (ics == nullptr) { 437 ALOGI("The incidentcompanion service is not an IIncidentCompanion. Will try again later."); 438 return nullptr; 439 } 440 441 return ics; 442 } 443 444 } // namespace incidentd 445 } // namespace os 446 } // namespace android 447 448 449