1 /*
2  * Copyright (C) 2024 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 "aidl_service.h"
18 
19 #include <cassert>
20 #include <cstddef>
21 #include <cstdint>
22 #include <cstdlib>
23 #include <cstring>
24 #include <limits>
25 #include <memory>
26 #include <vector>
27 
28 #include <trusty_ipc.h>
29 
30 #include <interface/storage/storage_aidl/ports.h>
31 
32 #include <binder/RpcServerTrusty.h>
33 #include <binder/Status.h>
34 #include <utils/Errors.h>
35 
36 #include <android/hardware/security/see/storage/Availability.h>
37 #include <android/hardware/security/see/storage/BnDir.h>
38 #include <android/hardware/security/see/storage/BnFile.h>
39 #include <android/hardware/security/see/storage/BnSecureStorage.h>
40 #include <android/hardware/security/see/storage/BnStorageSession.h>
41 #include <android/hardware/security/see/storage/CreationMode.h>
42 #include <android/hardware/security/see/storage/FileMode.h>
43 #include <android/hardware/security/see/storage/Filesystem.h>
44 #include <android/hardware/security/see/storage/IDir.h>
45 #include <android/hardware/security/see/storage/IFile.h>
46 #include <android/hardware/security/see/storage/ISecureStorage.h>
47 #include <android/hardware/security/see/storage/IStorageSession.h>
48 #include <android/hardware/security/see/storage/Integrity.h>
49 #include <android/hardware/security/see/storage/OpenOptions.h>
50 
51 #include "block_device_tipc.h"
52 #include "client.h"
53 #include "client_session.h"
54 #include "file.h"
55 #include "storage_limits.h"
56 
57 using ::android::RpcServerTrusty;
58 using ::android::RpcSession;
59 using ::android::sp;
60 using ::android::wp;
61 using ::android::binder::Status;
62 using ::android::hardware::security::see::storage::Availability;
63 using ::android::hardware::security::see::storage::BnDir;
64 using ::android::hardware::security::see::storage::BnFile;
65 using ::android::hardware::security::see::storage::BnSecureStorage;
66 using ::android::hardware::security::see::storage::BnStorageSession;
67 using ::android::hardware::security::see::storage::CreationMode;
68 using ::android::hardware::security::see::storage::FileMode;
69 using ::android::hardware::security::see::storage::Filesystem;
70 using ::android::hardware::security::see::storage::IDir;
71 using ::android::hardware::security::see::storage::IFile;
72 using ::android::hardware::security::see::storage::Integrity;
73 using ::android::hardware::security::see::storage::ISecureStorage;
74 using ::android::hardware::security::see::storage::IStorageSession;
75 using ::android::hardware::security::see::storage::OpenOptions;
76 
77 #define SS_ERR(args...) fprintf(stderr, "ss-aidl: " args)
78 
79 namespace storage_service {
80 namespace {
81 
82 constexpr uint32_t kAclFlags =
83 #if TEST_BUILD
84         IPC_PORT_ALLOW_TA_CONNECT | IPC_PORT_ALLOW_NS_CONNECT;
85 #else
86         IPC_PORT_ALLOW_TA_CONNECT;
87 #endif
88 
89 constexpr size_t kMaxBufferSize = STORAGE_MAX_BUFFER_SIZE;
90 
status_from_storage_err(storage_err err)91 static Status status_from_storage_err(storage_err err) {
92     switch (err) {
93     case storage_err::STORAGE_NO_ERROR:
94         return Status::ok();
95     case storage_err::STORAGE_ERR_GENERIC:
96         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
97     case storage_err::STORAGE_ERR_NOT_VALID:
98         return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
99     case storage_err::STORAGE_ERR_UNIMPLEMENTED:
100         return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION);
101     case storage_err::STORAGE_ERR_ACCESS:
102         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
103     case storage_err::STORAGE_ERR_NOT_FOUND:
104         return Status::fromServiceSpecificError(ISecureStorage::ERR_NOT_FOUND);
105     case storage_err::STORAGE_ERR_EXIST:
106         return Status::fromServiceSpecificError(
107                 ISecureStorage::ERR_ALREADY_EXISTS);
108     case storage_err::STORAGE_ERR_TRANSACT:
109         return Status::fromServiceSpecificError(
110                 ISecureStorage::ERR_BAD_TRANSACTION);
111     case storage_err::STORAGE_ERR_NOT_ALLOWED:
112         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
113     case storage_err::STORAGE_ERR_CORRUPTED:
114         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
115     case storage_err::STORAGE_ERR_FS_REPAIRED:
116         // TODO: Distinguish rolled back vs reset; catch other tampering
117         return Status::fromServiceSpecificError(
118                 ISecureStorage::ERR_FS_TAMPERED);
119     default:
120         return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
121                                          "Unknown error code.");
122     }
123 }
124 
create_mode(CreationMode mode)125 static file_create_mode create_mode(CreationMode mode) {
126     switch (mode) {
127     case CreationMode::CREATE_EXCLUSIVE:
128         return file_create_mode::FILE_OPEN_CREATE_EXCLUSIVE;
129     case CreationMode::CREATE:
130         return file_create_mode::FILE_OPEN_CREATE;
131     case CreationMode::NO_CREATE:
132         return file_create_mode::FILE_OPEN_NO_CREATE;
133     }
134 }
135 
get_fs(const Filesystem & filesystem,storage_filesystem_type * out)136 static Status get_fs(const Filesystem& filesystem,
137                      storage_filesystem_type* out) {
138     switch (filesystem.integrity) {
139     case Integrity::TAMPER_PROOF_AT_REST: {
140         // TP is persistent and available before userdata
141         *out = STORAGE_TP;
142         break;
143     }
144     case Integrity::TAMPER_DETECT: {
145         switch (filesystem.availability) {
146         case Availability::BEFORE_USERDATA: {
147             if (filesystem.persistent) {
148                 return Status::fromExceptionCode(
149                         Status::EX_UNSUPPORTED_OPERATION,
150                         "Unsupported Filesystem properties: TDEA does not guarantee persistence");
151             }
152             *out = STORAGE_TDEA;
153             break;
154         }
155         case Availability::AFTER_USERDATA: {
156             *out = filesystem.persistent ? STORAGE_TDP : STORAGE_TD;
157             break;
158         }
159         default:
160             return Status::fromExceptionCode(
161                     Status::EX_UNSUPPORTED_OPERATION,
162                     "Unsupported Filesystem properties: Unknown Availability value");
163         }
164         break;
165     }
166     default:
167         return Status::fromExceptionCode(
168                 Status::EX_UNSUPPORTED_OPERATION,
169                 "Unsupported Filesystem properties: Unknown Integrity value");
170     }
171     return Status::ok();
172 }
173 
174 class StorageClientSession {
175 public:
StorageClientSession(struct fs * fs,bool * fs_active,const uuid_t * peer)176     StorageClientSession(struct fs* fs, bool* fs_active, const uuid_t* peer)
177             : inner_(), active_(fs_active) {
178         storage_client_session_init(&inner_, fs, peer);
179     }
~StorageClientSession()180     ~StorageClientSession() { storage_client_session_destroy(&inner_); }
181 
get()182     storage_client_session* get() { return *active_ ? &inner_ : nullptr; }
183 
184 private:
185     storage_client_session inner_;
186     bool* active_;
187 };
188 
189 class Dir : public BnDir {
190 public:
Dir(std::weak_ptr<StorageClientSession> session)191     Dir(std::weak_ptr<StorageClientSession> session)
192             : session_(std::move(session)),
193               last_state_(storage_file_list_flag::STORAGE_FILE_LIST_START),
194               last_name_() {}
195 
readNextFilenames(int32_t max_count,std::vector<std::string> * out)196     Status readNextFilenames(int32_t max_count,
197                              std::vector<std::string>* out) final {
198         constexpr size_t kMaxFilenames = STORAGE_MAX_BUFFER_SIZE / FS_PATH_MAX;
199 
200         if (max_count < 0) {
201             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
202                                              "maxCount must not be negative.");
203         }
204         size_t max_names = (max_count == 0)
205                                    ? kMaxFilenames
206                                    : std::min(kMaxFilenames,
207                                               static_cast<size_t>(max_count));
208 
209         std::shared_ptr<StorageClientSession> session = session_.lock();
210         if (session == nullptr) {
211             return Status::fromExceptionCode(
212                     Status::EX_ILLEGAL_STATE,
213                     "IDir cannot be used after its parent session has been destroyed.");
214         }
215         storage_client_session* client_session = session->get();
216         if (client_session == nullptr) {
217             return Status::fromStatusT(android::WOULD_BLOCK);
218         }
219 
220         if (last_state_ == storage_file_list_flag::STORAGE_FILE_LIST_END) {
221             return Status::ok();
222         }
223 
224         ListCallbackData data = {
225                 .out = out,
226                 .curr_flags = last_state_,
227         };
228 
229         storage_err result = storage_file_list(
230                 client_session, max_names, last_state_, last_name_.data(),
231                 last_name_.size(), op_flags(),
232                 [](void* callback_data, size_t max_path_len) { return true; },
233                 [](void* callback_data, enum storage_file_list_flag flags,
234                    const char* path, size_t path_len) {
235                     auto& data = *static_cast<ListCallbackData*>(callback_data);
236 
237                     data.curr_flags = flags;
238                     if (flags ==
239                         storage_file_list_flag::STORAGE_FILE_LIST_END) {
240                         return;
241                     }
242 
243                     data.out->emplace_back(path, path_len);
244 
245                     // TODO: Do we need to tell the caller whether the file is
246                     // committed, added, removed?
247                 },
248                 &data);
249 
250         last_state_ = data.curr_flags;
251         last_name_ = out->empty() ? "" : out->back();
252 
253         return status_from_storage_err(result);
254     }
255 
256 private:
257     struct ListCallbackData {
258         std::vector<std::string>* out;
259         enum storage_file_list_flag curr_flags;
260     };
261 
op_flags()262     storage_op_flags op_flags() {
263         return storage_op_flags{
264                 .allow_repaired = false,
265                 .complete_transaction = false,
266                 .update_checkpoint = false,
267         };
268     }
269 
270     std::weak_ptr<StorageClientSession> session_;
271 
272     enum storage_file_list_flag last_state_;
273     std::string last_name_;
274 };
275 
276 class File : public BnFile {
277 public:
File(std::weak_ptr<StorageClientSession> session,uint32_t file_handle,FileMode access_mode)278     File(std::weak_ptr<StorageClientSession> session,
279          uint32_t file_handle,
280          FileMode access_mode)
281             : session_(std::move(session)),
282               file_handle_(file_handle),
283               access_mode_(access_mode) {}
284 
~File()285     ~File() {
286         std::shared_ptr<StorageClientSession> session = session_.lock();
287         if (session == nullptr) {
288             return;
289         }
290         storage_client_session* client_session = session->get();
291         if (client_session == nullptr) {
292             return;
293         }
294 
295         (void)storage_file_close(client_session, file_handle_, op_flags());
296     }
297 
read(int64_t size,int64_t offset,std::vector<uint8_t> * out)298     Status read(int64_t size, int64_t offset, std::vector<uint8_t>* out) final {
299         if (access_mode_ != FileMode::READ_ONLY &&
300             access_mode_ != FileMode::READ_WRITE) {
301             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
302                                              "File not opened for reading.");
303         }
304         if (size < 0) {
305             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
306                                              "Size must not be negative.");
307         }
308         if (size > std::numeric_limits<uint32_t>::max()) {
309             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
310                                              "Size would overflow");
311         }
312         if (offset < 0) {
313             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
314                                              "Offset must not be negative.");
315         }
316         std::shared_ptr<StorageClientSession> session = session_.lock();
317         if (session == nullptr) {
318             return Status::fromExceptionCode(
319                     Status::EX_ILLEGAL_STATE,
320                     "IFile cannot be used after its parent session has been destroyed.");
321         }
322         storage_client_session* client_session = session->get();
323         if (client_session == nullptr) {
324             return Status::fromStatusT(android::WOULD_BLOCK);
325         }
326 
327         out->resize(
328                 std::min(size, static_cast<int64_t>(STORAGE_MAX_BUFFER_SIZE)));
329         size_t out_len = out->size();
330 
331         storage_err result =
332                 storage_file_read(client_session, file_handle_, size, offset,
333                                   op_flags(), out->data(), &out_len);
334 
335         out->resize(out_len);
336         return status_from_storage_err(result);
337     }
338 
write(int64_t offset,const std::vector<uint8_t> & buffer,int64_t * out)339     Status write(int64_t offset,
340                  const std::vector<uint8_t>& buffer,
341                  int64_t* out) final {
342         if (access_mode_ != FileMode::WRITE_ONLY &&
343             access_mode_ != FileMode::READ_WRITE) {
344             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
345                                              "File not opened for writing.");
346         }
347         if (offset < 0) {
348             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
349                                              "Offset must not be negative.");
350         }
351         std::shared_ptr<StorageClientSession> session = session_.lock();
352         if (session == nullptr) {
353             return Status::fromExceptionCode(
354                     Status::EX_ILLEGAL_STATE,
355                     "IFile cannot be used after its parent session has been destroyed.");
356         }
357         storage_client_session* client_session = session->get();
358         if (client_session == nullptr) {
359             return Status::fromStatusT(android::WOULD_BLOCK);
360         }
361 
362         storage_err result =
363                 storage_file_write(session->get(), file_handle_, offset,
364                                    buffer.data(), buffer.size(), op_flags());
365         if (result != storage_err::STORAGE_NO_ERROR) {
366             return status_from_storage_err(result);
367         }
368 
369         *out = buffer.size();
370         return Status::ok();
371     }
372 
getSize(int64_t * out)373     Status getSize(int64_t* out) final {
374         std::shared_ptr<StorageClientSession> session = session_.lock();
375         if (session == nullptr) {
376             return Status::fromExceptionCode(
377                     Status::EX_ILLEGAL_STATE,
378                     "IFile cannot be used after its parent session has been destroyed.");
379         }
380         storage_client_session* client_session = session->get();
381         if (client_session == nullptr) {
382             return Status::fromStatusT(android::WOULD_BLOCK);
383         }
384 
385         uint64_t size;
386         storage_err result = storage_file_get_size(session->get(), file_handle_,
387                                                    op_flags(), &size);
388         if (result != storage_err::STORAGE_NO_ERROR) {
389             return status_from_storage_err(result);
390         }
391 
392         if (size > std::numeric_limits<int64_t>::max()) {
393             return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE,
394                                              "Size would overflow");
395         }
396         *out = static_cast<int64_t>(size);
397         return Status::ok();
398     }
399 
setSize(int64_t new_size)400     Status setSize(int64_t new_size) final {
401         if (access_mode_ != FileMode::WRITE_ONLY &&
402             access_mode_ != FileMode::READ_WRITE) {
403             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
404                                              "File not opened for writing.");
405         }
406         std::shared_ptr<StorageClientSession> session = session_.lock();
407         if (session == nullptr) {
408             return Status::fromExceptionCode(
409                     Status::EX_ILLEGAL_STATE,
410                     "IFile cannot be used after its parent session has been destroyed.");
411         }
412         storage_client_session* client_session = session->get();
413         if (client_session == nullptr) {
414             return Status::fromStatusT(android::WOULD_BLOCK);
415         }
416 
417         storage_err result = storage_file_set_size(session->get(), file_handle_,
418                                                    new_size, op_flags());
419         return status_from_storage_err(result);
420     }
421 
rename(const std::string & new_name,CreationMode dest_create_mode)422     Status rename(const std::string& new_name, CreationMode dest_create_mode) {
423         if (access_mode_ != FileMode::WRITE_ONLY &&
424             access_mode_ != FileMode::READ_WRITE) {
425             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
426                                              "File not opened for writing.");
427         }
428         std::shared_ptr<StorageClientSession> session = session_.lock();
429         if (session == nullptr) {
430             return Status::fromExceptionCode(
431                     Status::EX_ILLEGAL_STATE,
432                     "IFile cannot be used after its parent session has been destroyed.");
433         }
434         storage_client_session* client_session = session->get();
435         if (client_session == nullptr) {
436             return Status::fromStatusT(android::WOULD_BLOCK);
437         }
438 
439         storage_err result = storage_file_move(
440                 session->get(), file_handle_, true, nullptr, 0, new_name.data(),
441                 new_name.size(), create_mode(dest_create_mode), op_flags());
442         return status_from_storage_err(result);
443     }
444 
445 private:
op_flags()446     storage_op_flags op_flags() {
447         return storage_op_flags{
448                 .allow_repaired = false,
449                 .complete_transaction = false,
450                 .update_checkpoint = false,
451         };
452     }
453 
454     std::weak_ptr<StorageClientSession> session_;
455     uint32_t file_handle_;
456     FileMode access_mode_;
457 };
458 
459 class StorageSession : public BnStorageSession {
460 public:
StorageSession(std::shared_ptr<StorageClientSession> session)461     StorageSession(std::shared_ptr<StorageClientSession> session)
462             : session_(std::move(session)) {}
463 
stageChangesForCommitOnAbUpdateComplete()464     Status stageChangesForCommitOnAbUpdateComplete() final {
465         return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION);
466     }
467 
commitChanges()468     Status commitChanges() final { return endTransactions(true); }
abandonChanges()469     Status abandonChanges() final { return endTransactions(false); }
470 
openFile(const std::string & file_name,const OpenOptions & options,sp<IFile> * out)471     Status openFile(const std::string& file_name,
472                     const OpenOptions& options,
473                     sp<IFile>* out) final {
474         storage_client_session* client_session = session_->get();
475         if (client_session == nullptr) {
476             return Status::fromStatusT(android::WOULD_BLOCK);
477         }
478 
479         uint32_t file_handle;
480         storage_err err = storage_file_open(
481                 client_session, file_name.data(), file_name.size(),
482                 create_mode(options.createMode), options.truncateOnOpen,
483                 storage_op_flags{
484                         .allow_repaired = false,
485                         .complete_transaction = false,
486                         .update_checkpoint = false,
487                 },
488                 &file_handle);
489         if (err != storage_err::STORAGE_NO_ERROR) {
490             return status_from_storage_err(err);
491         }
492 
493         *out = sp<File>::make(session_, file_handle, options.accessMode);
494         return Status::ok();
495     }
496 
deleteFile(const std::string & file_name)497     Status deleteFile(const std::string& file_name) final {
498         storage_client_session* client_session = session_->get();
499         if (client_session == nullptr) {
500             return Status::fromStatusT(android::WOULD_BLOCK);
501         }
502 
503         storage_err err = storage_file_delete(
504                 client_session, file_name.data(), file_name.size(),
505                 storage_op_flags{
506                         .allow_repaired = false,
507                         .complete_transaction = false,
508                         .update_checkpoint = false,
509                 });
510         return status_from_storage_err(err);
511     }
512 
renameFile(const std::string & file_name,const std::string & new_name,CreationMode dest_create_mode)513     Status renameFile(const std::string& file_name,
514                       const std::string& new_name,
515                       CreationMode dest_create_mode) final {
516         storage_client_session* client_session = session_->get();
517         if (client_session == nullptr) {
518             return Status::fromStatusT(android::WOULD_BLOCK);
519         }
520 
521         storage_err err = storage_file_move(
522                 client_session, 0, false, file_name.data(), file_name.size(),
523                 new_name.data(), new_name.size(), create_mode(dest_create_mode),
524                 storage_op_flags{
525                         .allow_repaired = false,
526                         .complete_transaction = false,
527                         .update_checkpoint = false,
528                 });
529         return status_from_storage_err(err);
530     }
531 
openDir(const std::string & file_name,sp<IDir> * out)532     Status openDir(const std::string& file_name, sp<IDir>* out) final {
533         if (!file_name.empty()) {
534             return Status::fromExceptionCode(
535                     Status::EX_ILLEGAL_ARGUMENT,
536                     "Service currently only supports opening the root dir.");
537         }
538         if (session_->get() == nullptr) {
539             return Status::fromStatusT(android::WOULD_BLOCK);
540         }
541 
542         // TODO: Catch tampering?
543         *out = sp<Dir>::make(session_);
544         return Status::ok();
545     }
546 
547 private:
endTransactions(bool commit_changes)548     Status endTransactions(bool commit_changes) {
549         storage_op_flags flags = {
550                 .allow_repaired = false,
551                 .complete_transaction = commit_changes,
552                 // TODO: Allow updating checkpoint
553                 .update_checkpoint = false,
554         };
555 
556         storage_client_session* client_session = session_->get();
557         if (client_session == nullptr) {
558             return Status::fromStatusT(android::WOULD_BLOCK);
559         }
560         storage_err result = storage_transaction_end(client_session, flags);
561         return status_from_storage_err(result);
562     }
563 
564     std::shared_ptr<StorageClientSession> session_;
565 };
566 
567 class StorageService {
568 public:
MakeSession(const Filesystem & filesystem,const uuid_t * peer,std::shared_ptr<StorageClientSession> * out)569     Status MakeSession(const Filesystem& filesystem,
570                        const uuid_t* peer,
571                        std::shared_ptr<StorageClientSession>* out) {
572         storage_filesystem_type fs_type;
573         Status result = get_fs(filesystem, &fs_type);
574         if (!result.isOk()) {
575             return result;
576         }
577 
578         if (!filesystems_active_[fs_type]) {
579             return Status::fromStatusT(android::WOULD_BLOCK);
580         }
581 
582         *out = std::make_shared<StorageClientSession>(
583                 filesystems_[fs_type], &filesystems_active_[fs_type], peer);
584         return Status::ok();
585     }
586 
DeactivateFilesystem(storage_filesystem_type fs_type)587     void DeactivateFilesystem(storage_filesystem_type fs_type) {
588         if (!filesystems_active_[fs_type]) {
589             // The filesystem might be still be inactive because it wasn't
590             // connected when storage_aidl_enable was called, like NS-backed
591             // filesystems would be before NS is available.
592             return;
593         }
594 
595         filesystems_active_[fs_type] = false;
596     }
597 
TryActivateFilesystem(struct block_device_tipc * block_devices,storage_filesystem_type fs_type)598     void TryActivateFilesystem(struct block_device_tipc* block_devices,
599                                storage_filesystem_type fs_type) {
600         assert(!filesystems_active_[fs_type]);
601 
602         if (!block_device_tipc_fs_connected(block_devices, fs_type)) {
603             return;
604         }
605 
606         if (filesystems_[fs_type] == nullptr) {
607             filesystems_[fs_type] =
608                     block_device_tipc_get_fs(block_devices, fs_type);
609         } else {
610             assert(filesystems_[fs_type] ==
611                    block_device_tipc_get_fs(block_devices, fs_type));
612         }
613         filesystems_active_[fs_type] = true;
614     }
615 
616 private:
617     std::array<struct fs*, STORAGE_FILESYSTEMS_COUNT> filesystems_;
618     std::array<bool, STORAGE_FILESYSTEMS_COUNT> filesystems_active_;
619 };
620 
621 class SecureStorage : public BnSecureStorage {
622 public:
SecureStorage(StorageService * service,uuid_t peer)623     SecureStorage(StorageService* service, uuid_t peer)
624             : service_(service), peer_(peer) {}
625 
startSession(const Filesystem & filesystem,sp<IStorageSession> * out)626     Status startSession(const Filesystem& filesystem,
627                         sp<IStorageSession>* out) final {
628         std::shared_ptr<StorageClientSession> session;
629         Status result = service_->MakeSession(filesystem, &peer_, &session);
630         if (!result.isOk()) {
631             return result;
632         }
633 
634         *out = sp<StorageSession>::make(std::move(session));
635         return Status::ok();
636     }
637 
638 private:
639     StorageService* service_;
640     uuid_t peer_;
641 };
642 
643 }  // namespace
644 }  // namespace storage_service
645 
646 struct storage_service_aidl_context_inner {
647     sp<RpcServerTrusty> aidl_srv;
648     storage_service::StorageService service;
649 };
650 
storage_aidl_create_service(struct storage_service_aidl_context * ctx,struct tipc_hset * hset)651 int storage_aidl_create_service(struct storage_service_aidl_context* ctx,
652                                 struct tipc_hset* hset) {
653     auto result = std::make_unique<storage_service_aidl_context_inner>();
654     auto& service = result->service;
655 
656     auto port_acl =
657             RpcServerTrusty::PortAcl{.flags = storage_service::kAclFlags};
658     auto aidl_srv = RpcServerTrusty::make(
659             hset, STORAGE_ISECURE_STORAGE_PORT,
660             std::make_shared<const RpcServerTrusty::PortAcl>(port_acl),
661             storage_service::kMaxBufferSize);
662     if (aidl_srv == nullptr) {
663         return EXIT_FAILURE;
664     }
665 
666     aidl_srv->setPerSessionRootObject([&service](wp<RpcSession> session,
667                                                  const void* peer,
668                                                  size_t peer_size)
669                                               -> sp<storage_service::
670                                                             SecureStorage> {
671         if (peer_size != sizeof(uuid_t)) {
672             SS_ERR("Creating binder root object, but peer id had unexpected size %zu (expected %zu)",
673                    peer_size, sizeof(uuid_t));
674             return nullptr;
675         }
676         uuid_t peer_uuid = *static_cast<const uuid_t*>(peer);
677 
678         return sp<storage_service::SecureStorage>::make(&service,
679                                                         std::move(peer_uuid));
680     });
681     result->aidl_srv = std::move(aidl_srv);
682 
683     // Caller now owns underlying storage_service_aidl_context
684     ctx->inner = result.release();
685     return EXIT_SUCCESS;
686 }
687 
storage_aidl_destroy_service(struct storage_service_aidl_context * ctx)688 void storage_aidl_destroy_service(struct storage_service_aidl_context* ctx) {
689     delete ctx->inner;
690 }
691 
storage_aidl_enable(struct storage_service_aidl_context * self,struct block_device_tipc * block_devices)692 void storage_aidl_enable(struct storage_service_aidl_context* self,
693                          struct block_device_tipc* block_devices) {
694     storage_service::StorageService& service = self->inner->service;
695     service.TryActivateFilesystem(block_devices, STORAGE_TP);
696     service.TryActivateFilesystem(block_devices, STORAGE_TDEA);
697     service.TryActivateFilesystem(block_devices, STORAGE_TD);
698     service.TryActivateFilesystem(block_devices, STORAGE_TDP);
699     service.TryActivateFilesystem(block_devices, STORAGE_NSP);
700 }
701 
storage_aidl_disable(struct storage_service_aidl_context * self)702 void storage_aidl_disable(struct storage_service_aidl_context* self) {
703     storage_service::StorageService& service = self->inner->service;
704     service.DeactivateFilesystem(STORAGE_NSP);
705     service.DeactivateFilesystem(STORAGE_TDP);
706     service.DeactivateFilesystem(STORAGE_TD);
707     service.DeactivateFilesystem(STORAGE_TDEA);
708     service.DeactivateFilesystem(STORAGE_TP);
709 }