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