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