1 /*
2 * Copyright (C) 2018 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 "apexservice.h"
18
19 #include <android-base/file.h>
20 #include <android-base/logging.h>
21 #include <android-base/properties.h>
22 #include <android-base/result.h>
23 #include <android-base/stringprintf.h>
24 #include <android-base/strings.h>
25 #include <android/apex/BnApexService.h>
26 #include <binder/IPCThreadState.h>
27 #include <binder/IResultReceiver.h>
28 #include <binder/IServiceManager.h>
29 #include <binder/LazyServiceRegistrar.h>
30 #include <binder/ProcessState.h>
31 #include <binder/Status.h>
32 #include <dirent.h>
33 #include <private/android_filesystem_config.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <utils/String16.h>
37
38 #include "apex_constants.h"
39 #include "apex_file.h"
40 #include "apex_file_repository.h"
41 #include "apexd.h"
42 #include "apexd_metrics.h"
43 #include "apexd_session.h"
44 #include "string_log.h"
45
46 using android::base::Join;
47 using android::base::Result;
48
49 namespace android {
50 namespace apex {
51 namespace binder {
52 namespace {
53
54 using BinderStatus = ::android::binder::Status;
55
CheckCallerIsRoot(const std::string & name)56 BinderStatus CheckCallerIsRoot(const std::string& name) {
57 uid_t uid = IPCThreadState::self()->getCallingUid();
58 if (uid != AID_ROOT) {
59 std::string msg = "Only root is allowed to call " + name;
60 return BinderStatus::fromExceptionCode(BinderStatus::EX_SECURITY,
61 String8(msg.c_str()));
62 }
63 return BinderStatus::ok();
64 }
65
CheckCallerSystemOrRoot(const std::string & name)66 BinderStatus CheckCallerSystemOrRoot(const std::string& name) {
67 uid_t uid = IPCThreadState::self()->getCallingUid();
68 if (uid != AID_ROOT && uid != AID_SYSTEM) {
69 std::string msg = "Only root and system_server are allowed to call " + name;
70 return BinderStatus::fromExceptionCode(BinderStatus::EX_SECURITY,
71 String8(msg.c_str()));
72 }
73 return BinderStatus::ok();
74 }
75
76 class ApexService : public BnApexService {
77 public:
78 using BinderStatus = ::android::binder::Status;
79 using SessionState = ::apex::proto::SessionState;
80
ApexService()81 ApexService(){};
82
83 BinderStatus stagePackages(const std::vector<std::string>& paths) override;
84 BinderStatus unstagePackages(const std::vector<std::string>& paths) override;
85 BinderStatus submitStagedSession(const ApexSessionParams& params,
86 ApexInfoList* apex_info_list) override;
87 BinderStatus markStagedSessionReady(int session_id) override;
88 BinderStatus markStagedSessionSuccessful(int session_id) override;
89 BinderStatus getSessions(std::vector<ApexSessionInfo>* aidl_return) override;
90 BinderStatus getStagedSessionInfo(
91 int session_id, ApexSessionInfo* apex_session_info) override;
92 BinderStatus getStagedApexInfos(const ApexSessionParams& params,
93 std::vector<ApexInfo>* aidl_return) override;
94 BinderStatus getActivePackages(std::vector<ApexInfo>* aidl_return) override;
95 BinderStatus getActivePackage(const std::string& package_name,
96 ApexInfo* aidl_return) override;
97 BinderStatus getAllPackages(std::vector<ApexInfo>* aidl_return) override;
98 BinderStatus abortStagedSession(int session_id) override;
99 BinderStatus revertActiveSessions() override;
100 BinderStatus resumeRevertIfNeeded() override;
101 BinderStatus snapshotCeData(int user_id, int rollback_id,
102 const std::string& apex_name) override;
103 BinderStatus restoreCeData(int user_id, int rollback_id,
104 const std::string& apex_name) override;
105 BinderStatus destroyDeSnapshots(int rollback_id) override;
106 BinderStatus destroyCeSnapshots(int user_id, int rollback_id) override;
107 BinderStatus destroyCeSnapshotsNotSpecified(
108 int user_id, const std::vector<int>& retain_rollback_ids) override;
109 BinderStatus recollectPreinstalledData() override;
110 BinderStatus markBootCompleted() override;
111 BinderStatus calculateSizeForCompressedApex(
112 const CompressedApexInfoList& compressed_apex_info_list,
113 int64_t* required_size) override;
114 BinderStatus reserveSpaceForCompressedApex(
115 const CompressedApexInfoList& compressed_apex_info_list) override;
116 BinderStatus installAndActivatePackage(const std::string& package_path,
117 bool force,
118 ApexInfo* aidl_return) override;
119
120 status_t dump(int fd, const Vector<String16>& args) override;
121
122 // Override onTransact so we can handle shellCommand.
123 status_t onTransact(uint32_t _aidl_code, const Parcel& _aidl_data,
124 Parcel* _aidl_reply, uint32_t _aidl_flags) override;
125
126 status_t shellCommand(int in, int out, int err, const Vector<String16>& args);
127 };
128
CheckDebuggable(const std::string & name)129 BinderStatus CheckDebuggable(const std::string& name) {
130 if (!::android::base::GetBoolProperty("ro.debuggable", false)) {
131 std::string tmp = name + " unavailable on non-debuggable builds";
132 return BinderStatus::fromExceptionCode(BinderStatus::EX_SECURITY,
133 String8(tmp.c_str()));
134 }
135 return BinderStatus::ok();
136 }
137
stagePackages(const std::vector<std::string> & paths)138 BinderStatus ApexService::stagePackages(const std::vector<std::string>& paths) {
139 LOG(INFO) << "stagePackages() received by ApexService, paths "
140 << android::base::Join(paths, ',');
141
142 BinderStatus debug_check = CheckDebuggable("stagePackages");
143 if (!debug_check.isOk()) {
144 return debug_check;
145 }
146 if (auto is_root = CheckCallerIsRoot("stagePackages"); !is_root.isOk()) {
147 return is_root;
148 }
149 Result<void> res = ::android::apex::StagePackages(paths);
150
151 if (res.ok()) {
152 return BinderStatus::ok();
153 }
154
155 LOG(ERROR) << "Failed to stage " << android::base::Join(paths, ',') << ": "
156 << res.error();
157 return BinderStatus::fromExceptionCode(
158 BinderStatus::EX_SERVICE_SPECIFIC,
159 String8(res.error().message().c_str()));
160 }
161
unstagePackages(const std::vector<std::string> & paths)162 BinderStatus ApexService::unstagePackages(
163 const std::vector<std::string>& paths) {
164 LOG(INFO) << "unstagePackages() received by ApexService, paths "
165 << android::base::Join(paths, ',');
166
167 if (auto check = CheckCallerSystemOrRoot("unstagePackages"); !check.isOk()) {
168 return check;
169 }
170
171 Result<void> res = ::android::apex::UnstagePackages(paths);
172 if (res.ok()) {
173 return BinderStatus::ok();
174 }
175
176 LOG(ERROR) << "Failed to unstage " << android::base::Join(paths, ',') << ": "
177 << res.error();
178 return BinderStatus::fromExceptionCode(
179 BinderStatus::EX_SERVICE_SPECIFIC,
180 String8(res.error().message().c_str()));
181 }
182
submitStagedSession(const ApexSessionParams & params,ApexInfoList * apex_info_list)183 BinderStatus ApexService::submitStagedSession(const ApexSessionParams& params,
184 ApexInfoList* apex_info_list) {
185 LOG(INFO) << "submitStagedSession() received by ApexService, session id "
186 << params.sessionId << " child sessions: ["
187 << android::base::Join(params.childSessionIds, ',') << "]";
188
189 auto check = CheckCallerSystemOrRoot("submitStagedSession");
190 if (!check.isOk()) {
191 return check;
192 }
193
194 Result<std::vector<ApexFile>> packages = ::android::apex::SubmitStagedSession(
195 params.sessionId, params.childSessionIds, params.hasRollbackEnabled,
196 params.isRollback, params.rollbackId);
197 if (!packages.ok()) {
198 LOG(ERROR) << "Failed to submit session id " << params.sessionId << ": "
199 << packages.error();
200 return BinderStatus::fromExceptionCode(
201 BinderStatus::EX_SERVICE_SPECIFIC,
202 String8(packages.error().message().c_str()));
203 }
204
205 for (const auto& package : *packages) {
206 ApexInfo out;
207 out.moduleName = package.GetManifest().name();
208 out.modulePath = package.GetPath();
209 out.versionCode = package.GetManifest().version();
210 apex_info_list->apexInfos.push_back(out);
211 }
212 return BinderStatus::ok();
213 }
214
markStagedSessionReady(int session_id)215 BinderStatus ApexService::markStagedSessionReady(int session_id) {
216 LOG(INFO) << "markStagedSessionReady() received by ApexService, session id "
217 << session_id;
218
219 auto check = CheckCallerSystemOrRoot("markStagedSessionReady");
220 if (!check.isOk()) {
221 return check;
222 }
223
224 Result<void> success = ::android::apex::MarkStagedSessionReady(session_id);
225 if (!success.ok()) {
226 LOG(ERROR) << "Failed to mark session id " << session_id
227 << " as ready: " << success.error();
228 return BinderStatus::fromExceptionCode(
229 BinderStatus::EX_SERVICE_SPECIFIC,
230 String8(success.error().message().c_str()));
231 }
232 return BinderStatus::ok();
233 }
234
markStagedSessionSuccessful(int session_id)235 BinderStatus ApexService::markStagedSessionSuccessful(int session_id) {
236 LOG(INFO)
237 << "markStagedSessionSuccessful() received by ApexService, session id "
238 << session_id;
239
240 auto check = CheckCallerSystemOrRoot("markStagedSessionSuccessful");
241 if (!check.isOk()) {
242 return check;
243 }
244
245 Result<void> ret = ::android::apex::MarkStagedSessionSuccessful(session_id);
246 if (!ret.ok()) {
247 LOG(ERROR) << "Failed to mark session " << session_id
248 << " as SUCCESS: " << ret.error();
249 return BinderStatus::fromExceptionCode(
250 BinderStatus::EX_ILLEGAL_ARGUMENT,
251 String8(ret.error().message().c_str()));
252 }
253 return BinderStatus::ok();
254 }
255
markBootCompleted()256 BinderStatus ApexService::markBootCompleted() {
257 LOG(INFO) << "markBootCompleted() received by ApexService";
258
259 auto check = CheckCallerSystemOrRoot("markBootCompleted");
260 if (!check.isOk()) {
261 return check;
262 }
263
264 ::android::apex::OnBootCompleted();
265 return BinderStatus::ok();
266 }
267
calculateSizeForCompressedApex(const CompressedApexInfoList & compressed_apex_info_list,int64_t * required_size)268 BinderStatus ApexService::calculateSizeForCompressedApex(
269 const CompressedApexInfoList& compressed_apex_info_list,
270 int64_t* required_size) {
271 std::vector<std::tuple<std::string, int64_t, int64_t>> compressed_apexes;
272 compressed_apexes.reserve(compressed_apex_info_list.apexInfos.size());
273 for (const auto& apex_info : compressed_apex_info_list.apexInfos) {
274 compressed_apexes.emplace_back(apex_info.moduleName, apex_info.versionCode,
275 apex_info.decompressedSize);
276 }
277 const auto& instance = ApexFileRepository::GetInstance();
278 *required_size = ::android::apex::CalculateSizeForCompressedApex(
279 compressed_apexes, instance);
280 return BinderStatus::ok();
281 }
282
reserveSpaceForCompressedApex(const CompressedApexInfoList & compressed_apex_info_list)283 BinderStatus ApexService::reserveSpaceForCompressedApex(
284 const CompressedApexInfoList& compressed_apex_info_list) {
285 int64_t required_size;
286 if (auto res = calculateSizeForCompressedApex(compressed_apex_info_list,
287 &required_size);
288 !res.isOk()) {
289 return res;
290 }
291 if (auto res = ReserveSpaceForCompressedApex(required_size, kOtaReservedDir);
292 !res.ok()) {
293 return BinderStatus::fromExceptionCode(
294 BinderStatus::EX_SERVICE_SPECIFIC,
295 String8(res.error().message().c_str()));
296 }
297 return BinderStatus::ok();
298 }
299
ClearSessionInfo(ApexSessionInfo * session_info)300 static void ClearSessionInfo(ApexSessionInfo* session_info) {
301 session_info->sessionId = -1;
302 session_info->isUnknown = false;
303 session_info->isVerified = false;
304 session_info->isStaged = false;
305 session_info->isActivated = false;
306 session_info->isRevertInProgress = false;
307 session_info->isActivationFailed = false;
308 session_info->isSuccess = false;
309 session_info->isReverted = false;
310 session_info->isRevertFailed = false;
311 }
312
ConvertToApexSessionInfo(const ApexSession & session,ApexSessionInfo * session_info)313 void ConvertToApexSessionInfo(const ApexSession& session,
314 ApexSessionInfo* session_info) {
315 using SessionState = ::apex::proto::SessionState;
316
317 ClearSessionInfo(session_info);
318 session_info->sessionId = session.GetId();
319 session_info->crashingNativeProcess = session.GetCrashingNativeProcess();
320 session_info->errorMessage = session.GetErrorMessage();
321
322 switch (session.GetState()) {
323 case SessionState::VERIFIED:
324 session_info->isVerified = true;
325 break;
326 case SessionState::STAGED:
327 session_info->isStaged = true;
328 break;
329 case SessionState::ACTIVATED:
330 session_info->isActivated = true;
331 break;
332 case SessionState::ACTIVATION_FAILED:
333 session_info->isActivationFailed = true;
334 break;
335 case SessionState::SUCCESS:
336 session_info->isSuccess = true;
337 break;
338 case SessionState::REVERT_IN_PROGRESS:
339 session_info->isRevertInProgress = true;
340 break;
341 case SessionState::REVERTED:
342 session_info->isReverted = true;
343 break;
344 case SessionState::REVERT_FAILED:
345 session_info->isRevertFailed = true;
346 break;
347 case SessionState::UNKNOWN:
348 default:
349 session_info->isUnknown = true;
350 break;
351 }
352 }
353
Cast(ApexPartition in)354 static ::android::apex::ApexInfo::Partition Cast(ApexPartition in) {
355 switch (in) {
356 case ApexPartition::System:
357 return ::android::apex::ApexInfo::Partition::SYSTEM;
358 case ApexPartition::SystemExt:
359 return ::android::apex::ApexInfo::Partition::SYSTEM_EXT;
360 case ApexPartition::Product:
361 return ::android::apex::ApexInfo::Partition::PRODUCT;
362 case ApexPartition::Vendor:
363 return ::android::apex::ApexInfo::Partition::VENDOR;
364 case ApexPartition::Odm:
365 return ::android::apex::ApexInfo::Partition::ODM;
366 }
367 }
368
GetApexInfo(const ApexFile & package)369 static ApexInfo GetApexInfo(const ApexFile& package) {
370 auto& instance = ApexFileRepository::GetInstance();
371 ApexInfo out;
372 out.moduleName = package.GetManifest().name();
373 out.modulePath = package.GetPath();
374 out.versionCode = package.GetManifest().version();
375 out.versionName = package.GetManifest().versionname();
376 out.isFactory = instance.IsPreInstalledApex(package);
377 out.isActive = false;
378 Result<std::string> preinstalled_path =
379 instance.GetPreinstalledPath(package.GetManifest().name());
380 if (preinstalled_path.ok()) {
381 out.preinstalledModulePath = *preinstalled_path;
382 }
383 out.activeApexChanged = ::android::apex::IsActiveApexChanged(package);
384 out.partition = Cast(OR_FATAL(instance.GetPartition(package)));
385 return out;
386 }
387
ToString(const ApexInfo & package)388 static std::string ToString(const ApexInfo& package) {
389 std::string msg =
390 StringLog() << "Module: " << package.moduleName
391 << " Version: " << package.versionCode
392 << " VersionName: " << package.versionName
393 << " Path: " << package.modulePath
394 << " IsActive: " << std::boolalpha << package.isActive
395 << " IsFactory: " << std::boolalpha << package.isFactory
396 << " Partition: " << toString(package.partition) << std::endl;
397 return msg;
398 }
399
getSessions(std::vector<ApexSessionInfo> * aidl_return)400 BinderStatus ApexService::getSessions(
401 std::vector<ApexSessionInfo>* aidl_return) {
402 LOG(INFO) << "getSessions() received by ApexService";
403
404 auto check = CheckCallerSystemOrRoot("getSessions");
405 if (!check.isOk()) {
406 return check;
407 }
408
409 auto sessions = GetSessionManager()->GetSessions();
410 for (const auto& session : sessions) {
411 ApexSessionInfo session_info;
412 ConvertToApexSessionInfo(session, &session_info);
413 aidl_return->push_back(session_info);
414 }
415
416 return BinderStatus::ok();
417 }
418
getStagedSessionInfo(int session_id,ApexSessionInfo * apex_session_info)419 BinderStatus ApexService::getStagedSessionInfo(
420 int session_id, ApexSessionInfo* apex_session_info) {
421 LOG(INFO) << "getStagedSessionInfo() received by ApexService, session id "
422 << session_id;
423
424 auto check = CheckCallerSystemOrRoot("getStagedSessionInfo");
425 if (!check.isOk()) {
426 return check;
427 }
428
429 auto session = GetSessionManager()->GetSession(session_id);
430 if (!session.ok()) {
431 // Unknown session.
432 ClearSessionInfo(apex_session_info);
433 apex_session_info->isUnknown = true;
434 return BinderStatus::ok();
435 }
436
437 ConvertToApexSessionInfo(*session, apex_session_info);
438
439 return BinderStatus::ok();
440 }
441
getStagedApexInfos(const ApexSessionParams & params,std::vector<ApexInfo> * aidl_return)442 BinderStatus ApexService::getStagedApexInfos(
443 const ApexSessionParams& params, std::vector<ApexInfo>* aidl_return) {
444 LOG(INFO) << "getStagedApexInfos() received by ApexService, session id "
445 << params.sessionId << " child sessions: ["
446 << android::base::Join(params.childSessionIds, ',') << "]";
447
448 auto check = CheckCallerSystemOrRoot("getStagedApexInfos");
449 if (!check.isOk()) {
450 return check;
451 }
452
453 Result<std::vector<ApexFile>> files = ::android::apex::GetStagedApexFiles(
454 params.sessionId, params.childSessionIds);
455 if (!files.ok()) {
456 LOG(ERROR) << "Failed to getStagedApexInfo session id " << params.sessionId
457 << ": " << files.error();
458 return BinderStatus::fromExceptionCode(
459 BinderStatus::EX_SERVICE_SPECIFIC,
460 String8(files.error().message().c_str()));
461 }
462
463 // Retrieve classpath information
464 auto class_path = ::android::apex::MountAndDeriveClassPath(*files);
465 if (!class_path.ok()) {
466 LOG(ERROR) << "Failed to getStagedApexInfo session id " << params.sessionId
467 << ": " << class_path.error();
468 return BinderStatus::fromExceptionCode(
469 BinderStatus::EX_SERVICE_SPECIFIC,
470 String8(class_path.error().message().c_str()));
471 }
472
473 for (const auto& apex_file : *files) {
474 ApexInfo apex_info = GetApexInfo(apex_file);
475 auto package_name = apex_info.moduleName;
476 apex_info.hasClassPathJars = class_path->HasClassPathJars(package_name);
477 aidl_return->push_back(std::move(apex_info));
478 }
479
480 return BinderStatus::ok();
481 }
482
getActivePackages(std::vector<ApexInfo> * aidl_return)483 BinderStatus ApexService::getActivePackages(
484 std::vector<ApexInfo>* aidl_return) {
485 LOG(INFO) << "getActivePackages received by ApexService";
486
487 auto check = CheckCallerSystemOrRoot("getActivePackages");
488 if (!check.isOk()) {
489 return check;
490 }
491
492 auto packages = ::android::apex::GetActivePackages();
493 for (const auto& package : packages) {
494 ApexInfo apex_info = GetApexInfo(package);
495 apex_info.isActive = true;
496 aidl_return->push_back(std::move(apex_info));
497 }
498
499 return BinderStatus::ok();
500 }
501
getActivePackage(const std::string & package_name,ApexInfo * aidl_return)502 BinderStatus ApexService::getActivePackage(const std::string& package_name,
503 ApexInfo* aidl_return) {
504 LOG(INFO) << "getActivePackage received by ApexService package_name : "
505 << package_name;
506
507 auto check = CheckCallerSystemOrRoot("getActivePackage");
508 if (!check.isOk()) {
509 return check;
510 }
511
512 Result<ApexFile> apex = ::android::apex::GetActivePackage(package_name);
513 if (apex.ok()) {
514 *aidl_return = GetApexInfo(*apex);
515 aidl_return->isActive = true;
516 }
517 return BinderStatus::ok();
518 }
519
getAllPackages(std::vector<ApexInfo> * aidl_return)520 BinderStatus ApexService::getAllPackages(std::vector<ApexInfo>* aidl_return) {
521 LOG(INFO) << "getAllPackages received by ApexService";
522
523 auto check = CheckCallerSystemOrRoot("getAllPackages");
524 if (!check.isOk()) {
525 return check;
526 }
527
528 const auto& active = ::android::apex::GetActivePackages();
529 const auto& factory = ::android::apex::GetFactoryPackages();
530 for (const ApexFile& pkg : active) {
531 ApexInfo apex_info = GetApexInfo(pkg);
532 apex_info.isActive = true;
533 aidl_return->push_back(std::move(apex_info));
534 }
535 for (const ApexFile& pkg : factory) {
536 const auto& same_path = [&pkg](const auto& o) {
537 return o.GetPath() == pkg.GetPath();
538 };
539 if (std::find_if(active.begin(), active.end(), same_path) == active.end()) {
540 aidl_return->push_back(GetApexInfo(pkg));
541 }
542 }
543 return BinderStatus::ok();
544 }
545
installAndActivatePackage(const std::string & package_path,bool force,ApexInfo * aidl_return)546 BinderStatus ApexService::installAndActivatePackage(
547 const std::string& package_path, bool force, ApexInfo* aidl_return) {
548 LOG(INFO) << "installAndActivatePackage() received by ApexService, path: "
549 << package_path << " force : " << force;
550
551 auto check = CheckCallerSystemOrRoot("installAndActivatePackage");
552 if (!check.isOk()) {
553 return check;
554 }
555
556 if (force) {
557 auto debug_check = CheckDebuggable("Forced non-staged APEX update");
558 if (!debug_check.isOk()) {
559 return debug_check;
560 }
561 }
562
563 auto res = InstallPackage(package_path, force);
564 if (!res.ok()) {
565 LOG(ERROR) << "Failed to install package " << package_path << " : "
566 << res.error();
567 return BinderStatus::fromExceptionCode(
568 BinderStatus::EX_SERVICE_SPECIFIC,
569 String8(res.error().message().c_str()));
570 }
571 *aidl_return = GetApexInfo(*res);
572 aidl_return->isActive = true;
573 return BinderStatus::ok();
574 }
575
abortStagedSession(int session_id)576 BinderStatus ApexService::abortStagedSession(int session_id) {
577 LOG(INFO) << "abortStagedSession() received by ApexService session : "
578 << session_id;
579
580 auto check = CheckCallerSystemOrRoot("abortStagedSession");
581 if (!check.isOk()) {
582 return check;
583 }
584
585 Result<void> res = ::android::apex::AbortStagedSession(session_id);
586 if (!res.ok()) {
587 return BinderStatus::fromExceptionCode(
588 BinderStatus::EX_ILLEGAL_ARGUMENT,
589 String8(res.error().message().c_str()));
590 }
591 return BinderStatus::ok();
592 }
593
revertActiveSessions()594 BinderStatus ApexService::revertActiveSessions() {
595 LOG(INFO) << "revertActiveSessions() received by ApexService.";
596
597 auto check = CheckCallerSystemOrRoot("revertActiveSessions");
598 if (!check.isOk()) {
599 return check;
600 }
601
602 Result<void> res = ::android::apex::RevertActiveSessions("", "");
603 if (!res.ok()) {
604 return BinderStatus::fromExceptionCode(
605 BinderStatus::EX_ILLEGAL_ARGUMENT,
606 String8(res.error().message().c_str()));
607 }
608 return BinderStatus::ok();
609 }
610
resumeRevertIfNeeded()611 BinderStatus ApexService::resumeRevertIfNeeded() {
612 LOG(INFO) << "resumeRevertIfNeeded() received by ApexService.";
613
614 BinderStatus debug_check = CheckDebuggable("resumeRevertIfNeeded");
615 if (!debug_check.isOk()) {
616 return debug_check;
617 }
618
619 auto root_check = CheckCallerIsRoot("resumeRevertIfNeeded");
620 if (!root_check.isOk()) {
621 return root_check;
622 }
623
624 Result<void> res = ::android::apex::ResumeRevertIfNeeded();
625 if (!res.ok()) {
626 return BinderStatus::fromExceptionCode(
627 BinderStatus::EX_ILLEGAL_ARGUMENT,
628 String8(res.error().message().c_str()));
629 }
630 return BinderStatus::ok();
631 }
632
snapshotCeData(int user_id,int rollback_id,const std::string & apex_name)633 BinderStatus ApexService::snapshotCeData(int user_id, int rollback_id,
634 const std::string& apex_name) {
635 LOG(INFO) << "snapshotCeData() received by ApexService user_id : " << user_id
636 << " rollback_id : " << rollback_id << " apex_name : " << apex_name;
637
638 auto check = CheckCallerSystemOrRoot("snapshotCeData");
639 if (!check.isOk()) {
640 return check;
641 }
642
643 Result<void> res =
644 ::android::apex::SnapshotCeData(user_id, rollback_id, apex_name);
645 if (!res.ok()) {
646 return BinderStatus::fromExceptionCode(
647 BinderStatus::EX_SERVICE_SPECIFIC,
648 String8(res.error().message().c_str()));
649 }
650 return BinderStatus::ok();
651 }
652
restoreCeData(int user_id,int rollback_id,const std::string & apex_name)653 BinderStatus ApexService::restoreCeData(int user_id, int rollback_id,
654 const std::string& apex_name) {
655 LOG(INFO) << "restoreCeData() received by ApexService user_id : " << user_id
656 << " rollback_id : " << rollback_id << " apex_name : " << apex_name;
657
658 auto check = CheckCallerSystemOrRoot("restoreCeData");
659 if (!check.isOk()) {
660 return check;
661 }
662
663 Result<void> res =
664 ::android::apex::RestoreCeData(user_id, rollback_id, apex_name);
665 if (!res.ok()) {
666 return BinderStatus::fromExceptionCode(
667 BinderStatus::EX_SERVICE_SPECIFIC,
668 String8(res.error().message().c_str()));
669 }
670 return BinderStatus::ok();
671 }
672
destroyDeSnapshots(int rollback_id)673 BinderStatus ApexService::destroyDeSnapshots(int rollback_id) {
674 LOG(INFO) << "destroyDeSnapshots() received by ApexService rollback_id : "
675 << rollback_id;
676
677 auto check = CheckCallerSystemOrRoot("destroyDeSnapshots");
678 if (!check.isOk()) {
679 return check;
680 }
681
682 Result<void> res = ::android::apex::DestroyDeSnapshots(rollback_id);
683 if (!res.ok()) {
684 return BinderStatus::fromExceptionCode(
685 BinderStatus::EX_SERVICE_SPECIFIC,
686 String8(res.error().message().c_str()));
687 }
688 return BinderStatus::ok();
689 }
690
destroyCeSnapshots(int user_id,int rollback_id)691 BinderStatus ApexService::destroyCeSnapshots(int user_id, int rollback_id) {
692 LOG(INFO) << "destroyCeSnapshots() received by ApexService user_id : "
693 << user_id << " rollback_id : " << rollback_id;
694
695 auto check = CheckCallerSystemOrRoot("destroyCeSnapshots");
696 if (!check.isOk()) {
697 return check;
698 }
699
700 Result<void> res = ::android::apex::DestroyCeSnapshots(user_id, rollback_id);
701 if (!res.ok()) {
702 return BinderStatus::fromExceptionCode(
703 BinderStatus::EX_SERVICE_SPECIFIC,
704 String8(res.error().message().c_str()));
705 }
706 return BinderStatus::ok();
707 }
708
destroyCeSnapshotsNotSpecified(int user_id,const std::vector<int> & retain_rollback_ids)709 BinderStatus ApexService::destroyCeSnapshotsNotSpecified(
710 int user_id, const std::vector<int>& retain_rollback_ids) {
711 LOG(INFO)
712 << "destroyCeSnapshotsNotSpecified() received by ApexService user_id : "
713 << user_id << " retain_rollback_ids : [" << Join(retain_rollback_ids, ',')
714 << "]";
715
716 auto check = CheckCallerSystemOrRoot("destroyCeSnapshotsNotSpecified");
717 if (!check.isOk()) {
718 return check;
719 }
720
721 Result<void> res = ::android::apex::DestroyCeSnapshotsNotSpecified(
722 user_id, retain_rollback_ids);
723 if (!res.ok()) {
724 return BinderStatus::fromExceptionCode(
725 BinderStatus::EX_SERVICE_SPECIFIC,
726 String8(res.error().message().c_str()));
727 }
728 return BinderStatus::ok();
729 }
730
recollectPreinstalledData()731 BinderStatus ApexService::recollectPreinstalledData() {
732 LOG(INFO) << "recollectPreinstalledData() received by ApexService";
733
734 if (auto debug = CheckDebuggable("recollectPreinstalledData");
735 !debug.isOk()) {
736 return debug;
737 }
738 if (auto root = CheckCallerIsRoot("recollectPreinstalledData");
739 !root.isOk()) {
740 return root;
741 }
742
743 ApexFileRepository& instance = ApexFileRepository::GetInstance();
744 if (auto res = instance.AddPreInstalledApex(kBuiltinApexPackageDirs);
745 !res.ok()) {
746 return BinderStatus::fromExceptionCode(
747 BinderStatus::EX_SERVICE_SPECIFIC,
748 String8(res.error().message().c_str()));
749 }
750 return BinderStatus::ok();
751 }
752
onTransact(uint32_t _aidl_code,const Parcel & _aidl_data,Parcel * _aidl_reply,uint32_t _aidl_flags)753 status_t ApexService::onTransact(uint32_t _aidl_code, const Parcel& _aidl_data,
754 Parcel* _aidl_reply, uint32_t _aidl_flags) {
755 switch (_aidl_code) {
756 case IBinder::SHELL_COMMAND_TRANSACTION: {
757 int in = _aidl_data.readFileDescriptor();
758 int out = _aidl_data.readFileDescriptor();
759 int err = _aidl_data.readFileDescriptor();
760 int argc = _aidl_data.readInt32();
761 Vector<String16> args;
762 for (int i = 0; i < argc && _aidl_data.dataAvail() > 0; i++) {
763 args.add(_aidl_data.readString16());
764 }
765 sp<IBinder> unused_callback;
766 sp<IResultReceiver> result_receiver;
767 status_t status;
768 if ((status = _aidl_data.readNullableStrongBinder(&unused_callback)) !=
769 OK)
770 return status;
771 if ((status = _aidl_data.readNullableStrongBinder(&result_receiver)) !=
772 OK)
773 return status;
774 status = shellCommand(in, out, err, args);
775 if (result_receiver != nullptr) {
776 result_receiver->send(status);
777 }
778 return OK;
779 }
780 }
781 return BnApexService::onTransact(_aidl_code, _aidl_data, _aidl_reply,
782 _aidl_flags);
783 }
dump(int fd,const Vector<String16> &)784 status_t ApexService::dump(int fd, const Vector<String16>& /*args*/) {
785 std::vector<ApexInfo> list;
786 BinderStatus status = getActivePackages(&list);
787 dprintf(fd, "ACTIVE PACKAGES:\n");
788 if (!status.isOk()) {
789 std::string msg = StringLog() << "Failed to retrieve packages: "
790 << status.toString8().c_str() << std::endl;
791 dprintf(fd, "%s", msg.c_str());
792 return BAD_VALUE;
793 } else {
794 for (const auto& item : list) {
795 std::string msg = ToString(item);
796 dprintf(fd, "%s", msg.c_str());
797 }
798 }
799
800 dprintf(fd, "SESSIONS:\n");
801 std::vector<ApexSession> sessions = GetSessionManager()->GetSessions();
802
803 for (const auto& session : sessions) {
804 std::string child_ids_str = "";
805 auto child_ids = session.GetChildSessionIds();
806 if (child_ids.size() > 0) {
807 child_ids_str = "Child IDs:";
808 for (auto childSessionId : session.GetChildSessionIds()) {
809 child_ids_str += " " + std::to_string(childSessionId);
810 }
811 }
812 std::string revert_reason = "";
813 const auto& crashing_native_process = session.GetCrashingNativeProcess();
814 if (!crashing_native_process.empty()) {
815 revert_reason = " Revert Reason: " + crashing_native_process;
816 }
817 std::string error_message_dump = "";
818 const auto& error_message = session.GetErrorMessage();
819 if (!error_message.empty()) {
820 error_message_dump = " Error Message: " + error_message;
821 }
822 std::string msg =
823 StringLog() << "Session ID: " << session.GetId() << child_ids_str
824 << " State: " << SessionState_State_Name(session.GetState())
825 << revert_reason << error_message_dump << std::endl;
826 dprintf(fd, "%s", msg.c_str());
827 }
828
829 return OK;
830 }
831
shellCommand(int in,int out,int err,const Vector<String16> & args)832 status_t ApexService::shellCommand(int in, int out, int err,
833 const Vector<String16>& args) {
834 if (in == BAD_TYPE || out == BAD_TYPE || err == BAD_TYPE) {
835 return BAD_VALUE;
836 }
837 auto print_help = [](int fd, const char* prefix = nullptr) {
838 StringLog log;
839 if (prefix != nullptr) {
840 log << prefix << std::endl;
841 }
842 log << "ApexService:" << std::endl
843 << " help - display this help" << std::endl
844 << " getActivePackage [package_name] - return info for active package "
845 "with given name, if present"
846 << std::endl
847 << " getAllPackages - return the list of all packages" << std::endl
848 << " getActivePackages - return the list of active packages"
849 << std::endl
850 << " getStagedSessionInfo [sessionId] - displays information about a "
851 "given session previously submitted"
852 << std::endl;
853 dprintf(fd, "%s", log.operator std::string().c_str());
854 };
855
856 if (args.size() == 0) {
857 print_help(err, "No command given");
858 return BAD_VALUE;
859 }
860
861 const String16& cmd = args[0];
862
863 if (cmd == String16("getAllPackages")) {
864 if (args.size() != 1) {
865 print_help(err, "Unrecognized options");
866 return BAD_VALUE;
867 }
868 std::vector<ApexInfo> list;
869 BinderStatus status = getAllPackages(&list);
870 if (status.isOk()) {
871 for (const auto& item : list) {
872 std::string msg = ToString(item);
873 dprintf(out, "%s", msg.c_str());
874 }
875 return OK;
876 }
877 std::string msg = StringLog() << "Failed to retrieve packages: "
878 << status.toString8().c_str() << std::endl;
879 dprintf(err, "%s", msg.c_str());
880 return BAD_VALUE;
881 }
882
883 if (cmd == String16("getActivePackages")) {
884 if (args.size() != 1) {
885 print_help(err, "Unrecognized options");
886 return BAD_VALUE;
887 }
888 std::vector<ApexInfo> list;
889 BinderStatus status = getActivePackages(&list);
890 if (status.isOk()) {
891 for (const auto& item : list) {
892 std::string msg = ToString(item);
893 dprintf(out, "%s", msg.c_str());
894 }
895 return OK;
896 }
897 std::string msg = StringLog() << "Failed to retrieve packages: "
898 << status.toString8().c_str() << std::endl;
899 dprintf(err, "%s", msg.c_str());
900 return BAD_VALUE;
901 }
902
903 if (cmd == String16("getActivePackage")) {
904 if (args.size() != 2) {
905 print_help(err, "Unrecognized options");
906 return BAD_VALUE;
907 }
908
909 ApexInfo package;
910 BinderStatus status = getActivePackage(String8(args[1]).c_str(), &package);
911 if (status.isOk()) {
912 std::string msg = ToString(package);
913 dprintf(out, "%s", msg.c_str());
914 return OK;
915 }
916
917 std::string msg = StringLog()
918 << "Failed to fetch active package: "
919 << String8(args[1]).c_str()
920 << ", error: " << status.toString8().c_str() << std::endl;
921 dprintf(err, "%s", msg.c_str());
922 return BAD_VALUE;
923 }
924
925 if (cmd == String16("getStagedSessionInfo")) {
926 if (args.size() != 2) {
927 print_help(err, "getStagedSessionInfo requires one session id");
928 return BAD_VALUE;
929 }
930 int session_id = strtol(String8(args[1]).c_str(), nullptr, 10);
931 if (session_id < 0) {
932 std::string msg = StringLog()
933 << "Failed to parse session id. Must be an integer.";
934 dprintf(err, "%s", msg.c_str());
935 return BAD_VALUE;
936 }
937
938 ApexSessionInfo session_info;
939 BinderStatus status = getStagedSessionInfo(session_id, &session_info);
940 if (status.isOk()) {
941 std::string revert_reason = "";
942 std::string crashing_native_process = session_info.crashingNativeProcess;
943 if (!crashing_native_process.empty()) {
944 revert_reason = " revertReason: " + crashing_native_process;
945 }
946 std::string msg = StringLog()
947 << "session_info: "
948 << " isUnknown: " << session_info.isUnknown
949 << " isVerified: " << session_info.isVerified
950 << " isStaged: " << session_info.isStaged
951 << " isActivated: " << session_info.isActivated
952 << " isActivationFailed: "
953 << session_info.isActivationFailed << revert_reason
954 << std::endl;
955 dprintf(out, "%s", msg.c_str());
956 return OK;
957 }
958 std::string msg = StringLog() << "Failed to query session: "
959 << status.toString8().c_str() << std::endl;
960 dprintf(err, "%s", msg.c_str());
961 return BAD_VALUE;
962 }
963
964 if (cmd == String16("help")) {
965 if (args.size() != 1) {
966 print_help(err, "Help has no options");
967 return BAD_VALUE;
968 }
969 print_help(out);
970 return OK;
971 }
972
973 print_help(err);
974 return BAD_VALUE;
975 }
976
977 } // namespace
978
979 static constexpr const char* kApexServiceName = "apexservice";
980
981 using android::IPCThreadState;
982 using android::ProcessState;
983 using android::sp;
984 using android::binder::LazyServiceRegistrar;
985
CreateAndRegisterService()986 void CreateAndRegisterService() {
987 sp<ProcessState> ps(ProcessState::self());
988
989 // Create binder service and register with LazyServiceRegistrar
990 sp<ApexService> apex_service = sp<ApexService>::make();
991 auto lazy_registrar = LazyServiceRegistrar::getInstance();
992 lazy_registrar.forcePersist(true);
993 lazy_registrar.registerService(apex_service, kApexServiceName);
994 }
995
AllowServiceShutdown()996 void AllowServiceShutdown() {
997 auto lazy_registrar = LazyServiceRegistrar::getInstance();
998 lazy_registrar.forcePersist(false);
999 }
1000
StartThreadPool()1001 void StartThreadPool() {
1002 sp<ProcessState> ps(ProcessState::self());
1003
1004 // Start threadpool, wait for IPC
1005 ps->startThreadPool();
1006 }
1007
JoinThreadPool()1008 void JoinThreadPool() {
1009 IPCThreadState::self()->joinThreadPool(); // should not return
1010 }
1011
1012 } // namespace binder
1013 } // namespace apex
1014 } // namespace android
1015