1 /* 2 * Copyright (C) 2020 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 "incremental.h" 18 19 #include "incremental_utils.h" 20 21 #include <android-base/file.h> 22 #include <android-base/stringprintf.h> 23 #include <openssl/base64.h> 24 25 #include "adb_client.h" 26 #include "adb_utils.h" 27 #include "commandline.h" 28 #include "sysdeps.h" 29 30 using namespace std::literals; 31 32 namespace incremental { 33 34 using android::base::StringPrintf; 35 36 // Read, verify and return the signature bytes. Keeping fd at the position of start of verity tree. read_signature(Size file_size,std::string signature_file,bool silent)37 static std::pair<unique_fd, std::vector<char>> read_signature(Size file_size, 38 std::string signature_file, 39 bool silent) { 40 signature_file += IDSIG; 41 42 struct stat st; 43 if (stat(signature_file.c_str(), &st)) { 44 if (!silent) { 45 fprintf(stderr, "Failed to stat signature file %s. Abort.\n", signature_file.c_str()); 46 } 47 return {}; 48 } 49 50 unique_fd fd(adb_open(signature_file.c_str(), O_RDONLY)); 51 if (fd < 0) { 52 if (!silent) { 53 fprintf(stderr, "Failed to open signature file: %s. Abort.\n", signature_file.c_str()); 54 } 55 return {}; 56 } 57 58 auto [signature, tree_size] = read_id_sig_headers(fd); 59 if (auto expected = verity_tree_size_for_file(file_size); tree_size != expected) { 60 if (!silent) { 61 fprintf(stderr, 62 "Verity tree size mismatch in signature file: %s [was %lld, expected %lld].\n", 63 signature_file.c_str(), (long long)tree_size, (long long)expected); 64 } 65 return {}; 66 } 67 68 return {std::move(fd), std::move(signature)}; 69 } 70 71 // Base64-encode signature bytes. Keeping fd at the position of start of verity tree. read_and_encode_signature(Size file_size,std::string signature_file,bool silent)72 static std::pair<unique_fd, std::string> read_and_encode_signature(Size file_size, 73 std::string signature_file, 74 bool silent) { 75 auto [fd, signature] = read_signature(file_size, std::move(signature_file), silent); 76 if (!fd.ok()) { 77 return {}; 78 } 79 80 size_t base64_len = 0; 81 if (!EVP_EncodedLength(&base64_len, signature.size())) { 82 if (!silent) { 83 fprintf(stderr, "Fail to estimate base64 encoded length. Abort.\n"); 84 } 85 return {}; 86 } 87 std::string encoded_signature(base64_len, '\0'); 88 encoded_signature.resize(EVP_EncodeBlock((uint8_t*)encoded_signature.data(), 89 (const uint8_t*)signature.data(), signature.size())); 90 91 return {std::move(fd), std::move(encoded_signature)}; 92 } 93 94 // Send install-incremental to the device along with properly configured file descriptors in 95 // streaming format. Once connection established, send all fs-verity tree bytes. start_install(const Files & files,const Args & passthrough_args,bool silent)96 static unique_fd start_install(const Files& files, const Args& passthrough_args, bool silent) { 97 std::vector<std::string> command_args{"package", "install-incremental"}; 98 command_args.insert(command_args.end(), passthrough_args.begin(), passthrough_args.end()); 99 100 for (int i = 0, size = files.size(); i < size; ++i) { 101 const auto& file = files[i]; 102 103 struct stat st; 104 if (stat(file.c_str(), &st)) { 105 if (!silent) { 106 fprintf(stderr, "Failed to stat input file %s. Abort.\n", file.c_str()); 107 } 108 return {}; 109 } 110 111 auto [signature_fd, signature] = read_and_encode_signature(st.st_size, file, silent); 112 if (!signature_fd.ok()) { 113 return {}; 114 } 115 116 auto file_desc = StringPrintf("%s:%lld:%d:%s:1", android::base::Basename(file).c_str(), 117 (long long)st.st_size, i, signature.c_str()); 118 command_args.push_back(std::move(file_desc)); 119 } 120 121 std::string error; 122 auto connection_fd = unique_fd(send_abb_exec_command(command_args, &error)); 123 if (connection_fd < 0) { 124 if (!silent) { 125 fprintf(stderr, "Failed to run: %s, error: %s\n", 126 android::base::Join(command_args, " ").c_str(), error.c_str()); 127 } 128 return {}; 129 } 130 131 return connection_fd; 132 } 133 can_install(const Files & files)134 bool can_install(const Files& files) { 135 for (const auto& file : files) { 136 struct stat st; 137 if (stat(file.c_str(), &st)) { 138 return false; 139 } 140 141 auto [fd, _] = read_signature(st.st_size, file, true); 142 if (!fd.ok()) { 143 return false; 144 } 145 } 146 return true; 147 } 148 install(const Files & files,const Args & passthrough_args,bool silent)149 std::optional<Process> install(const Files& files, const Args& passthrough_args, bool silent) { 150 auto connection_fd = start_install(files, passthrough_args, silent); 151 if (connection_fd < 0) { 152 if (!silent) { 153 fprintf(stderr, "adb: failed to initiate installation on device.\n"); 154 } 155 return {}; 156 } 157 158 std::string adb_path = android::base::GetExecutablePath(); 159 160 auto osh = adb_get_os_handle(connection_fd.get()); 161 #ifdef _WIN32 162 auto fd_param = std::to_string(reinterpret_cast<intptr_t>(osh)); 163 #else /* !_WIN32 a.k.a. Unix */ 164 auto fd_param = std::to_string(osh); 165 #endif 166 167 // pipe for child process to write output 168 int print_fds[2]; 169 if (adb_socketpair(print_fds) != 0) { 170 if (!silent) { 171 fprintf(stderr, "Failed to create socket pair for child to print to parent\n"); 172 } 173 return {}; 174 } 175 auto [pipe_read_fd, pipe_write_fd] = print_fds; 176 auto pipe_write_fd_param = std::to_string(intptr_t(adb_get_os_handle(pipe_write_fd))); 177 close_on_exec(pipe_read_fd); 178 179 std::vector<std::string> args(std::move(files)); 180 args.insert(args.begin(), {"inc-server", fd_param, pipe_write_fd_param}); 181 auto child = 182 adb_launch_process(adb_path, std::move(args), {connection_fd.get(), pipe_write_fd}); 183 if (!child) { 184 if (!silent) { 185 fprintf(stderr, "adb: failed to fork: %s\n", strerror(errno)); 186 } 187 return {}; 188 } 189 190 adb_close(pipe_write_fd); 191 192 auto killOnExit = [](Process* p) { p->kill(); }; 193 std::unique_ptr<Process, decltype(killOnExit)> serverKiller(&child, killOnExit); 194 195 Result result = wait_for_installation(pipe_read_fd); 196 adb_close(pipe_read_fd); 197 198 if (result == Result::Success) { 199 // adb client exits now but inc-server can continue 200 serverKiller.release(); 201 } 202 return child; 203 } 204 wait_for_installation(int read_fd)205 Result wait_for_installation(int read_fd) { 206 static constexpr int maxMessageSize = 256; 207 std::vector<char> child_stdout(CHUNK_SIZE); 208 int bytes_read; 209 int buf_size = 0; 210 // TODO(b/150865433): optimize child's output parsing 211 while ((bytes_read = adb_read(read_fd, child_stdout.data() + buf_size, 212 child_stdout.size() - buf_size)) > 0) { 213 // print to parent's stdout 214 fprintf(stdout, "%.*s", bytes_read, child_stdout.data() + buf_size); 215 216 buf_size += bytes_read; 217 const std::string_view stdout_str(child_stdout.data(), buf_size); 218 // wait till installation either succeeds or fails 219 if (stdout_str.find("Success") != std::string::npos) { 220 return Result::Success; 221 } 222 // on failure, wait for full message 223 static constexpr auto failure_msg_head = "Failure ["sv; 224 if (const auto begin_itr = stdout_str.find(failure_msg_head); 225 begin_itr != std::string::npos) { 226 if (buf_size >= maxMessageSize) { 227 return Result::Failure; 228 } 229 const auto end_itr = stdout_str.rfind("]"); 230 if (end_itr != std::string::npos && end_itr >= begin_itr + failure_msg_head.size()) { 231 return Result::Failure; 232 } 233 } 234 child_stdout.resize(buf_size + CHUNK_SIZE); 235 } 236 return Result::None; 237 } 238 239 } // namespace incremental 240