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(Device * device,InstallResult * result)93 static auto AdbInstallPackageHandler(Device* device, InstallResult* 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   auto ui = device->GetUI();
99   constexpr int ADB_INSTALL_TIMEOUT = 15;
100   bool should_continue = true;
101   *result = INSTALL_ERROR;
102   for (int i = 0; i < ADB_INSTALL_TIMEOUT; ++i) {
103     struct stat st;
104     if (stat(FUSE_SIDELOAD_HOST_PATHNAME, &st) != 0) {
105       if (errno == ENOENT && i < ADB_INSTALL_TIMEOUT - 1) {
106         sleep(1);
107         continue;
108       } else {
109         should_continue = false;
110         ui->Print("\nTimed out waiting for fuse to be ready.\n\n");
111         break;
112       }
113     }
114 
115     auto package =
116         Package::CreateFilePackage(FUSE_SIDELOAD_HOST_PATHNAME,
117                                    std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1));
118     *result = InstallPackage(package.get(), FUSE_SIDELOAD_HOST_PATHNAME, false, 0, device);
119     break;
120   }
121 
122   // Calling stat() on this magic filename signals the FUSE to exit.
123   struct stat st;
124   stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st);
125   return std::make_pair(*result == INSTALL_SUCCESS, should_continue);
126 }
127 
AdbRebootHandler(MinadbdCommand command,InstallResult * result,Device::BuiltinAction * reboot_action)128 static auto AdbRebootHandler(MinadbdCommand command, InstallResult* result,
129                              Device::BuiltinAction* reboot_action) {
130   // Use Device::REBOOT_{FASTBOOT,RECOVERY,RESCUE}, instead of the ones with ENTER_. This allows
131   // rebooting back into fastboot/recovery/rescue mode through bootloader, which may use a newly
132   // installed bootloader/recovery image.
133   switch (command) {
134     case MinadbdCommand::kRebootBootloader:
135       *reboot_action = Device::REBOOT_BOOTLOADER;
136       break;
137     case MinadbdCommand::kRebootFastboot:
138       *reboot_action = Device::REBOOT_FASTBOOT;
139       break;
140     case MinadbdCommand::kRebootRecovery:
141       *reboot_action = Device::REBOOT_RECOVERY;
142       break;
143     case MinadbdCommand::kRebootRescue:
144       *reboot_action = Device::REBOOT_RESCUE;
145       break;
146     case MinadbdCommand::kRebootAndroid:
147     default:
148       *reboot_action = Device::REBOOT;
149       break;
150   }
151   *result = INSTALL_REBOOT;
152   return std::make_pair(true, false);
153 }
154 
155 // Parses and executes the command from minadbd. Returns whether the caller should keep waiting for
156 // next command.
HandleMessageFromMinadbd(int socket_fd,const std::map<MinadbdCommand,CommandFunction> & command_map)157 static bool HandleMessageFromMinadbd(int socket_fd,
158                                      const std::map<MinadbdCommand, CommandFunction>& command_map) {
159   char buffer[kMinadbdMessageSize];
160   if (!android::base::ReadFully(socket_fd, buffer, kMinadbdMessageSize)) {
161     PLOG(ERROR) << "Failed to read message from minadbd";
162     return false;
163   }
164 
165   std::string message(buffer, buffer + kMinadbdMessageSize);
166   auto command_type = ParseMinadbdCommand(message);
167   if (command_type == MinadbdCommand::kError) {
168     return false;
169   }
170   if (command_map.find(command_type) == command_map.end()) {
171     LOG(ERROR) << "Unsupported command: "
172                << android::base::get_unaligned<unsigned int>(
173                       message.substr(strlen(kMinadbdCommandPrefix)).c_str());
174     return false;
175   }
176 
177   // We have received a valid command, execute the corresponding function.
178   const auto& command_func = command_map.at(command_type);
179   const auto [result, should_continue] = command_func();
180   LOG(INFO) << "Command " << static_cast<uint32_t>(command_type) << " finished with " << result;
181   if (!WriteStatusToFd(result ? MinadbdCommandStatus::kSuccess : MinadbdCommandStatus::kFailure,
182                        socket_fd)) {
183     return false;
184   }
185   return should_continue;
186 }
187 
188 // 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)189 static void ListenAndExecuteMinadbdCommands(
190     RecoveryUI* ui, pid_t minadbd_pid, android::base::unique_fd&& socket_fd,
191     const std::map<MinadbdCommand, CommandFunction>& command_map) {
192   android::base::unique_fd epoll_fd(epoll_create1(O_CLOEXEC));
193   if (epoll_fd == -1) {
194     PLOG(ERROR) << "Failed to create epoll";
195     kill(minadbd_pid, SIGKILL);
196     return;
197   }
198 
199   constexpr int EPOLL_MAX_EVENTS = 10;
200   struct epoll_event ev = {};
201   ev.events = EPOLLIN | EPOLLHUP;
202   ev.data.fd = socket_fd.get();
203   struct epoll_event events[EPOLL_MAX_EVENTS];
204   if (epoll_ctl(epoll_fd.get(), EPOLL_CTL_ADD, socket_fd.get(), &ev) == -1) {
205     PLOG(ERROR) << "Failed to add socket fd to epoll";
206     kill(minadbd_pid, SIGKILL);
207     return;
208   }
209 
210   // Set the timeout to be 300s when waiting for minadbd commands.
211   constexpr int TIMEOUT_MILLIS = 300 * 1000;
212   while (true) {
213     // Reset the progress bar and the background image before each command.
214     ui->SetProgressType(RecoveryUI::EMPTY);
215     ui->SetBackground(RecoveryUI::NO_COMMAND);
216 
217     // Poll for the status change of the socket_fd, and handle the message if the fd is ready to
218     // read.
219     int event_count =
220         TEMP_FAILURE_RETRY(epoll_wait(epoll_fd.get(), events, EPOLL_MAX_EVENTS, TIMEOUT_MILLIS));
221     if (event_count == -1) {
222       PLOG(ERROR) << "Failed to wait for epoll events";
223       kill(minadbd_pid, SIGKILL);
224       return;
225     }
226     if (event_count == 0) {
227       LOG(ERROR) << "Timeout waiting for messages from minadbd";
228       kill(minadbd_pid, SIGKILL);
229       return;
230     }
231 
232     for (int n = 0; n < event_count; n++) {
233       if (events[n].events & EPOLLHUP) {
234         LOG(INFO) << "Socket has been closed";
235         kill(minadbd_pid, SIGKILL);
236         return;
237       }
238       if (!HandleMessageFromMinadbd(socket_fd.get(), command_map)) {
239         kill(minadbd_pid, SIGKILL);
240         return;
241       }
242     }
243   }
244 }
245 
246 // Recovery starts minadbd service as a child process, and spawns another thread to listen for the
247 // message from minadbd through a socket pair. Here is an example to execute one command from adb
248 // host.
249 //  a. recovery                    b. listener thread               c. minadbd service
250 //
251 //  a1. create socket pair
252 //  a2. fork minadbd service
253 //                                                                c3. wait for the adb commands
254 //                                                                    from host
255 //                                                                c4. after receiving host commands:
256 //                                                                  1) set up pre-condition (i.e.
257 //                                                                     start fuse for adb sideload)
258 //                                                                  2) issue command through
259 //                                                                     socket.
260 //                                                                  3) wait for result
261 //  a5. start listener thread
262 //                               b6. listen for message from
263 //                                   minadbd in a loop.
264 //                               b7. After receiving a minadbd
265 //                                   command from socket
266 //                                 1) execute the command function
267 //                                 2) send the result back to
268 //                                    minadbd
269 //  ......
270 //                                                                 c8. exit upon receiving the
271 //                                                                     result
272 // a9.  wait for listener thread
273 //      to exit.
274 //
275 // a10. wait for minadbd to
276 //      exit
277 //                               b11. exit the listening loop
278 //
CreateMinadbdServiceAndExecuteCommands(RecoveryUI * ui,const std::map<MinadbdCommand,CommandFunction> & command_map,bool rescue_mode)279 static void CreateMinadbdServiceAndExecuteCommands(
280     RecoveryUI* ui, const std::map<MinadbdCommand, CommandFunction>& command_map,
281     bool rescue_mode) {
282   signal(SIGPIPE, SIG_IGN);
283 
284   android::base::unique_fd recovery_socket;
285   android::base::unique_fd minadbd_socket;
286   if (!android::base::Socketpair(AF_UNIX, SOCK_STREAM, 0, &recovery_socket, &minadbd_socket)) {
287     PLOG(ERROR) << "Failed to create socket";
288     return;
289   }
290 
291   pid_t child = fork();
292   if (child == -1) {
293     PLOG(ERROR) << "Failed to fork child process";
294     return;
295   }
296   if (child == 0) {
297     recovery_socket.reset();
298     std::vector<std::string> minadbd_commands = {
299       "/system/bin/minadbd",
300       "--socket_fd",
301       std::to_string(minadbd_socket.release()),
302     };
303     if (rescue_mode) {
304       minadbd_commands.push_back("--rescue");
305     }
306     auto exec_args = StringVectorToNullTerminatedArray(minadbd_commands);
307     execv(exec_args[0], exec_args.data());
308     _exit(EXIT_FAILURE);
309   }
310 
311   minadbd_socket.reset();
312 
313   // We need to call SetUsbConfig() after forking minadbd service. Because the function waits for
314   // the usb state to be updated, which depends on sys.usb.ffs.ready=1 set in the adb daemon.
315   if (!SetUsbConfig("sideload")) {
316     LOG(ERROR) << "Failed to set usb config to sideload";
317     return;
318   }
319 
320   std::thread listener_thread(ListenAndExecuteMinadbdCommands, ui, child,
321                               std::move(recovery_socket), std::ref(command_map));
322   if (listener_thread.joinable()) {
323     listener_thread.join();
324   }
325 
326   int status;
327   waitpid(child, &status, 0);
328   if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
329     if (WEXITSTATUS(status) == MinadbdErrorCode::kMinadbdAdbVersionError) {
330       LOG(ERROR) << "\nYou need adb 1.0.32 or newer to sideload\nto this device.\n";
331     } else if (!WIFSIGNALED(status)) {
332       LOG(ERROR) << "\n(adbd status " << WEXITSTATUS(status) << ")";
333     }
334   }
335 
336   signal(SIGPIPE, SIG_DFL);
337 }
338 
ApplyFromAdb(Device * device,bool rescue_mode,Device::BuiltinAction * reboot_action)339 InstallResult ApplyFromAdb(Device* device, bool rescue_mode, Device::BuiltinAction* reboot_action) {
340   // Save the usb state to restore after the sideload operation.
341   std::string usb_state = android::base::GetProperty("sys.usb.state", "none");
342   // Clean up state and stop adbd.
343   if (usb_state != "none" && !SetUsbConfig("none")) {
344     LOG(ERROR) << "Failed to clear USB config";
345     return INSTALL_ERROR;
346   }
347 
348   RecoveryUI* ui = device->GetUI();
349 
350   InstallResult install_result = INSTALL_ERROR;
351   std::map<MinadbdCommand, CommandFunction> command_map{
352     { MinadbdCommand::kInstall, std::bind(&AdbInstallPackageHandler, device, &install_result) },
353     { MinadbdCommand::kRebootAndroid, std::bind(&AdbRebootHandler, MinadbdCommand::kRebootAndroid,
354                                                 &install_result, reboot_action) },
355     { MinadbdCommand::kRebootBootloader,
356       std::bind(&AdbRebootHandler, MinadbdCommand::kRebootBootloader, &install_result,
357                 reboot_action) },
358     { MinadbdCommand::kRebootFastboot, std::bind(&AdbRebootHandler, MinadbdCommand::kRebootFastboot,
359                                                  &install_result, reboot_action) },
360     { MinadbdCommand::kRebootRecovery, std::bind(&AdbRebootHandler, MinadbdCommand::kRebootRecovery,
361                                                  &install_result, reboot_action) },
362     { MinadbdCommand::kRebootRescue,
363       std::bind(&AdbRebootHandler, MinadbdCommand::kRebootRescue, &install_result, reboot_action) },
364   };
365 
366   if (!rescue_mode) {
367     ui->Print(
368         "\n\nNow send the package you want to apply\n"
369         "to the device with \"adb sideload <filename>\"...\n");
370   } else {
371     command_map.emplace(MinadbdCommand::kWipeData, [&device]() {
372       bool result = WipeData(device);
373       return std::make_pair(result, true);
374     });
375     command_map.emplace(MinadbdCommand::kNoOp, []() { return std::make_pair(true, true); });
376 
377     ui->Print("\n\nWaiting for rescue commands...\n");
378   }
379 
380   CreateMinadbdServiceAndExecuteCommands(ui, command_map, rescue_mode);
381 
382   // Clean up before switching to the older state, for example setting the state
383   // to none sets sys/class/android_usb/android0/enable to 0.
384   if (!SetUsbConfig("none")) {
385     LOG(ERROR) << "Failed to clear USB config";
386   }
387 
388   if (usb_state != "none") {
389     if (!SetUsbConfig(usb_state)) {
390       LOG(ERROR) << "Failed to set USB config to " << usb_state;
391     }
392   }
393 
394   return install_result;
395 }
396