1 //
2 // Copyright (C) 2023 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 #include "host/commands/secure_env/worker_thread_loop_body.h"
17 
18 #include "common/libs/fs/shared_select.h"
19 #include "host/commands/secure_env/suspend_resume_handler.h"
20 
21 namespace cuttlefish {
22 namespace secure_env_impl {
23 
WorkerInnerLoop(std::function<bool ()> process_callback,SharedFD read_fd,SharedFD snapshot_socket)24 Result<void> WorkerInnerLoop(std::function<bool()> process_callback,
25                              SharedFD read_fd, SharedFD snapshot_socket) {
26   for (;;) {
27     SharedFDSet readable_fds;
28     readable_fds.Set(read_fd);
29     readable_fds.Set(snapshot_socket);
30 
31     int num_fds = Select(&readable_fds, nullptr, nullptr, nullptr);
32     if (num_fds < 0) {
33       LOG(FATAL) << "Select() returned a negative value: " << num_fds
34                  << strerror(errno);
35     }
36 
37     if (readable_fds.IsSet(read_fd)) {
38       // if process_callback() fails, we need to reset the secure_env
39       // component.
40       if (!process_callback()) {
41         // NOTE: We don't need to worry about whether `snapshot_socket` is
42         // readable at this point. After the component is reset, we'll re-enter
43         // this loop and take care of it.
44         break;
45       }
46       continue;
47     }
48 
49     if (readable_fds.IsSet(snapshot_socket)) {
50       // Read the suspend request.
51       SnapshotSocketMessage suspend_request;
52       CF_EXPECT_EQ(
53           sizeof(suspend_request),
54           snapshot_socket->Read(&suspend_request, sizeof(suspend_request)),
55           "socket read failed: " << snapshot_socket->StrError());
56       CF_EXPECT_EQ(SnapshotSocketMessage::kSuspend, suspend_request);
57       // Send the ACK response.
58       const SnapshotSocketMessage ack_response =
59           SnapshotSocketMessage::kSuspendAck;
60       CF_EXPECT_EQ(sizeof(ack_response),
61                    snapshot_socket->Write(&ack_response, sizeof(ack_response)),
62                    "socket write failed: " << snapshot_socket->StrError());
63       // Block until resumed.
64       SnapshotSocketMessage resume_request;
65       CF_EXPECT_EQ(
66           sizeof(resume_request),
67           snapshot_socket->Read(&resume_request, sizeof(resume_request)),
68           "socket read failed: " << snapshot_socket->StrError());
69       CF_EXPECT_EQ(SnapshotSocketMessage::kResume, resume_request);
70     }
71   }
72 
73   return {};
74 }
75 
76 }  // namespace secure_env_impl
77 }  // namespace cuttlefish
78