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 #define DEBUG false
17 #include "Log.h"
18
19 #include "IncidentService.h"
20
21 #include "FdBuffer.h"
22 #include "PrivacyFilter.h"
23 #include "Reporter.h"
24 #include "incidentd_util.h"
25 #include "section_list.h"
26
27 #include <android/os/IncidentReportArgs.h>
28 #include <binder/IPCThreadState.h>
29 #include <binder/IResultReceiver.h>
30 #include <binder/IServiceManager.h>
31 #include <binder/IShellCallback.h>
32 #include <log/log.h>
33 #include <private/android_filesystem_config.h>
34 #include <utils/Looper.h>
35 #include <thread>
36
37 #include <unistd.h>
38
39 enum {
40 WHAT_TAKE_REPORT = 1,
41 WHAT_SEND_BROADCASTS = 2
42 };
43
44 #define DEFAULT_DELAY_NS (1000000000LL)
45
46 #define DEFAULT_BYTES_SIZE_LIMIT (96 * 1024 * 1024) // 96MB
47 #define DEFAULT_REFACTORY_PERIOD_MS (24 * 60 * 60 * 1000) // 1 Day
48
49 // Skip these sections for dumpstate only. Dumpstate allows 10s max for each service to dump.
50 // Skip logs (1100 - 1108) and traces (1200 - 1202) because they are already in the bug report.
51 // Skip 3018 because it takes too long.
52 #define SKIPPED_SECTIONS { 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, /* Logs */ \
53 1200, 1201, 1202, /* Native, hal, java traces */ \
54 3018 /* "meminfo -a --proto" */ }
55
56 namespace android {
57 namespace os {
58 namespace incidentd {
59
60 String16 const APPROVE_INCIDENT_REPORTS("android.permission.APPROVE_INCIDENT_REPORTS");
61 String16 const DUMP_PERMISSION("android.permission.DUMP");
62 String16 const USAGE_STATS_PERMISSION("android.permission.PACKAGE_USAGE_STATS");
63
checkIncidentPermissions(const IncidentReportArgs & args)64 static Status checkIncidentPermissions(const IncidentReportArgs& args) {
65 uid_t callingUid = IPCThreadState::self()->getCallingUid();
66 pid_t callingPid = IPCThreadState::self()->getCallingPid();
67 if (callingUid == AID_ROOT || callingUid == AID_SHELL) {
68 // Root and shell are ok.
69 return Status::ok();
70 }
71
72 if (checkCallingPermission(APPROVE_INCIDENT_REPORTS)) {
73 // Permission controller (this is a singleton permission that is always granted
74 // exactly for PermissionController) is allowed to access incident reports
75 // so it can show the user info about what they are approving.
76 return Status::ok();
77 }
78
79 // checking calling permission.
80 if (!checkCallingPermission(DUMP_PERMISSION)) {
81 ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP",
82 callingPid, callingUid);
83 return Status::fromExceptionCode(
84 Status::EX_SECURITY,
85 "Calling process does not have permission: android.permission.DUMP");
86 }
87 if (!checkCallingPermission(USAGE_STATS_PERMISSION)) {
88 ALOGW("Calling pid %d and uid %d does not have permission: android.permission.USAGE_STATS",
89 callingPid, callingUid);
90 return Status::fromExceptionCode(
91 Status::EX_SECURITY,
92 "Calling process does not have permission: android.permission.USAGE_STATS");
93 }
94
95 // checking calling request uid permission.
96 switch (args.getPrivacyPolicy()) {
97 case PRIVACY_POLICY_LOCAL:
98 if (callingUid != AID_SHELL && callingUid != AID_ROOT) {
99 ALOGW("Calling pid %d and uid %d does not have permission to get local data.",
100 callingPid, callingUid);
101 return Status::fromExceptionCode(
102 Status::EX_SECURITY,
103 "Calling process does not have permission to get local data.");
104 }
105 break;
106 case PRIVACY_POLICY_EXPLICIT:
107 if (callingUid != AID_SHELL && callingUid != AID_ROOT && callingUid != AID_STATSD &&
108 callingUid != AID_SYSTEM) {
109 ALOGW("Calling pid %d and uid %d does not have permission to get explicit data.",
110 callingPid, callingUid);
111 return Status::fromExceptionCode(
112 Status::EX_SECURITY,
113 "Calling process does not have permission to get explicit data.");
114 }
115 break;
116 }
117 return Status::ok();
118 }
119
build_uri(const string & pkg,const string & cls,const string & id)120 static string build_uri(const string& pkg, const string& cls, const string& id) {
121 return "content://android.os.IncidentManager/pending?pkg="
122 + pkg + "&receiver=" + cls + "&r=" + id;
123 }
124
125 // ================================================================================
ReportHandler(const sp<WorkDirectory> & workDirectory,const sp<Broadcaster> & broadcaster,const sp<Looper> & handlerLooper,const sp<Throttler> & throttler)126 ReportHandler::ReportHandler(const sp<WorkDirectory>& workDirectory,
127 const sp<Broadcaster>& broadcaster, const sp<Looper>& handlerLooper,
128 const sp<Throttler>& throttler)
129 :mLock(),
130 mWorkDirectory(workDirectory),
131 mBroadcaster(broadcaster),
132 mHandlerLooper(handlerLooper),
133 mBacklogDelay(DEFAULT_DELAY_NS),
134 mThrottler(throttler),
135 mBatch(new ReportBatch()) {
136 }
137
~ReportHandler()138 ReportHandler::~ReportHandler() {
139 }
140
handleMessage(const Message & message)141 void ReportHandler::handleMessage(const Message& message) {
142 switch (message.what) {
143 case WHAT_TAKE_REPORT:
144 take_report();
145 break;
146 case WHAT_SEND_BROADCASTS:
147 send_broadcasts();
148 break;
149 }
150 }
151
schedulePersistedReport(const IncidentReportArgs & args)152 void ReportHandler::schedulePersistedReport(const IncidentReportArgs& args) {
153 mBatch->addPersistedReport(args);
154 mHandlerLooper->removeMessages(this, WHAT_TAKE_REPORT);
155 mHandlerLooper->sendMessage(this, Message(WHAT_TAKE_REPORT));
156 }
157
scheduleStreamingReport(const IncidentReportArgs & args,const sp<IIncidentReportStatusListener> & listener,int streamFd)158 void ReportHandler::scheduleStreamingReport(const IncidentReportArgs& args,
159 const sp<IIncidentReportStatusListener>& listener, int streamFd) {
160 mBatch->addStreamingReport(args, listener, streamFd);
161 mHandlerLooper->removeMessages(this, WHAT_TAKE_REPORT);
162 mHandlerLooper->sendMessage(this, Message(WHAT_TAKE_REPORT));
163 }
164
scheduleSendBacklog()165 void ReportHandler::scheduleSendBacklog() {
166 unique_lock<mutex> lock(mLock);
167 mBacklogDelay = DEFAULT_DELAY_NS;
168 schedule_send_broadcasts_locked();
169 }
170
schedule_send_broadcasts_locked()171 void ReportHandler::schedule_send_broadcasts_locked() {
172 mHandlerLooper->removeMessages(this, WHAT_SEND_BROADCASTS);
173 mHandlerLooper->sendMessageDelayed(mBacklogDelay, this, Message(WHAT_SEND_BROADCASTS));
174 }
175
take_report()176 void ReportHandler::take_report() {
177 // Cycle the batch and throttle.
178 sp<ReportBatch> batch;
179 {
180 unique_lock<mutex> lock(mLock);
181 batch = mThrottler->filterBatch(mBatch);
182 }
183
184 if (batch->empty()) {
185 // Nothing to do.
186 return;
187 }
188
189 sp<Reporter> reporter = new Reporter(mWorkDirectory, batch);
190
191 // Take the report, which might take a while. More requests might queue
192 // up while we're doing this, and we'll handle them in their next batch.
193 // TODO: We should further rate-limit the reports to no more than N per time-period.
194 // TODO: Move this inside reporter.
195 size_t reportByteSize = 0;
196 reporter->runReport(&reportByteSize);
197
198 // Tell the throttler how big it was, for the next throttling.
199 // TODO: This still isn't ideal. The throttler really should just track the
200 // persisted reqeusts, but changing Reporter::runReport() to track that individually
201 // will be a big change.
202 if (batch->hasPersistedReports()) {
203 mThrottler->addReportSize(reportByteSize);
204 }
205
206 // Kick off the next steps, one of which is to send any new or otherwise remaining
207 // approvals, and one of which is to send any new or remaining broadcasts.
208 {
209 unique_lock<mutex> lock(mLock);
210 schedule_send_broadcasts_locked();
211 }
212 }
213
send_broadcasts()214 void ReportHandler::send_broadcasts() {
215 Broadcaster::broadcast_status_t result = mBroadcaster->sendBroadcasts();
216 if (result == Broadcaster::BROADCASTS_FINISHED) {
217 // We're done.
218 unique_lock<mutex> lock(mLock);
219 mBacklogDelay = DEFAULT_DELAY_NS;
220 } else if (result == Broadcaster::BROADCASTS_REPEAT) {
221 // It worked, but there are more.
222 unique_lock<mutex> lock(mLock);
223 mBacklogDelay = DEFAULT_DELAY_NS;
224 schedule_send_broadcasts_locked();
225 } else if (result == Broadcaster::BROADCASTS_BACKOFF) {
226 // There was a failure. Exponential backoff.
227 unique_lock<mutex> lock(mLock);
228 mBacklogDelay *= 2;
229 ALOGI("Error sending to dropbox. Trying again in %lld minutes",
230 (mBacklogDelay / (1000000000LL * 60)));
231 schedule_send_broadcasts_locked();
232 }
233 }
234
235 // ================================================================================
IncidentService(const sp<Looper> & handlerLooper)236 IncidentService::IncidentService(const sp<Looper>& handlerLooper) {
237 mThrottler = new Throttler(DEFAULT_BYTES_SIZE_LIMIT, DEFAULT_REFACTORY_PERIOD_MS);
238 mWorkDirectory = new WorkDirectory();
239 mBroadcaster = new Broadcaster(mWorkDirectory);
240 mHandler = new ReportHandler(mWorkDirectory, mBroadcaster, handlerLooper,
241 mThrottler);
242 mBroadcaster->setHandler(mHandler);
243 }
244
~IncidentService()245 IncidentService::~IncidentService() {}
246
reportIncident(const IncidentReportArgs & args)247 Status IncidentService::reportIncident(const IncidentReportArgs& args) {
248 IncidentReportArgs argsCopy(args);
249
250 // Validate that the privacy policy is one of the real ones.
251 // If it isn't, clamp it to the next more restrictive real one.
252 argsCopy.setPrivacyPolicy(cleanup_privacy_policy(args.getPrivacyPolicy()));
253
254 // TODO: Check that the broadcast recevier has the proper permissions
255 // TODO: Maybe we should consider relaxing the permissions if it's going to
256 // dropbox, but definitely not if it's going to the broadcaster.
257 Status status = checkIncidentPermissions(args);
258 if (!status.isOk()) {
259 return status;
260 }
261
262 // If they asked for the LOCAL privacy policy, give them EXPLICT. LOCAL has to
263 // be streamed. (This only applies to shell/root, because everyone else would have
264 // been rejected by checkIncidentPermissions()).
265 if (argsCopy.getPrivacyPolicy() < PRIVACY_POLICY_EXPLICIT) {
266 ALOGI("Demoting privacy policy to EXPLICT for persisted report.");
267 argsCopy.setPrivacyPolicy(PRIVACY_POLICY_EXPLICIT);
268 }
269
270 // If they didn't specify a component, use dropbox.
271 if (argsCopy.receiverPkg().length() == 0 && argsCopy.receiverCls().length() == 0) {
272 argsCopy.setReceiverPkg(DROPBOX_SENTINEL.getPackageName());
273 argsCopy.setReceiverCls(DROPBOX_SENTINEL.getClassName());
274 }
275
276 mHandler->schedulePersistedReport(argsCopy);
277
278 return Status::ok();
279 }
280
reportIncidentToStream(const IncidentReportArgs & args,const sp<IIncidentReportStatusListener> & listener,const unique_fd & stream)281 Status IncidentService::reportIncidentToStream(const IncidentReportArgs& args,
282 const sp<IIncidentReportStatusListener>& listener,
283 const unique_fd& stream) {
284 IncidentReportArgs argsCopy(args);
285
286 // Streaming reports can not also be broadcast.
287 argsCopy.setReceiverPkg("");
288 argsCopy.setReceiverCls("");
289
290 // Validate that the privacy policy is one of the real ones.
291 // If it isn't, clamp it to the next more restrictive real one.
292 argsCopy.setPrivacyPolicy(cleanup_privacy_policy(args.getPrivacyPolicy()));
293
294 Status status = checkIncidentPermissions(argsCopy);
295 if (!status.isOk()) {
296 return status;
297 }
298
299 // The ReportRequest takes ownership of the fd, so we need to dup it.
300 int fd = dup(stream.get());
301 if (fd < 0) {
302 return Status::fromStatusT(-errno);
303 }
304
305 mHandler->scheduleStreamingReport(argsCopy, listener, fd);
306
307 return Status::ok();
308 }
309
systemRunning()310 Status IncidentService::systemRunning() {
311 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
312 return Status::fromExceptionCode(Status::EX_SECURITY,
313 "Only system uid can call systemRunning");
314 }
315
316 // When system_server is up and running, schedule the dropbox task to run.
317 mBroadcaster->reset();
318 mHandler->scheduleSendBacklog();
319
320 return Status::ok();
321 }
322
getIncidentReportList(const String16 & pkg16,const String16 & cls16,vector<String16> * result)323 Status IncidentService::getIncidentReportList(const String16& pkg16, const String16& cls16,
324 vector<String16>* result) {
325 status_t err;
326 const string pkg(String8(pkg16).string());
327 const string cls(String8(cls16).string());
328
329 // List the reports
330 vector<sp<ReportFile>> all;
331 err = mWorkDirectory->getReports(&all, 0);
332 if (err != NO_ERROR) {
333 return Status::fromStatusT(err);
334 }
335
336 // Find the ones that match pkg and cls.
337 for (sp<ReportFile>& file: all) {
338 err = file->loadEnvelope();
339 if (err != NO_ERROR) {
340 continue;
341 }
342 const ReportFileProto& envelope = file->getEnvelope();
343 size_t reportCount = envelope.report_size();
344 for (int reportIndex = 0; reportIndex < reportCount; reportIndex++) {
345 const ReportFileProto_Report& report = envelope.report(reportIndex);
346 if (pkg == report.pkg() && cls == report.cls()) {
347 result->push_back(String16(build_uri(pkg, cls, file->getId()).c_str()));
348 break;
349 }
350 }
351 }
352
353 return Status::ok();
354 }
355
getIncidentReport(const String16 & pkg16,const String16 & cls16,const String16 & id16,IncidentManager::IncidentReport * result)356 Status IncidentService::getIncidentReport(const String16& pkg16, const String16& cls16,
357 const String16& id16, IncidentManager::IncidentReport* result) {
358 status_t err;
359
360 const string pkg(String8(pkg16).string());
361 const string cls(String8(cls16).string());
362 const string id(String8(id16).string());
363
364 IncidentReportArgs args;
365 sp<ReportFile> file = mWorkDirectory->getReport(pkg, cls, id, &args);
366 if (file != nullptr) {
367 // Create pipe
368 int fds[2];
369 if (pipe(fds) != 0) {
370 ALOGW("Error opening pipe to filter incident report: %s",
371 file->getDataFileName().c_str());
372 return Status::ok();
373 }
374 result->setTimestampNs(file->getTimestampNs());
375 result->setPrivacyPolicy(file->getEnvelope().privacy_policy());
376 result->takeFileDescriptor(fds[0]);
377 int writeFd = fds[1];
378 // spawn a thread to write the data. Release the writeFd ownership to the thread.
379 thread th([file, writeFd, args]() { file->startFilteringData(writeFd, args); });
380
381 th.detach();
382 }
383
384 return Status::ok();
385 }
386
deleteIncidentReports(const String16 & pkg16,const String16 & cls16,const String16 & id16)387 Status IncidentService::deleteIncidentReports(const String16& pkg16, const String16& cls16,
388 const String16& id16) {
389 const string pkg(String8(pkg16).string());
390 const string cls(String8(cls16).string());
391 const string id(String8(id16).string());
392
393 sp<ReportFile> file = mWorkDirectory->getReport(pkg, cls, id, nullptr);
394 if (file != nullptr) {
395 mWorkDirectory->commit(file, pkg, cls);
396 }
397 mBroadcaster->clearBroadcasts(pkg, cls, id);
398
399 return Status::ok();
400 }
401
deleteAllIncidentReports(const String16 & pkg16)402 Status IncidentService::deleteAllIncidentReports(const String16& pkg16) {
403 const string pkg(String8(pkg16).string());
404
405 mWorkDirectory->commitAll(pkg);
406 mBroadcaster->clearPackageBroadcasts(pkg);
407
408 return Status::ok();
409 }
410
411 /**
412 * Implement our own because the default binder implementation isn't
413 * properly handling SHELL_COMMAND_TRANSACTION.
414 */
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)415 status_t IncidentService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
416 uint32_t flags) {
417 status_t err;
418
419 switch (code) {
420 case SHELL_COMMAND_TRANSACTION: {
421 int in = data.readFileDescriptor();
422 int out = data.readFileDescriptor();
423 int err = data.readFileDescriptor();
424 int argc = data.readInt32();
425 Vector<String8> args;
426 for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
427 args.add(String8(data.readString16()));
428 }
429 sp<IShellCallback> shellCallback = IShellCallback::asInterface(data.readStrongBinder());
430 sp<IResultReceiver> resultReceiver =
431 IResultReceiver::asInterface(data.readStrongBinder());
432
433 FILE* fin = fdopen(in, "r");
434 FILE* fout = fdopen(out, "w");
435 FILE* ferr = fdopen(err, "w");
436
437 if (fin == NULL || fout == NULL || ferr == NULL) {
438 resultReceiver->send(NO_MEMORY);
439 } else {
440 err = command(fin, fout, ferr, args);
441 resultReceiver->send(err);
442 }
443
444 if (fin != NULL) {
445 fflush(fin);
446 fclose(fin);
447 }
448 if (fout != NULL) {
449 fflush(fout);
450 fclose(fout);
451 }
452 if (fout != NULL) {
453 fflush(ferr);
454 fclose(ferr);
455 }
456
457 return NO_ERROR;
458 } break;
459 default: { return BnIncidentManager::onTransact(code, data, reply, flags); }
460 }
461 }
462
command(FILE * in,FILE * out,FILE * err,Vector<String8> & args)463 status_t IncidentService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
464 const int argCount = args.size();
465
466 if (argCount >= 1) {
467 if (!args[0].compare(String8("privacy"))) {
468 return cmd_privacy(in, out, err, args);
469 }
470 if (!args[0].compare(String8("throttler"))) {
471 mThrottler->dump(out);
472 return NO_ERROR;
473 }
474 if (!args[0].compare(String8("section"))) {
475 int id = atoi(args[1]);
476 int idx = 0;
477 while (SECTION_LIST[idx] != NULL) {
478 const Section* section = SECTION_LIST[idx];
479 if (section->id == id) {
480 fprintf(out, "Section[%d] %s\n", id, section->name.string());
481 break;
482 }
483 idx++;
484 }
485 return NO_ERROR;
486 }
487 }
488 return cmd_help(out);
489 }
490
cmd_help(FILE * out)491 status_t IncidentService::cmd_help(FILE* out) {
492 fprintf(out, "usage: adb shell cmd incident privacy print <section_id>\n");
493 fprintf(out, "usage: adb shell cmd incident privacy parse <section_id> < proto.txt\n");
494 fprintf(out, " Prints/parses for the section id.\n\n");
495 fprintf(out, "usage: adb shell cmd incident section <section_id>\n");
496 fprintf(out, " Prints section id and its name.\n\n");
497 fprintf(out, "usage: adb shell cmd incident throttler\n");
498 fprintf(out, " Prints the current throttler state\n");
499 return NO_ERROR;
500 }
501
printPrivacy(const Privacy * p,FILE * out,String8 indent)502 static void printPrivacy(const Privacy* p, FILE* out, String8 indent) {
503 if (p == NULL) return;
504 fprintf(out, "%sid:%d, type:%d, dest:%d\n", indent.string(), p->field_id, p->type, p->policy);
505 if (p->children == NULL) return;
506 for (int i = 0; p->children[i] != NULL; i++) { // NULL-terminated.
507 printPrivacy(p->children[i], out, indent + " ");
508 }
509 }
510
cmd_privacy(FILE * in,FILE * out,FILE * err,Vector<String8> & args)511 status_t IncidentService::cmd_privacy(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
512 (void)in;
513
514 const int argCount = args.size();
515 if (argCount >= 3) {
516 String8 opt = args[1];
517 int sectionId = atoi(args[2].string());
518
519 const Privacy* p = get_privacy_of_section(sectionId);
520 if (p == NULL) {
521 fprintf(err, "Can't find section id %d\n", sectionId);
522 return NO_ERROR;
523 }
524 fprintf(err, "Get privacy for %d\n", sectionId);
525 if (opt == "print") {
526 printPrivacy(p, out, String8(""));
527 } else if (opt == "parse") {
528 /*
529 FdBuffer buf;
530 status_t error = buf.read(fileno(in), 60000);
531 if (error != NO_ERROR) {
532 fprintf(err, "Error reading from stdin\n");
533 return error;
534 }
535 fprintf(err, "Read %zu bytes\n", buf.size());
536 PrivacyFilter pBuf(p, buf.data());
537
538 PrivacySpec spec = PrivacySpec::new_spec(argCount > 3 ? atoi(args[3]) : -1);
539 error = pBuf.strip(spec);
540 if (error != NO_ERROR) {
541 fprintf(err, "Error strip pii fields with spec %d\n", spec.policy);
542 return error;
543 }
544 return pBuf.flush(fileno(out));
545 */
546 return -1;
547 }
548 } else {
549 return cmd_help(out);
550 }
551 return NO_ERROR;
552 }
553
dump(int fd,const Vector<String16> & args)554 status_t IncidentService::dump(int fd, const Vector<String16>& args) {
555 if (std::find(args.begin(), args.end(), String16("--proto")) == args.end()) {
556 ALOGD("Skip dumping incident. Only proto format is supported.");
557 dprintf(fd, "Incident dump only supports proto version.\n");
558 return NO_ERROR;
559 }
560
561 ALOGD("Dump incident proto");
562 IncidentReportArgs incidentArgs;
563 incidentArgs.setPrivacyPolicy(PRIVACY_POLICY_EXPLICIT);
564 int skipped[] = SKIPPED_SECTIONS;
565 for (const Section** section = SECTION_LIST; *section; section++) {
566 const int id = (*section)->id;
567 if (std::find(std::begin(skipped), std::end(skipped), id) == std::end(skipped)
568 && !section_requires_specific_mention(id)) {
569 incidentArgs.addSection(id);
570 }
571 }
572
573 if (!checkIncidentPermissions(incidentArgs).isOk()) {
574 return PERMISSION_DENIED;
575 }
576
577 // The ReportRequest takes ownership of the fd, so we need to dup it.
578 int fd1 = dup(fd);
579 if (fd1 < 0) {
580 return -errno;
581 }
582
583 // TODO: Remove this. Someone even dumpstate, wanting to get an incident report
584 // should use the API. That will take making dumpstated call the API, which is a
585 // good thing. It also means it won't be subject to the timeout.
586 mHandler->scheduleStreamingReport(incidentArgs, NULL, fd1);
587
588 return NO_ERROR;
589 }
590
591 } // namespace incidentd
592 } // namespace os
593 } // namespace android
594