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 if (new_size < 0) {
407 return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
408 "File size must not be negative.");
409 }
410 std::shared_ptr<StorageClientSession> session = session_.lock();
411 if (session == nullptr) {
412 return Status::fromExceptionCode(
413 Status::EX_ILLEGAL_STATE,
414 "IFile cannot be used after its parent session has been destroyed.");
415 }
416 storage_client_session* client_session = session->get();
417 if (client_session == nullptr) {
418 return Status::fromStatusT(android::WOULD_BLOCK);
419 }
420
421 storage_err result = storage_file_set_size(session->get(), file_handle_,
422 new_size, op_flags());
423 return status_from_storage_err(result);
424 }
425
rename(const std::string & new_name,CreationMode dest_create_mode)426 Status rename(const std::string& new_name, CreationMode dest_create_mode) {
427 if (access_mode_ != FileMode::WRITE_ONLY &&
428 access_mode_ != FileMode::READ_WRITE) {
429 return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
430 "File not opened for writing.");
431 }
432 std::shared_ptr<StorageClientSession> session = session_.lock();
433 if (session == nullptr) {
434 return Status::fromExceptionCode(
435 Status::EX_ILLEGAL_STATE,
436 "IFile cannot be used after its parent session has been destroyed.");
437 }
438 storage_client_session* client_session = session->get();
439 if (client_session == nullptr) {
440 return Status::fromStatusT(android::WOULD_BLOCK);
441 }
442
443 storage_err result = storage_file_move(
444 session->get(), file_handle_, true, nullptr, 0, new_name.data(),
445 new_name.size(), create_mode(dest_create_mode), op_flags());
446 return status_from_storage_err(result);
447 }
448
449 private:
op_flags()450 storage_op_flags op_flags() {
451 return storage_op_flags{
452 .allow_repaired = false,
453 .complete_transaction = false,
454 .update_checkpoint = false,
455 };
456 }
457
458 std::weak_ptr<StorageClientSession> session_;
459 uint32_t file_handle_;
460 FileMode access_mode_;
461 };
462
463 class StorageSession : public BnStorageSession {
464 public:
StorageSession(std::shared_ptr<StorageClientSession> session)465 StorageSession(std::shared_ptr<StorageClientSession> session)
466 : session_(std::move(session)) {}
467
stageChangesForCommitOnAbUpdateComplete()468 Status stageChangesForCommitOnAbUpdateComplete() final {
469 return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION);
470 }
471
commitChanges()472 Status commitChanges() final { return endTransactions(true); }
abandonChanges()473 Status abandonChanges() final { return endTransactions(false); }
474
openFile(const std::string & file_name,const OpenOptions & options,sp<IFile> * out)475 Status openFile(const std::string& file_name,
476 const OpenOptions& options,
477 sp<IFile>* out) final {
478 storage_client_session* client_session = session_->get();
479 if (client_session == nullptr) {
480 return Status::fromStatusT(android::WOULD_BLOCK);
481 }
482
483 uint32_t file_handle;
484 storage_err err = storage_file_open(
485 client_session, file_name.data(), file_name.size(),
486 create_mode(options.createMode), options.truncateOnOpen,
487 storage_op_flags{
488 .allow_repaired = false,
489 .complete_transaction = false,
490 .update_checkpoint = false,
491 },
492 &file_handle);
493 if (err != storage_err::STORAGE_NO_ERROR) {
494 return status_from_storage_err(err);
495 }
496
497 *out = sp<File>::make(session_, file_handle, options.accessMode);
498 return Status::ok();
499 }
500
deleteFile(const std::string & file_name)501 Status deleteFile(const std::string& file_name) final {
502 storage_client_session* client_session = session_->get();
503 if (client_session == nullptr) {
504 return Status::fromStatusT(android::WOULD_BLOCK);
505 }
506
507 storage_err err = storage_file_delete(
508 client_session, file_name.data(), file_name.size(),
509 storage_op_flags{
510 .allow_repaired = false,
511 .complete_transaction = false,
512 .update_checkpoint = false,
513 });
514 return status_from_storage_err(err);
515 }
516
renameFile(const std::string & file_name,const std::string & new_name,CreationMode dest_create_mode)517 Status renameFile(const std::string& file_name,
518 const std::string& new_name,
519 CreationMode dest_create_mode) final {
520 storage_client_session* client_session = session_->get();
521 if (client_session == nullptr) {
522 return Status::fromStatusT(android::WOULD_BLOCK);
523 }
524
525 storage_err err = storage_file_move(
526 client_session, 0, false, file_name.data(), file_name.size(),
527 new_name.data(), new_name.size(), create_mode(dest_create_mode),
528 storage_op_flags{
529 .allow_repaired = false,
530 .complete_transaction = false,
531 .update_checkpoint = false,
532 });
533 return status_from_storage_err(err);
534 }
535
openDir(const std::string & file_name,sp<IDir> * out)536 Status openDir(const std::string& file_name, sp<IDir>* out) final {
537 if (!file_name.empty()) {
538 return Status::fromExceptionCode(
539 Status::EX_ILLEGAL_ARGUMENT,
540 "Service currently only supports opening the root dir.");
541 }
542 if (session_->get() == nullptr) {
543 return Status::fromStatusT(android::WOULD_BLOCK);
544 }
545
546 // TODO: Catch tampering?
547 *out = sp<Dir>::make(session_);
548 return Status::ok();
549 }
550
551 private:
endTransactions(bool commit_changes)552 Status endTransactions(bool commit_changes) {
553 storage_op_flags flags = {
554 .allow_repaired = false,
555 .complete_transaction = commit_changes,
556 // TODO: Allow updating checkpoint
557 .update_checkpoint = false,
558 };
559
560 storage_client_session* client_session = session_->get();
561 if (client_session == nullptr) {
562 return Status::fromStatusT(android::WOULD_BLOCK);
563 }
564 storage_err result = storage_transaction_end(client_session, flags);
565 return status_from_storage_err(result);
566 }
567
568 std::shared_ptr<StorageClientSession> session_;
569 };
570
571 class StorageService {
572 public:
MakeSession(const Filesystem & filesystem,const uuid_t * peer,std::shared_ptr<StorageClientSession> * out)573 Status MakeSession(const Filesystem& filesystem,
574 const uuid_t* peer,
575 std::shared_ptr<StorageClientSession>* out) {
576 storage_filesystem_type fs_type;
577 Status result = get_fs(filesystem, &fs_type);
578 if (!result.isOk()) {
579 return result;
580 }
581
582 if (!filesystems_active_[fs_type]) {
583 return Status::fromStatusT(android::WOULD_BLOCK);
584 }
585
586 *out = std::make_shared<StorageClientSession>(
587 filesystems_[fs_type], &filesystems_active_[fs_type], peer);
588 return Status::ok();
589 }
590
DeactivateFilesystem(storage_filesystem_type fs_type)591 void DeactivateFilesystem(storage_filesystem_type fs_type) {
592 if (!filesystems_active_[fs_type]) {
593 // The filesystem might be still be inactive because it wasn't
594 // connected when storage_aidl_enable was called, like NS-backed
595 // filesystems would be before NS is available.
596 return;
597 }
598
599 filesystems_active_[fs_type] = false;
600 }
601
TryActivateFilesystem(struct block_device_tipc * block_devices,storage_filesystem_type fs_type)602 void TryActivateFilesystem(struct block_device_tipc* block_devices,
603 storage_filesystem_type fs_type) {
604 assert(!filesystems_active_[fs_type]);
605
606 if (!block_device_tipc_fs_connected(block_devices, fs_type)) {
607 return;
608 }
609
610 if (filesystems_[fs_type] == nullptr) {
611 filesystems_[fs_type] =
612 block_device_tipc_get_fs(block_devices, fs_type);
613 } else {
614 assert(filesystems_[fs_type] ==
615 block_device_tipc_get_fs(block_devices, fs_type));
616 }
617 filesystems_active_[fs_type] = true;
618 }
619
620 private:
621 std::array<struct fs*, STORAGE_FILESYSTEMS_COUNT> filesystems_;
622 std::array<bool, STORAGE_FILESYSTEMS_COUNT> filesystems_active_;
623 };
624
625 class SecureStorage : public BnSecureStorage {
626 public:
SecureStorage(StorageService * service,uuid_t peer)627 SecureStorage(StorageService* service, uuid_t peer)
628 : service_(service), peer_(peer) {}
629
startSession(const Filesystem & filesystem,sp<IStorageSession> * out)630 Status startSession(const Filesystem& filesystem,
631 sp<IStorageSession>* out) final {
632 std::shared_ptr<StorageClientSession> session;
633 Status result = service_->MakeSession(filesystem, &peer_, &session);
634 if (!result.isOk()) {
635 return result;
636 }
637
638 *out = sp<StorageSession>::make(std::move(session));
639 return Status::ok();
640 }
641
642 private:
643 StorageService* service_;
644 uuid_t peer_;
645 };
646
647 } // namespace
648 } // namespace storage_service
649
650 struct storage_service_aidl_context_inner {
651 sp<RpcServerTrusty> aidl_srv;
652 storage_service::StorageService service;
653 };
654
storage_aidl_create_service(struct storage_service_aidl_context * ctx,struct tipc_hset * hset)655 int storage_aidl_create_service(struct storage_service_aidl_context* ctx,
656 struct tipc_hset* hset) {
657 auto result = std::make_unique<storage_service_aidl_context_inner>();
658 auto& service = result->service;
659
660 auto port_acl =
661 RpcServerTrusty::PortAcl{.flags = storage_service::kAclFlags};
662 auto aidl_srv = RpcServerTrusty::make(
663 hset, STORAGE_ISECURE_STORAGE_PORT,
664 std::make_shared<const RpcServerTrusty::PortAcl>(port_acl),
665 storage_service::kMaxBufferSize);
666 if (aidl_srv == nullptr) {
667 return EXIT_FAILURE;
668 }
669
670 aidl_srv->setPerSessionRootObject([&service](wp<RpcSession> session,
671 const void* peer,
672 size_t peer_size)
673 -> sp<storage_service::
674 SecureStorage> {
675 if (peer_size != sizeof(uuid_t)) {
676 SS_ERR("Creating binder root object, but peer id had unexpected size %zu (expected %zu)",
677 peer_size, sizeof(uuid_t));
678 return nullptr;
679 }
680 uuid_t peer_uuid = *static_cast<const uuid_t*>(peer);
681
682 return sp<storage_service::SecureStorage>::make(&service,
683 std::move(peer_uuid));
684 });
685 result->aidl_srv = std::move(aidl_srv);
686
687 // Caller now owns underlying storage_service_aidl_context
688 ctx->inner = result.release();
689 return EXIT_SUCCESS;
690 }
691
storage_aidl_destroy_service(struct storage_service_aidl_context * ctx)692 void storage_aidl_destroy_service(struct storage_service_aidl_context* ctx) {
693 delete ctx->inner;
694 }
695
storage_aidl_enable(struct storage_service_aidl_context * self,struct block_device_tipc * block_devices)696 void storage_aidl_enable(struct storage_service_aidl_context* self,
697 struct block_device_tipc* block_devices) {
698 storage_service::StorageService& service = self->inner->service;
699 service.TryActivateFilesystem(block_devices, STORAGE_TP);
700 service.TryActivateFilesystem(block_devices, STORAGE_TDEA);
701 service.TryActivateFilesystem(block_devices, STORAGE_TD);
702 service.TryActivateFilesystem(block_devices, STORAGE_TDP);
703 service.TryActivateFilesystem(block_devices, STORAGE_NSP);
704 }
705
storage_aidl_disable(struct storage_service_aidl_context * self)706 void storage_aidl_disable(struct storage_service_aidl_context* self) {
707 storage_service::StorageService& service = self->inner->service;
708 service.DeactivateFilesystem(STORAGE_NSP);
709 service.DeactivateFilesystem(STORAGE_TDP);
710 service.DeactivateFilesystem(STORAGE_TD);
711 service.DeactivateFilesystem(STORAGE_TDEA);
712 service.DeactivateFilesystem(STORAGE_TP);
713 }