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 "PrivacyBuffer.h"
23 #include "Reporter.h"
24 #include "incidentd_util.h"
25 #include "section_list.h"
26
27 #include <binder/IPCThreadState.h>
28 #include <binder/IResultReceiver.h>
29 #include <binder/IServiceManager.h>
30 #include <binder/IShellCallback.h>
31 #include <cutils/log.h>
32 #include <private/android_filesystem_config.h>
33 #include <utils/Looper.h>
34
35 #include <unistd.h>
36
37 enum { WHAT_RUN_REPORT = 1, WHAT_SEND_BACKLOG_TO_DROPBOX = 2 };
38
39 #define DEFAULT_BACKLOG_DELAY_NS (1000000000LL)
40
41 #define DEFAULT_BYTES_SIZE_LIMIT (20 * 1024 * 1024) // 20MB
42 #define DEFAULT_REFACTORY_PERIOD_MS (24 * 60 * 60 * 1000) // 1 Day
43
44 namespace android {
45 namespace os {
46 namespace incidentd {
47
48 String16 const DUMP_PERMISSION("android.permission.DUMP");
49 String16 const USAGE_STATS_PERMISSION("android.permission.PACKAGE_USAGE_STATS");
50
checkIncidentPermissions(const IncidentReportArgs & args)51 static Status checkIncidentPermissions(const IncidentReportArgs& args) {
52 uid_t callingUid = IPCThreadState::self()->getCallingUid();
53 pid_t callingPid = IPCThreadState::self()->getCallingPid();
54 if (callingUid == AID_ROOT || callingUid == AID_SHELL) {
55 // root doesn't have permission.DUMP if don't do this!
56 return Status::ok();
57 }
58
59 // checking calling permission.
60 if (!checkCallingPermission(DUMP_PERMISSION)) {
61 ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP",
62 callingPid, callingUid);
63 return Status::fromExceptionCode(
64 Status::EX_SECURITY,
65 "Calling process does not have permission: android.permission.DUMP");
66 }
67 if (!checkCallingPermission(USAGE_STATS_PERMISSION)) {
68 ALOGW("Calling pid %d and uid %d does not have permission: android.permission.USAGE_STATS",
69 callingPid, callingUid);
70 return Status::fromExceptionCode(
71 Status::EX_SECURITY,
72 "Calling process does not have permission: android.permission.USAGE_STATS");
73 }
74
75 // checking calling request uid permission.
76 switch (args.dest()) {
77 case DEST_LOCAL:
78 if (callingUid != AID_SHELL && callingUid != AID_ROOT) {
79 ALOGW("Calling pid %d and uid %d does not have permission to get local data.",
80 callingPid, callingUid);
81 return Status::fromExceptionCode(
82 Status::EX_SECURITY,
83 "Calling process does not have permission to get local data.");
84 }
85 case DEST_EXPLICIT:
86 if (callingUid != AID_SHELL && callingUid != AID_ROOT && callingUid != AID_STATSD &&
87 callingUid != AID_SYSTEM) {
88 ALOGW("Calling pid %d and uid %d does not have permission to get explicit data.",
89 callingPid, callingUid);
90 return Status::fromExceptionCode(
91 Status::EX_SECURITY,
92 "Calling process does not have permission to get explicit data.");
93 }
94 }
95 return Status::ok();
96 }
97
98 // ================================================================================
ReportRequestQueue()99 ReportRequestQueue::ReportRequestQueue() {}
100
~ReportRequestQueue()101 ReportRequestQueue::~ReportRequestQueue() {}
102
addRequest(const sp<ReportRequest> & request)103 void ReportRequestQueue::addRequest(const sp<ReportRequest>& request) {
104 unique_lock<mutex> lock(mLock);
105 mQueue.push_back(request);
106 }
107
getNextRequest()108 sp<ReportRequest> ReportRequestQueue::getNextRequest() {
109 unique_lock<mutex> lock(mLock);
110 if (mQueue.empty()) {
111 return NULL;
112 } else {
113 sp<ReportRequest> front(mQueue.front());
114 mQueue.pop_front();
115 return front;
116 }
117 }
118
119 // ================================================================================
ReportHandler(const sp<Looper> & handlerLooper,const sp<ReportRequestQueue> & queue,const sp<Throttler> & throttler)120 ReportHandler::ReportHandler(const sp<Looper>& handlerLooper, const sp<ReportRequestQueue>& queue,
121 const sp<Throttler>& throttler)
122 : mBacklogDelay(DEFAULT_BACKLOG_DELAY_NS),
123 mHandlerLooper(handlerLooper),
124 mQueue(queue),
125 mThrottler(throttler) {}
126
~ReportHandler()127 ReportHandler::~ReportHandler() {}
128
handleMessage(const Message & message)129 void ReportHandler::handleMessage(const Message& message) {
130 switch (message.what) {
131 case WHAT_RUN_REPORT:
132 run_report();
133 break;
134 case WHAT_SEND_BACKLOG_TO_DROPBOX:
135 send_backlog_to_dropbox();
136 break;
137 }
138 }
139
scheduleRunReport(const sp<ReportRequest> & request)140 void ReportHandler::scheduleRunReport(const sp<ReportRequest>& request) {
141 mQueue->addRequest(request);
142 mHandlerLooper->removeMessages(this, WHAT_RUN_REPORT);
143 mHandlerLooper->sendMessage(this, Message(WHAT_RUN_REPORT));
144 }
145
scheduleSendBacklogToDropbox()146 void ReportHandler::scheduleSendBacklogToDropbox() {
147 unique_lock<mutex> lock(mLock);
148 mBacklogDelay = DEFAULT_BACKLOG_DELAY_NS;
149 schedule_send_backlog_to_dropbox_locked();
150 }
151
schedule_send_backlog_to_dropbox_locked()152 void ReportHandler::schedule_send_backlog_to_dropbox_locked() {
153 mHandlerLooper->removeMessages(this, WHAT_SEND_BACKLOG_TO_DROPBOX);
154 mHandlerLooper->sendMessageDelayed(mBacklogDelay, this, Message(WHAT_SEND_BACKLOG_TO_DROPBOX));
155 }
156
run_report()157 void ReportHandler::run_report() {
158 sp<Reporter> reporter = new Reporter();
159
160 // Merge all of the requests into one that has all of the
161 // requested fields.
162 while (true) {
163 sp<ReportRequest> request = mQueue->getNextRequest();
164 if (request == NULL) {
165 break;
166 }
167 reporter->batch.add(request);
168 }
169
170 if (mThrottler->shouldThrottle()) {
171 ALOGW("RunReport got throttled.");
172 return;
173 }
174
175 // Take the report, which might take a while. More requests might queue
176 // up while we're doing this, and we'll handle them in their next batch.
177 // TODO: We should further rate-limit the reports to no more than N per time-period.
178 size_t reportByteSize = 0;
179 Reporter::run_report_status_t reportStatus = reporter->runReport(&reportByteSize);
180 mThrottler->addReportSize(reportByteSize);
181 if (reportStatus == Reporter::REPORT_NEEDS_DROPBOX) {
182 unique_lock<mutex> lock(mLock);
183 schedule_send_backlog_to_dropbox_locked();
184 }
185 }
186
send_backlog_to_dropbox()187 void ReportHandler::send_backlog_to_dropbox() {
188 if (Reporter::upload_backlog() == Reporter::REPORT_NEEDS_DROPBOX) {
189 // There was a failure. Exponential backoff.
190 unique_lock<mutex> lock(mLock);
191 mBacklogDelay *= 2;
192 ALOGI("Error sending to dropbox. Trying again in %lld minutes",
193 (mBacklogDelay / (1000000000LL * 60)));
194 schedule_send_backlog_to_dropbox_locked();
195 } else {
196 mBacklogDelay = DEFAULT_BACKLOG_DELAY_NS;
197 }
198 }
199
200 // ================================================================================
IncidentService(const sp<Looper> & handlerLooper)201 IncidentService::IncidentService(const sp<Looper>& handlerLooper)
202 : mQueue(new ReportRequestQueue()),
203 mThrottler(new Throttler(DEFAULT_BYTES_SIZE_LIMIT, DEFAULT_REFACTORY_PERIOD_MS)) {
204 mHandler = new ReportHandler(handlerLooper, mQueue, mThrottler);
205 }
206
~IncidentService()207 IncidentService::~IncidentService() {}
208
reportIncident(const IncidentReportArgs & args)209 Status IncidentService::reportIncident(const IncidentReportArgs& args) {
210 ALOGI("reportIncident");
211
212 Status status = checkIncidentPermissions(args);
213 if (!status.isOk()) {
214 return status;
215 }
216
217 mHandler->scheduleRunReport(new ReportRequest(args, NULL, -1));
218
219 return Status::ok();
220 }
221
reportIncidentToStream(const IncidentReportArgs & args,const sp<IIncidentReportStatusListener> & listener,const unique_fd & stream)222 Status IncidentService::reportIncidentToStream(const IncidentReportArgs& args,
223 const sp<IIncidentReportStatusListener>& listener,
224 const unique_fd& stream) {
225 ALOGI("reportIncidentToStream");
226
227 Status status = checkIncidentPermissions(args);
228 if (!status.isOk()) {
229 return status;
230 }
231
232 int fd = dup(stream.get());
233 if (fd < 0) {
234 return Status::fromStatusT(-errno);
235 }
236
237 mHandler->scheduleRunReport(new ReportRequest(args, listener, fd));
238
239 return Status::ok();
240 }
241
systemRunning()242 Status IncidentService::systemRunning() {
243 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
244 return Status::fromExceptionCode(Status::EX_SECURITY,
245 "Only system uid can call systemRunning");
246 }
247
248 // When system_server is up and running, schedule the dropbox task to run.
249 mHandler->scheduleSendBacklogToDropbox();
250
251 return Status::ok();
252 }
253
254 /**
255 * Implement our own because the default binder implementation isn't
256 * properly handling SHELL_COMMAND_TRANSACTION.
257 */
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)258 status_t IncidentService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
259 uint32_t flags) {
260 status_t err;
261
262 switch (code) {
263 case SHELL_COMMAND_TRANSACTION: {
264 int in = data.readFileDescriptor();
265 int out = data.readFileDescriptor();
266 int err = data.readFileDescriptor();
267 int argc = data.readInt32();
268 Vector<String8> args;
269 for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
270 args.add(String8(data.readString16()));
271 }
272 sp<IShellCallback> shellCallback = IShellCallback::asInterface(data.readStrongBinder());
273 sp<IResultReceiver> resultReceiver =
274 IResultReceiver::asInterface(data.readStrongBinder());
275
276 FILE* fin = fdopen(in, "r");
277 FILE* fout = fdopen(out, "w");
278 FILE* ferr = fdopen(err, "w");
279
280 if (fin == NULL || fout == NULL || ferr == NULL) {
281 resultReceiver->send(NO_MEMORY);
282 } else {
283 err = command(fin, fout, ferr, args);
284 resultReceiver->send(err);
285 }
286
287 if (fin != NULL) {
288 fflush(fin);
289 fclose(fin);
290 }
291 if (fout != NULL) {
292 fflush(fout);
293 fclose(fout);
294 }
295 if (fout != NULL) {
296 fflush(ferr);
297 fclose(ferr);
298 }
299
300 return NO_ERROR;
301 }
302 default: { return BnIncidentManager::onTransact(code, data, reply, flags); }
303 }
304 }
305
command(FILE * in,FILE * out,FILE * err,Vector<String8> & args)306 status_t IncidentService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
307 const int argCount = args.size();
308
309 if (argCount >= 1) {
310 if (!args[0].compare(String8("privacy"))) {
311 return cmd_privacy(in, out, err, args);
312 }
313 if (!args[0].compare(String8("throttler"))) {
314 mThrottler->dump(out);
315 return NO_ERROR;
316 }
317 }
318 return cmd_help(out);
319 }
320
cmd_help(FILE * out)321 status_t IncidentService::cmd_help(FILE* out) {
322 fprintf(out, "usage: adb shell cmd incident privacy print <section_id>\n");
323 fprintf(out, "usage: adb shell cmd incident privacy parse <section_id> < proto.txt\n");
324 fprintf(out, " Prints/parses for the section id.\n");
325 fprintf(out, "\n");
326 fprintf(out, "usage: adb shell cmd incident throttler\n");
327 fprintf(out, " Prints the current throttler state\n");
328 return NO_ERROR;
329 }
330
printPrivacy(const Privacy * p,FILE * out,String8 indent)331 static void printPrivacy(const Privacy* p, FILE* out, String8 indent) {
332 if (p == NULL) return;
333 fprintf(out, "%sid:%d, type:%d, dest:%d\n", indent.string(), p->field_id, p->type, p->dest);
334 if (p->children == NULL) return;
335 for (int i = 0; p->children[i] != NULL; i++) { // NULL-terminated.
336 printPrivacy(p->children[i], out, indent + " ");
337 }
338 }
339
cmd_privacy(FILE * in,FILE * out,FILE * err,Vector<String8> & args)340 status_t IncidentService::cmd_privacy(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
341 const int argCount = args.size();
342 if (argCount >= 3) {
343 String8 opt = args[1];
344 int sectionId = atoi(args[2].string());
345
346 const Privacy* p = get_privacy_of_section(sectionId);
347 if (p == NULL) {
348 fprintf(err, "Can't find section id %d\n", sectionId);
349 return NO_ERROR;
350 }
351 fprintf(err, "Get privacy for %d\n", sectionId);
352 if (opt == "print") {
353 printPrivacy(p, out, String8(""));
354 } else if (opt == "parse") {
355 FdBuffer buf;
356 status_t error = buf.read(fileno(in), 60000);
357 if (error != NO_ERROR) {
358 fprintf(err, "Error reading from stdin\n");
359 return error;
360 }
361 fprintf(err, "Read %zu bytes\n", buf.size());
362 PrivacyBuffer pBuf(p, buf.data());
363
364 PrivacySpec spec = PrivacySpec::new_spec(argCount > 3 ? atoi(args[3]) : -1);
365 error = pBuf.strip(spec);
366 if (error != NO_ERROR) {
367 fprintf(err, "Error strip pii fields with spec %d\n", spec.dest);
368 return error;
369 }
370 return pBuf.flush(fileno(out));
371 }
372 } else {
373 return cmd_help(out);
374 }
375 return NO_ERROR;
376 }
377
378 } // namespace incidentd
379 } // namespace os
380 } // namespace android
381