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 }