1 /*
2 * Copyright (C) 2021 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 "host/commands/cvd/server.h"
18
19 #include <signal.h>
20 #include <unistd.h>
21
22 #include <atomic>
23 #include <future>
24 #include <map>
25 #include <mutex>
26 #include <optional>
27 #include <thread>
28
29 #include <android-base/file.h>
30 #include <android-base/logging.h>
31 #include <android-base/strings.h>
32 #include <fruit/fruit.h>
33
34 #include "cvd_server.pb.h"
35
36 #include "common/libs/fs/shared_buf.h"
37 #include "common/libs/fs/shared_fd.h"
38 #include "common/libs/fs/shared_select.h"
39 #include "common/libs/utils/files.h"
40 #include "common/libs/utils/flag_parser.h"
41 #include "common/libs/utils/result.h"
42 #include "common/libs/utils/scope_guard.h"
43 #include "common/libs/utils/shared_fd_flag.h"
44 #include "common/libs/utils/subprocess.h"
45 #include "host/commands/cvd/build_api.h"
46 #include "host/commands/cvd/command_sequence.h"
47 #include "host/commands/cvd/demo_multi_vd.h"
48 #include "host/commands/cvd/epoll_loop.h"
49 #include "host/commands/cvd/logger.h"
50 #include "host/commands/cvd/server_command/acloud.h"
51 #include "host/commands/cvd/server_command/cmd_list.h"
52 #include "host/commands/cvd/server_command/crosvm.h"
53 #include "host/commands/cvd/server_command/display.h"
54 #include "host/commands/cvd/server_command/env.h"
55 #include "host/commands/cvd/server_command/generic.h"
56 #include "host/commands/cvd/server_command/handler_proxy.h"
57 #include "host/commands/cvd/server_command/load_configs.h"
58 #include "host/commands/cvd/server_command/operation_to_bins_map.h"
59 #include "host/commands/cvd/server_command/power.h"
60 #include "host/commands/cvd/server_command/reset.h"
61 #include "host/commands/cvd/server_command/start.h"
62 #include "host/commands/cvd/server_command/subcmd.h"
63 #include "host/commands/cvd/server_constants.h"
64 #include "host/libs/config/cuttlefish_config.h"
65 #include "host/libs/config/inject.h"
66 #include "host/libs/config/known_paths.h"
67
68 namespace cuttlefish {
69
70 static constexpr int kNumThreads = 10;
71
CvdServer(BuildApi & build_api,EpollPool & epoll_pool,InstanceManager & instance_manager,HostToolTargetManager & host_tool_target_manager,ServerLogger & server_logger)72 CvdServer::CvdServer(BuildApi& build_api, EpollPool& epoll_pool,
73 InstanceManager& instance_manager,
74 HostToolTargetManager& host_tool_target_manager,
75 ServerLogger& server_logger)
76 : build_api_(build_api),
77 epoll_pool_(epoll_pool),
78 instance_manager_(instance_manager),
79 host_tool_target_manager_(host_tool_target_manager),
80 server_logger_(server_logger),
81 running_(true),
82 optout_(false) {
83 std::scoped_lock lock(threads_mutex_);
84 for (auto i = 0; i < kNumThreads; i++) {
85 threads_.emplace_back([this]() {
86 while (running_) {
87 auto result = epoll_pool_.HandleEvent();
88 if (!result.ok()) {
89 LOG(ERROR) << "Epoll worker error:\n" << result.error().Message();
90 LOG(DEBUG) << "Epoll worker error:\n" << result.error().Trace();
91 }
92 }
93 auto wakeup = BestEffortWakeup();
94 CHECK(wakeup.ok()) << wakeup.error().Trace();
95 });
96 }
97 }
98
~CvdServer()99 CvdServer::~CvdServer() {
100 running_ = false;
101 auto wakeup = BestEffortWakeup();
102 CHECK(wakeup.ok()) << wakeup.error().Trace();
103 Join();
104 }
105
RequestComponent(CvdServer * server)106 fruit::Component<> CvdServer::RequestComponent(CvdServer* server) {
107 return fruit::createComponent()
108 .bindInstance(*server)
109 .bindInstance(server->instance_manager_)
110 .bindInstance(server->build_api_)
111 .bindInstance(server->host_tool_target_manager_)
112 .bindInstance<
113 fruit::Annotated<AcloudTranslatorOptOut, std::atomic<bool>>>(
114 server->optout_)
115 .install(CvdAcloudComponent)
116 .install(CvdCmdlistComponent)
117 .install(CommandSequenceExecutorComponent)
118 .install(CvdCrosVmComponent)
119 .install(cvdCommandComponent)
120 .install(CvdDevicePowerComponent)
121 .install(CvdDisplayComponent)
122 .install(CvdEnvComponent)
123 .install(cvdGenericCommandComponent)
124 .install(CvdHandlerProxyComponent)
125 .install(CvdHelpComponent)
126 .install(CvdResetComponent)
127 .install(CvdRestartComponent)
128 .install(cvdShutdownComponent)
129 .install(CvdStartCommandComponent)
130 .install(cvdVersionComponent)
131 .install(DemoMultiVdComponent)
132 .install(LoadConfigsComponent);
133 }
134
BestEffortWakeup()135 Result<void> CvdServer::BestEffortWakeup() {
136 // This attempts to cascade through the responder threads, forcing them
137 // to wake up and see that running_ is false, then exit and wake up
138 // further threads.
139 auto eventfd = SharedFD::Event();
140 CF_EXPECT(eventfd->IsOpen(), eventfd->StrError());
141 CF_EXPECT(eventfd->EventfdWrite(1) == 0, eventfd->StrError());
142
143 auto cb = [](EpollEvent) -> Result<void> { return {}; };
144 CF_EXPECT(epoll_pool_.Register(eventfd, EPOLLIN, cb));
145 return {};
146 }
147
Stop()148 void CvdServer::Stop() {
149 {
150 std::lock_guard lock(ongoing_requests_mutex_);
151 running_ = false;
152 }
153 while (true) {
154 std::shared_ptr<OngoingRequest> request;
155 {
156 std::lock_guard lock(ongoing_requests_mutex_);
157 if (ongoing_requests_.empty()) {
158 break;
159 }
160 auto it = ongoing_requests_.begin();
161 request = *it;
162 ongoing_requests_.erase(it);
163 }
164 {
165 std::lock_guard lock(request->mutex);
166 if (request->handler == nullptr) {
167 continue;
168 }
169 request->handler->Interrupt();
170 }
171 auto wakeup = BestEffortWakeup();
172 CHECK(wakeup.ok()) << wakeup.error().Trace();
173 std::scoped_lock lock(threads_mutex_);
174 for (auto& thread : threads_) {
175 auto current_thread = thread.get_id() == std::this_thread::get_id();
176 auto matching_thread = thread.get_id() == request->thread_id;
177 if (!current_thread && matching_thread && thread.joinable()) {
178 thread.join();
179 }
180 }
181 }
182 }
183
Join()184 void CvdServer::Join() {
185 for (auto& thread : threads_) {
186 if (thread.joinable()) {
187 thread.join();
188 }
189 }
190 }
191
Exec(const ExecParam & exec_param)192 Result<void> CvdServer::Exec(const ExecParam& exec_param) {
193 CF_EXPECT(server_fd_->IsOpen(), "Server not running");
194 Stop();
195 android::base::unique_fd server_dup{server_fd_->UNMANAGED_Dup()};
196 CF_EXPECT(server_dup.get() >= 0, "dup: \"" << server_fd_->StrError() << "\"");
197 android::base::unique_fd client_dup{
198 exec_param.carryover_client_fd->UNMANAGED_Dup()};
199 CF_EXPECT(client_dup.get() >= 0, "dup: \"" << server_fd_->StrError() << "\"");
200 android::base::unique_fd client_stderr_dup{
201 exec_param.client_stderr_fd->UNMANAGED_Dup()};
202 CF_EXPECT(client_stderr_dup.get() >= 0,
203 "dup: \"" << exec_param.client_stderr_fd->StrError() << "\"");
204 cvd_common::Args argv_str = {
205 kServerExecPath,
206 "-INTERNAL_server_fd=" + std::to_string(server_dup.get()),
207 "-INTERNAL_carryover_client_fd=" + std::to_string(client_dup.get()),
208 "-INTERNAL_carryover_stderr_fd=" +
209 std::to_string(client_stderr_dup.get()),
210 };
211
212 int in_memory_dup = -1;
213 ScopeGuard exit_action([&in_memory_dup]() {
214 if (in_memory_dup >= 0) {
215 if (close(in_memory_dup) != 0) {
216 LOG(ERROR) << "Failed to close file " << in_memory_dup;
217 }
218 }
219 });
220 if (exec_param.in_memory_data_fd) {
221 in_memory_dup = exec_param.in_memory_data_fd.value()->UNMANAGED_Dup();
222 CF_EXPECT(
223 in_memory_dup >= 0,
224 "dup: \"" << exec_param.in_memory_data_fd.value()->StrError() << "\"");
225 argv_str.push_back("-INTERNAL_memory_carryover_fd=" +
226 std::to_string(in_memory_dup));
227 }
228
229 std::vector<char*> argv_cstr;
230 for (const auto& argv : argv_str) {
231 argv_cstr.emplace_back(strdup(argv.c_str()));
232 }
233 argv_cstr.emplace_back(nullptr);
234 android::base::unique_fd new_exe_dup{exec_param.new_exe->UNMANAGED_Dup()};
235 CF_EXPECT(new_exe_dup.get() >= 0,
236 "dup: \"" << exec_param.new_exe->StrError() << "\"");
237
238 if (exec_param.verbose) {
239 LOG(ERROR) << "Server Exec'ing: " << android::base::Join(argv_str, " ");
240 }
241
242 fexecve(new_exe_dup.get(), argv_cstr.data(), environ);
243 for (const auto& argv : argv_cstr) {
244 free(argv);
245 }
246 return CF_ERR("fexecve failed: \"" << strerror(errno) << "\"");
247 }
248
RequestHandler(const RequestWithStdio & request,const std::vector<CvdServerHandler * > & handlers)249 Result<CvdServerHandler*> RequestHandler(
250 const RequestWithStdio& request,
251 const std::vector<CvdServerHandler*>& handlers) {
252 Result<cvd::Response> response;
253 std::vector<CvdServerHandler*> compatible_handlers;
254 for (auto& handler : handlers) {
255 if (CF_EXPECT(handler->CanHandle(request))) {
256 compatible_handlers.push_back(handler);
257 }
258 }
259 CF_EXPECT(compatible_handlers.size() == 1,
260 "Expected exactly one handler for message, found "
261 << compatible_handlers.size());
262 return compatible_handlers[0];
263 }
264
StartServer(SharedFD server_fd)265 Result<void> CvdServer::StartServer(SharedFD server_fd) {
266 server_fd_ = server_fd;
267 auto cb = [this](EpollEvent ev) -> Result<void> {
268 CF_EXPECT(AcceptClient(ev));
269 return {};
270 };
271 CF_EXPECT(epoll_pool_.Register(server_fd, EPOLLIN, cb));
272 return {};
273 }
274
AcceptCarryoverClient(SharedFD client,std::unique_ptr<ServerLogger::ScopedLogger>)275 Result<void> CvdServer::AcceptCarryoverClient(
276 SharedFD client,
277 // the passed ScopedLogger should be destroyed on return of this function.
278 std::unique_ptr<ServerLogger::ScopedLogger>) {
279 auto self_cb = [this](EpollEvent ev) -> Result<void> {
280 CF_EXPECT(HandleMessage(ev));
281 return {};
282 };
283 CF_EXPECT(epoll_pool_.Register(client, EPOLLIN, self_cb));
284
285 cvd::Response success_message;
286 success_message.mutable_status()->set_code(cvd::Status::OK);
287 success_message.mutable_command_response();
288 CF_EXPECT(SendResponse(client, success_message));
289 return {};
290 }
291
AcceptClient(EpollEvent event)292 Result<void> CvdServer::AcceptClient(EpollEvent event) {
293 ScopeGuard stop_on_failure([this] { Stop(); });
294
295 CF_EXPECT(event.events & EPOLLIN);
296 auto client_fd = SharedFD::Accept(*event.fd);
297 CF_EXPECT(client_fd->IsOpen(), client_fd->StrError());
298 auto client_cb = [this](EpollEvent ev) -> Result<void> {
299 CF_EXPECT(HandleMessage(ev));
300 return {};
301 };
302 CF_EXPECT(epoll_pool_.Register(client_fd, EPOLLIN, client_cb));
303
304 auto self_cb = [this](EpollEvent ev) -> Result<void> {
305 CF_EXPECT(AcceptClient(ev));
306 return {};
307 };
308 CF_EXPECT(epoll_pool_.Register(event.fd, EPOLLIN, self_cb));
309
310 stop_on_failure.Cancel();
311 return {};
312 }
313
HandleMessage(EpollEvent event)314 Result<void> CvdServer::HandleMessage(EpollEvent event) {
315 ScopeGuard abandon_client([this, event] { epoll_pool_.Remove(event.fd); });
316
317 if (event.events & EPOLLHUP) { // Client went away.
318 epoll_pool_.Remove(event.fd);
319 return {};
320 }
321
322 CF_EXPECT(event.events & EPOLLIN);
323 auto request = CF_EXPECT(GetRequest(event.fd));
324 if (!request) { // End-of-file / client went away.
325 epoll_pool_.Remove(event.fd);
326 return {};
327 }
328
329 auto logger = server_logger_.LogThreadToFd(request->Err());
330 auto response = HandleRequest(*request, event.fd);
331 if (!response.ok()) {
332 cvd::Response failure_message;
333 failure_message.mutable_status()->set_code(cvd::Status::INTERNAL);
334 failure_message.mutable_status()->set_message(response.error().Trace());
335 CF_EXPECT(SendResponse(event.fd, failure_message));
336 return {}; // Error already sent to the client, don't repeat on the server
337 }
338 CF_EXPECT(SendResponse(event.fd, *response));
339
340 auto self_cb = [this, err = request->Err()](EpollEvent ev) -> Result<void> {
341 CF_EXPECT(HandleMessage(ev));
342 return {};
343 };
344 CF_EXPECT(epoll_pool_.Register(event.fd, EPOLLIN, self_cb));
345
346 abandon_client.Cancel();
347 return {};
348 }
349
350 // convert HOME, ANDROID_HOST_OUT, ANDROID_SOONG_HOST_OUT
351 // and ANDROID_PRODUCT_OUT into absolute paths if any.
ConvertDirPathToAbsolute(const RequestWithStdio & request)352 static Result<RequestWithStdio> ConvertDirPathToAbsolute(
353 const RequestWithStdio& request) {
354 if (request.Message().contents_case() !=
355 cvd::Request::ContentsCase::kCommandRequest) {
356 return request;
357 }
358 if (request.Message().command_request().env().empty()) {
359 return request;
360 }
361 auto envs =
362 cvd_common::ConvertToEnvs(request.Message().command_request().env());
363 std::unordered_set<std::string> interested_envs{
364 kAndroidHostOut, kAndroidSoongHostOut, "HOME", kAndroidProductOut};
365 const auto& current_dir =
366 request.Message().command_request().working_directory();
367
368 // make sure that "~" is not included
369 for (const auto& key : interested_envs) {
370 if (!Contains(envs, key)) {
371 continue;
372 }
373 const auto& dir = envs.at(key);
374 CF_EXPECT(dir != "~" && !android::base::StartsWith(dir, "~/"),
375 "The " << key << " directory should not start with ~");
376 }
377
378 for (const auto& key : interested_envs) {
379 if (!Contains(envs, key)) {
380 continue;
381 }
382 const auto dir = envs.at(key);
383 envs[key] =
384 CF_EXPECT(EmulateAbsolutePath({.current_working_dir = current_dir,
385 .home_dir = std::nullopt, // unused
386 .path_to_convert = dir,
387 .follow_symlink = false}));
388 }
389
390 auto cmd_args =
391 cvd_common::ConvertToArgs(request.Message().command_request().args());
392 auto selector_args = cvd_common::ConvertToArgs(
393 request.Message().command_request().selector_opts().args());
394 RequestWithStdio new_request(
395 request.Client(),
396 MakeRequest({.cmd_args = std::move(cmd_args),
397 .selector_args = std::move(selector_args),
398 .env = std::move(envs),
399 .working_dir = current_dir},
400 request.Message().command_request().wait_behavior()),
401 request.FileDescriptors(), request.Credentials());
402 return new_request;
403 }
404
VerifyUser(const RequestWithStdio & request)405 static Result<void> VerifyUser(const RequestWithStdio& request) {
406 CF_EXPECT(request.Credentials(),
407 "ucred is not available while it is necessary.");
408 const uid_t client_uid = request.Credentials()->uid;
409 CF_EXPECT_EQ(client_uid, getuid(), "Cvd server process is one per user.");
410 return {};
411 }
412
HandleRequest(RequestWithStdio orig_request,SharedFD client)413 Result<cvd::Response> CvdServer::HandleRequest(RequestWithStdio orig_request,
414 SharedFD client) {
415 CF_EXPECT(VerifyUser(orig_request));
416 auto request = CF_EXPECT(ConvertDirPathToAbsolute(orig_request));
417 fruit::Injector<> injector(RequestComponent, this);
418
419 for (auto& late_injected : injector.getMultibindings<LateInjected>()) {
420 CF_EXPECT(late_injected->LateInject(injector));
421 }
422
423 auto possible_handlers = injector.getMultibindings<CvdServerHandler>();
424
425 // Even if the interrupt callback outlives the request handler, it'll only
426 // hold on to this struct which will be cleaned out when the request handler
427 // exits.
428 auto shared = std::make_shared<OngoingRequest>();
429 shared->handler = CF_EXPECT(RequestHandler(request, possible_handlers));
430 shared->thread_id = std::this_thread::get_id();
431
432 {
433 std::lock_guard lock(ongoing_requests_mutex_);
434 if (running_) {
435 ongoing_requests_.insert(shared);
436 } else {
437 // We're executing concurrently with a Stop() call.
438 return {};
439 }
440 }
441 ScopeGuard remove_ongoing_request([this, shared] {
442 std::lock_guard lock(ongoing_requests_mutex_);
443 ongoing_requests_.erase(shared);
444 });
445
446 auto interrupt_cb = [this, shared,
447 err = request.Err()](EpollEvent) -> Result<void> {
448 auto logger = server_logger_.LogThreadToFd(err);
449 std::lock_guard lock(shared->mutex);
450 CF_EXPECT(shared->handler != nullptr);
451 CF_EXPECT(shared->handler->Interrupt());
452 return {};
453 };
454 CF_EXPECT(epoll_pool_.Register(client, EPOLLHUP, interrupt_cb));
455
456 auto response = CF_EXPECT(shared->handler->Handle(request));
457 {
458 std::lock_guard lock(shared->mutex);
459 shared->handler = nullptr;
460 }
461 CF_EXPECT(epoll_pool_.Remove(client)); // Delete interrupt handler
462
463 return response;
464 }
465
InstanceDbFromJson(const std::string & json_string)466 Result<void> CvdServer::InstanceDbFromJson(const std::string& json_string) {
467 const uid_t uid = getuid();
468 auto json = CF_EXPECT(ParseJson(json_string));
469 CF_EXPECT(instance_manager_.LoadFromJson(uid, json));
470 return {};
471 }
472
ServerComponent(ServerLogger * server_logger)473 static fruit::Component<> ServerComponent(ServerLogger* server_logger) {
474 return fruit::createComponent()
475 .addMultibinding<CvdServer, CvdServer>()
476 .bindInstance(*server_logger)
477 .install(BuildApiModule)
478 .install(EpollLoopComponent)
479 .install(HostToolTargetManagerComponent)
480 .install(OperationToBinsMapComponent);
481 }
482
CvdServerMain(ServerMainParam && fds)483 Result<int> CvdServerMain(ServerMainParam&& fds) {
484 LOG(INFO) << "Starting server";
485
486 CF_EXPECT(daemon(0, 0) != -1, strerror(errno));
487
488 signal(SIGPIPE, SIG_IGN);
489
490 SharedFD server_fd = std::move(fds.internal_server_fd);
491 CF_EXPECT(server_fd->IsOpen(), "Did not receive a valid cvd_server fd");
492
493 std::unique_ptr<ServerLogger> server_logger = std::move(fds.server_logger);
494 fruit::Injector<> injector(ServerComponent, server_logger.get());
495
496 for (auto& late_injected : injector.getMultibindings<LateInjected>()) {
497 CF_EXPECT(late_injected->LateInject(injector));
498 }
499
500 auto server_bindings = injector.getMultibindings<CvdServer>();
501 CF_EXPECT(server_bindings.size() == 1,
502 "Expected 1 server binding, got " << server_bindings.size());
503 auto& server = *(server_bindings[0]);
504
505 std::optional<SharedFD> memory_carryover_fd =
506 std::move(fds.memory_carryover_fd);
507 if (memory_carryover_fd) {
508 const std::string json_string =
509 CF_EXPECT(ReadAllFromMemFd(*memory_carryover_fd));
510 CF_EXPECT(server.InstanceDbFromJson(json_string),
511 "Failed to load from: " << json_string);
512 }
513
514 server.StartServer(server_fd);
515
516 SharedFD carryover_client = std::move(fds.carryover_client_fd);
517 // The carryover_client wouldn't be available after AcceptCarryoverClient()
518 if (carryover_client->IsOpen()) {
519 // release scoped_logger for this thread inside AcceptCarryoverClient()
520 CF_EXPECT(server.AcceptCarryoverClient(carryover_client,
521 std::move(fds.scoped_logger)));
522 } else {
523 // release scoped_logger now and delete the object
524 fds.scoped_logger.reset();
525 }
526 server.Join();
527
528 return 0;
529 }
530
ReadAllFromMemFd(const SharedFD & mem_fd)531 Result<std::string> ReadAllFromMemFd(const SharedFD& mem_fd) {
532 const auto n_message_size = mem_fd->LSeek(0, SEEK_END);
533 CF_EXPECT_NE(n_message_size, -1, "LSeek on the memory file failed.");
534 std::vector<char> buffer(n_message_size);
535 CF_EXPECT_EQ(mem_fd->LSeek(0, SEEK_SET), 0, mem_fd->StrError());
536 auto n_read = ReadExact(mem_fd, buffer.data(), n_message_size);
537 CF_EXPECT(n_read == n_message_size,
538 "Expected to read " << n_message_size << " bytes but actually read "
539 << n_read << " bytes.");
540 std::string message(buffer.begin(), buffer.end());
541 return message;
542 }
543
544 } // namespace cuttlefish
545