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 // ============================================================
ConsentListener(const sp<Broadcaster> & broadcaster,const ReportId & reportId)35 Broadcaster::ConsentListener::ConsentListener(const sp<Broadcaster>& broadcaster,
36 const ReportId& reportId)
37 :mBroadcaster(broadcaster),
38 mId(reportId) {
39 }
40
~ConsentListener()41 Broadcaster::ConsentListener::~ConsentListener() {
42 }
43
onReportApproved()44 Status Broadcaster::ConsentListener::onReportApproved() {
45 mBroadcaster->report_approved(mId);
46 return Status::ok();
47 }
48
onReportDenied()49 Status Broadcaster::ConsentListener::onReportDenied() {
50 mBroadcaster->report_denied(mId);
51 return Status::ok();
52 }
53
54 // ============================================================
ReportId()55 Broadcaster::ReportId::ReportId()
56 :id(),
57 pkg(),
58 cls() {
59 }
60
ReportId(const ReportId & that)61 Broadcaster::ReportId::ReportId(const ReportId& that)
62 :id(that.id),
63 pkg(that.pkg),
64 cls(that.cls) {
65 }
66
ReportId(const string & i,const string & p,const string & c)67 Broadcaster::ReportId::ReportId(const string& i, const string& p, const string& c)
68 :id(i),
69 pkg(p),
70 cls(c) {
71 }
72
~ReportId()73 Broadcaster::ReportId::~ReportId() {
74 }
75
operator <(const ReportId & that) const76 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 // ============================================================
ReportStatus()96 Broadcaster::ReportStatus::ReportStatus()
97 :approval_sent(false),
98 ready_sent(false),
99 listener(nullptr) {
100 }
101
ReportStatus(const ReportStatus & that)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
~ReportStatus()108 Broadcaster::ReportStatus::~ReportStatus() {
109 }
110
111 // ============================================================
Broadcaster(const sp<WorkDirectory> & workDirectory)112 Broadcaster::Broadcaster(const sp<WorkDirectory>& workDirectory)
113 :mReportHandler(),
114 mWorkDirectory(workDirectory) {
115 }
116
setHandler(const sp<ReportHandler> & handler)117 void Broadcaster::setHandler(const sp<ReportHandler>& handler) {
118 mReportHandler = handler;
119 }
120
reset()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
clearBroadcasts(const string & pkg,const string & cls,const string & id)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
clearPackageBroadcasts(const string & pkg)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
sendBroadcasts()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
set_last_sent(int64_t timestamp)247 void Broadcaster::set_last_sent(int64_t timestamp) {
248 unique_lock<mutex> lock(mLock);
249 mLastSent = timestamp;
250 }
251
get_last_sent()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
was_approval_sent(const string & id,const string & pkg,const string & cls)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
set_approval_sent(const string & id,const string & pkg,const string & cls,const sp<ConsentListener> & listener)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
was_ready_sent(const string & id,const string & pkg,const string & cls)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
set_ready_sent(const string & id,const string & pkg,const string & cls)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
send_approval_broadcasts(const string & id,const string & pkg,const string & cls)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
report_approved(const ReportId & reportId)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
report_denied(const ReportId & reportId)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
send_report_ready_broadcasts(const string & id,const string & pkg,const string & cls)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
send_to_dropbox(const sp<ReportFile> & file,const IncidentReportArgs & args)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
get_incident_companion()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