1 /*
2 * Copyright (C) 2012 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 "install/adb_install.h"
18
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <signal.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/epoll.h>
25 #include <sys/socket.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <sys/wait.h>
29 #include <unistd.h>
30
31 #include <atomic>
32 #include <functional>
33 #include <map>
34 #include <utility>
35 #include <vector>
36
37 #include <android-base/file.h>
38 #include <android-base/logging.h>
39 #include <android-base/memory.h>
40 #include <android-base/properties.h>
41 #include <android-base/strings.h>
42 #include <android-base/unique_fd.h>
43
44 #include "fuse_sideload.h"
45 #include "install/install.h"
46 #include "install/wipe_data.h"
47 #include "minadbd_types.h"
48 #include "otautil/sysutil.h"
49 #include "recovery_ui/device.h"
50 #include "recovery_ui/ui.h"
51
52 // A CommandFunction returns a pair of (result, should_continue), which indicates the command
53 // execution result and whether it should proceed to the next iteration. The execution result will
54 // always be sent to the minadbd side.
55 using CommandFunction = std::function<std::pair<bool, bool>()>;
56
SetUsbConfig(const std::string & state)57 static bool SetUsbConfig(const std::string& state) {
58 android::base::SetProperty("sys.usb.config", state);
59 return android::base::WaitForProperty("sys.usb.state", state);
60 }
61
62 // Parses the minadbd command in |message|; returns MinadbdCommand::kError upon errors.
ParseMinadbdCommand(const std::string & message)63 static MinadbdCommand ParseMinadbdCommand(const std::string& message) {
64 if (!android::base::StartsWith(message, kMinadbdCommandPrefix)) {
65 LOG(ERROR) << "Failed to parse command in message " << message;
66 return MinadbdCommand::kError;
67 }
68
69 auto cmd_code_string = message.substr(strlen(kMinadbdCommandPrefix));
70 auto cmd_code = android::base::get_unaligned<uint32_t>(cmd_code_string.c_str());
71 if (cmd_code >= static_cast<uint32_t>(MinadbdCommand::kError)) {
72 LOG(ERROR) << "Unsupported command code: " << cmd_code;
73 return MinadbdCommand::kError;
74 }
75
76 return static_cast<MinadbdCommand>(cmd_code);
77 }
78
WriteStatusToFd(MinadbdCommandStatus status,int fd)79 static bool WriteStatusToFd(MinadbdCommandStatus status, int fd) {
80 char message[kMinadbdMessageSize];
81 memcpy(message, kMinadbdStatusPrefix, strlen(kMinadbdStatusPrefix));
82 android::base::put_unaligned(message + strlen(kMinadbdStatusPrefix), status);
83
84 if (!android::base::WriteFully(fd, message, kMinadbdMessageSize)) {
85 PLOG(ERROR) << "Failed to write message " << message;
86 return false;
87 }
88 return true;
89 }
90
91 // Installs the package from FUSE. Returns the installation result and whether it should continue
92 // waiting for new commands.
AdbInstallPackageHandler(RecoveryUI * ui,int * result)93 static auto AdbInstallPackageHandler(RecoveryUI* ui, int* result) {
94 // How long (in seconds) we wait for the package path to be ready. It doesn't need to be too long
95 // because the minadbd service has already issued an install command. FUSE_SIDELOAD_HOST_PATHNAME
96 // will start to exist once the host connects and starts serving a package. Poll for its
97 // appearance. (Note that inotify doesn't work with FUSE.)
98 constexpr int ADB_INSTALL_TIMEOUT = 15;
99 bool should_continue = true;
100 *result = INSTALL_ERROR;
101 for (int i = 0; i < ADB_INSTALL_TIMEOUT; ++i) {
102 struct stat st;
103 if (stat(FUSE_SIDELOAD_HOST_PATHNAME, &st) != 0) {
104 if (errno == ENOENT && i < ADB_INSTALL_TIMEOUT - 1) {
105 sleep(1);
106 continue;
107 } else {
108 should_continue = false;
109 ui->Print("\nTimed out waiting for fuse to be ready.\n\n");
110 break;
111 }
112 }
113 *result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0, ui);
114 break;
115 }
116
117 // Calling stat() on this magic filename signals the FUSE to exit.
118 struct stat st;
119 stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st);
120 return std::make_pair(*result == INSTALL_SUCCESS, should_continue);
121 }
122
AdbRebootHandler(MinadbdCommand command,int * result,Device::BuiltinAction * reboot_action)123 static auto AdbRebootHandler(MinadbdCommand command, int* result,
124 Device::BuiltinAction* reboot_action) {
125 // Use Device::REBOOT_{FASTBOOT,RECOVERY,RESCUE}, instead of the ones with ENTER_. This allows
126 // rebooting back into fastboot/recovery/rescue mode through bootloader, which may use a newly
127 // installed bootloader/recovery image.
128 switch (command) {
129 case MinadbdCommand::kRebootBootloader:
130 *reboot_action = Device::REBOOT_BOOTLOADER;
131 break;
132 case MinadbdCommand::kRebootFastboot:
133 *reboot_action = Device::REBOOT_FASTBOOT;
134 break;
135 case MinadbdCommand::kRebootRecovery:
136 *reboot_action = Device::REBOOT_RECOVERY;
137 break;
138 case MinadbdCommand::kRebootRescue:
139 *reboot_action = Device::REBOOT_RESCUE;
140 break;
141 case MinadbdCommand::kRebootAndroid:
142 default:
143 *reboot_action = Device::REBOOT;
144 break;
145 }
146 *result = INSTALL_REBOOT;
147 return std::make_pair(true, false);
148 }
149
150 // Parses and executes the command from minadbd. Returns whether the caller should keep waiting for
151 // next command.
HandleMessageFromMinadbd(int socket_fd,const std::map<MinadbdCommand,CommandFunction> & command_map)152 static bool HandleMessageFromMinadbd(int socket_fd,
153 const std::map<MinadbdCommand, CommandFunction>& command_map) {
154 char buffer[kMinadbdMessageSize];
155 if (!android::base::ReadFully(socket_fd, buffer, kMinadbdMessageSize)) {
156 PLOG(ERROR) << "Failed to read message from minadbd";
157 return false;
158 }
159
160 std::string message(buffer, buffer + kMinadbdMessageSize);
161 auto command_type = ParseMinadbdCommand(message);
162 if (command_type == MinadbdCommand::kError) {
163 return false;
164 }
165 if (command_map.find(command_type) == command_map.end()) {
166 LOG(ERROR) << "Unsupported command: "
167 << android::base::get_unaligned<unsigned int>(
168 message.substr(strlen(kMinadbdCommandPrefix)).c_str());
169 return false;
170 }
171
172 // We have received a valid command, execute the corresponding function.
173 const auto& command_func = command_map.at(command_type);
174 const auto [result, should_continue] = command_func();
175 LOG(INFO) << "Command " << static_cast<uint32_t>(command_type) << " finished with " << result;
176 if (!WriteStatusToFd(result ? MinadbdCommandStatus::kSuccess : MinadbdCommandStatus::kFailure,
177 socket_fd)) {
178 return false;
179 }
180 return should_continue;
181 }
182
183 // TODO(xunchang) add a wrapper function and kill the minadbd service there.
ListenAndExecuteMinadbdCommands(RecoveryUI * ui,pid_t minadbd_pid,android::base::unique_fd && socket_fd,const std::map<MinadbdCommand,CommandFunction> & command_map)184 static void ListenAndExecuteMinadbdCommands(
185 RecoveryUI* ui, pid_t minadbd_pid, android::base::unique_fd&& socket_fd,
186 const std::map<MinadbdCommand, CommandFunction>& command_map) {
187 android::base::unique_fd epoll_fd(epoll_create1(O_CLOEXEC));
188 if (epoll_fd == -1) {
189 PLOG(ERROR) << "Failed to create epoll";
190 kill(minadbd_pid, SIGKILL);
191 return;
192 }
193
194 constexpr int EPOLL_MAX_EVENTS = 10;
195 struct epoll_event ev = {};
196 ev.events = EPOLLIN | EPOLLHUP;
197 ev.data.fd = socket_fd.get();
198 struct epoll_event events[EPOLL_MAX_EVENTS];
199 if (epoll_ctl(epoll_fd.get(), EPOLL_CTL_ADD, socket_fd.get(), &ev) == -1) {
200 PLOG(ERROR) << "Failed to add socket fd to epoll";
201 kill(minadbd_pid, SIGKILL);
202 return;
203 }
204
205 // Set the timeout to be 300s when waiting for minadbd commands.
206 constexpr int TIMEOUT_MILLIS = 300 * 1000;
207 while (true) {
208 // Reset the progress bar and the background image before each command.
209 ui->SetProgressType(RecoveryUI::EMPTY);
210 ui->SetBackground(RecoveryUI::NO_COMMAND);
211
212 // Poll for the status change of the socket_fd, and handle the message if the fd is ready to
213 // read.
214 int event_count =
215 TEMP_FAILURE_RETRY(epoll_wait(epoll_fd.get(), events, EPOLL_MAX_EVENTS, TIMEOUT_MILLIS));
216 if (event_count == -1) {
217 PLOG(ERROR) << "Failed to wait for epoll events";
218 kill(minadbd_pid, SIGKILL);
219 return;
220 }
221 if (event_count == 0) {
222 LOG(ERROR) << "Timeout waiting for messages from minadbd";
223 kill(minadbd_pid, SIGKILL);
224 return;
225 }
226
227 for (int n = 0; n < event_count; n++) {
228 if (events[n].events & EPOLLHUP) {
229 LOG(INFO) << "Socket has been closed";
230 kill(minadbd_pid, SIGKILL);
231 return;
232 }
233 if (!HandleMessageFromMinadbd(socket_fd.get(), command_map)) {
234 kill(minadbd_pid, SIGKILL);
235 return;
236 }
237 }
238 }
239 }
240
241 // Recovery starts minadbd service as a child process, and spawns another thread to listen for the
242 // message from minadbd through a socket pair. Here is an example to execute one command from adb
243 // host.
244 // a. recovery b. listener thread c. minadbd service
245 //
246 // a1. create socket pair
247 // a2. fork minadbd service
248 // c3. wait for the adb commands
249 // from host
250 // c4. after receiving host commands:
251 // 1) set up pre-condition (i.e.
252 // start fuse for adb sideload)
253 // 2) issue command through
254 // socket.
255 // 3) wait for result
256 // a5. start listener thread
257 // b6. listen for message from
258 // minadbd in a loop.
259 // b7. After receiving a minadbd
260 // command from socket
261 // 1) execute the command function
262 // 2) send the result back to
263 // minadbd
264 // ......
265 // c8. exit upon receiving the
266 // result
267 // a9. wait for listener thread
268 // to exit.
269 //
270 // a10. wait for minadbd to
271 // exit
272 // b11. exit the listening loop
273 //
CreateMinadbdServiceAndExecuteCommands(RecoveryUI * ui,const std::map<MinadbdCommand,CommandFunction> & command_map,bool rescue_mode)274 static void CreateMinadbdServiceAndExecuteCommands(
275 RecoveryUI* ui, const std::map<MinadbdCommand, CommandFunction>& command_map,
276 bool rescue_mode) {
277 signal(SIGPIPE, SIG_IGN);
278
279 android::base::unique_fd recovery_socket;
280 android::base::unique_fd minadbd_socket;
281 if (!android::base::Socketpair(AF_UNIX, SOCK_STREAM, 0, &recovery_socket, &minadbd_socket)) {
282 PLOG(ERROR) << "Failed to create socket";
283 return;
284 }
285
286 pid_t child = fork();
287 if (child == -1) {
288 PLOG(ERROR) << "Failed to fork child process";
289 return;
290 }
291 if (child == 0) {
292 recovery_socket.reset();
293 std::vector<std::string> minadbd_commands = {
294 "/system/bin/minadbd",
295 "--socket_fd",
296 std::to_string(minadbd_socket.release()),
297 };
298 if (rescue_mode) {
299 minadbd_commands.push_back("--rescue");
300 }
301 auto exec_args = StringVectorToNullTerminatedArray(minadbd_commands);
302 execv(exec_args[0], exec_args.data());
303 _exit(EXIT_FAILURE);
304 }
305
306 minadbd_socket.reset();
307
308 // We need to call SetUsbConfig() after forking minadbd service. Because the function waits for
309 // the usb state to be updated, which depends on sys.usb.ffs.ready=1 set in the adb daemon.
310 if (!SetUsbConfig("sideload")) {
311 LOG(ERROR) << "Failed to set usb config to sideload";
312 return;
313 }
314
315 std::thread listener_thread(ListenAndExecuteMinadbdCommands, ui, child,
316 std::move(recovery_socket), std::ref(command_map));
317 if (listener_thread.joinable()) {
318 listener_thread.join();
319 }
320
321 int status;
322 waitpid(child, &status, 0);
323 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
324 if (WEXITSTATUS(status) == MinadbdErrorCode::kMinadbdAdbVersionError) {
325 LOG(ERROR) << "\nYou need adb 1.0.32 or newer to sideload\nto this device.\n";
326 } else if (!WIFSIGNALED(status)) {
327 LOG(ERROR) << "\n(adbd status " << WEXITSTATUS(status) << ")";
328 }
329 }
330
331 signal(SIGPIPE, SIG_DFL);
332 }
333
ApplyFromAdb(Device * device,bool rescue_mode,Device::BuiltinAction * reboot_action)334 int ApplyFromAdb(Device* device, bool rescue_mode, Device::BuiltinAction* reboot_action) {
335 // Save the usb state to restore after the sideload operation.
336 std::string usb_state = android::base::GetProperty("sys.usb.state", "none");
337 // Clean up state and stop adbd.
338 if (usb_state != "none" && !SetUsbConfig("none")) {
339 LOG(ERROR) << "Failed to clear USB config";
340 return INSTALL_ERROR;
341 }
342
343 RecoveryUI* ui = device->GetUI();
344
345 int install_result = INSTALL_ERROR;
346 std::map<MinadbdCommand, CommandFunction> command_map{
347 { MinadbdCommand::kInstall, std::bind(&AdbInstallPackageHandler, ui, &install_result) },
348 { MinadbdCommand::kRebootAndroid, std::bind(&AdbRebootHandler, MinadbdCommand::kRebootAndroid,
349 &install_result, reboot_action) },
350 { MinadbdCommand::kRebootBootloader,
351 std::bind(&AdbRebootHandler, MinadbdCommand::kRebootBootloader, &install_result,
352 reboot_action) },
353 { MinadbdCommand::kRebootFastboot, std::bind(&AdbRebootHandler, MinadbdCommand::kRebootFastboot,
354 &install_result, reboot_action) },
355 { MinadbdCommand::kRebootRecovery, std::bind(&AdbRebootHandler, MinadbdCommand::kRebootRecovery,
356 &install_result, reboot_action) },
357 { MinadbdCommand::kRebootRescue,
358 std::bind(&AdbRebootHandler, MinadbdCommand::kRebootRescue, &install_result, reboot_action) },
359 };
360
361 if (!rescue_mode) {
362 ui->Print(
363 "\n\nNow send the package you want to apply\n"
364 "to the device with \"adb sideload <filename>\"...\n");
365 } else {
366 command_map.emplace(MinadbdCommand::kWipeData, [&device]() {
367 bool result = WipeData(device, false);
368 return std::make_pair(result, true);
369 });
370 command_map.emplace(MinadbdCommand::kNoOp, []() { return std::make_pair(true, true); });
371
372 ui->Print("\n\nWaiting for rescue commands...\n");
373 }
374
375 CreateMinadbdServiceAndExecuteCommands(ui, command_map, rescue_mode);
376
377 // Clean up before switching to the older state, for example setting the state
378 // to none sets sys/class/android_usb/android0/enable to 0.
379 if (!SetUsbConfig("none")) {
380 LOG(ERROR) << "Failed to clear USB config";
381 }
382
383 if (usb_state != "none") {
384 if (!SetUsbConfig(usb_state)) {
385 LOG(ERROR) << "Failed to set USB config to " << usb_state;
386 }
387 }
388
389 return install_result;
390 }
391