aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'install.cpp')
-rw-r--r--install.cpp203
1 files changed, 187 insertions, 16 deletions
diff --git a/install.cpp b/install.cpp
index 0f9088a7..fada2de6 100644
--- a/install.cpp
+++ b/install.cpp
@@ -17,6 +17,7 @@
17#include <ctype.h> 17#include <ctype.h>
18#include <errno.h> 18#include <errno.h>
19#include <fcntl.h> 19#include <fcntl.h>
20#include <inttypes.h>
20#include <limits.h> 21#include <limits.h>
21#include <string.h> 22#include <string.h>
22#include <sys/stat.h> 23#include <sys/stat.h>
@@ -24,6 +25,8 @@
24#include <unistd.h> 25#include <unistd.h>
25 26
26#include <chrono> 27#include <chrono>
28#include <limits>
29#include <map>
27#include <string> 30#include <string>
28#include <vector> 31#include <vector>
29 32
@@ -32,6 +35,7 @@
32#include <android-base/parseint.h> 35#include <android-base/parseint.h>
33#include <android-base/stringprintf.h> 36#include <android-base/stringprintf.h>
34#include <android-base/strings.h> 37#include <android-base/strings.h>
38#include <cutils/properties.h>
35#include <ziparchive/zip_archive.h> 39#include <ziparchive/zip_archive.h>
36 40
37#include "common.h" 41#include "common.h"
@@ -46,6 +50,8 @@
46extern RecoveryUI* ui; 50extern RecoveryUI* ui;
47 51
48#define ASSUMED_UPDATE_BINARY_NAME "META-INF/com/google/android/update-binary" 52#define ASSUMED_UPDATE_BINARY_NAME "META-INF/com/google/android/update-binary"
53static constexpr const char* AB_OTA_PAYLOAD_PROPERTIES = "payload_properties.txt";
54static constexpr const char* AB_OTA_PAYLOAD = "payload.bin";
49#define PUBLIC_KEYS_FILE "/res/keys" 55#define PUBLIC_KEYS_FILE "/res/keys"
50static constexpr const char* METADATA_PATH = "META-INF/com/android/metadata"; 56static constexpr const char* METADATA_PATH = "META-INF/com/android/metadata";
51static constexpr const char* UNCRYPT_STATUS = "/cache/recovery/uncrypt_status"; 57static constexpr const char* UNCRYPT_STATUS = "/cache/recovery/uncrypt_status";
@@ -120,13 +126,146 @@ static void read_source_target_build(ZipArchiveHandle zip, std::vector<std::stri
120 } 126 }
121} 127}
122 128
123// If the package contains an update binary, extract it and run it. 129// Extract the update binary from the open zip archive |zip| located at |path|
130// and store into |cmd| the command line that should be called. The |status_fd|
131// is the file descriptor the child process should use to report back the
132// progress of the update.
124static int 133static int
125try_update_binary(const char* path, ZipArchiveHandle zip, bool* wipe_cache, 134update_binary_command(const char* path, ZipArchiveHandle zip, int retry_count,
126 std::vector<std::string>& log_buffer, int retry_count) 135 int status_fd, std::vector<std::string>* cmd);
136
137#ifdef AB_OTA_UPDATER
138
139// Parses the metadata of the OTA package in |zip| and checks whether we are
140// allowed to accept this A/B package. Downgrading is not allowed unless
141// explicitly enabled in the package and only for incremental packages.
142static int check_newer_ab_build(ZipArchiveHandle zip)
127{ 143{
128 read_source_target_build(zip, log_buffer); 144 std::string metadata_str;
145 if (!read_metadata_from_package(zip, &metadata_str)) {
146 return INSTALL_CORRUPT;
147 }
148 std::map<std::string, std::string> metadata;
149 for (const std::string& line : android::base::Split(metadata_str, "\n")) {
150 size_t eq = line.find('=');
151 if (eq != std::string::npos) {
152 metadata[line.substr(0, eq)] = line.substr(eq + 1);
153 }
154 }
155 char value[PROPERTY_VALUE_MAX];
156
157 property_get("ro.product.device", value, "");
158 const std::string& pkg_device = metadata["pre-device"];
159 if (pkg_device != value || pkg_device.empty()) {
160 LOG(ERROR) << "Package is for product " << pkg_device << " but expected " << value;
161 return INSTALL_ERROR;
162 }
163
164 // We allow the package to not have any serialno, but if it has a non-empty
165 // value it should match.
166 property_get("ro.serialno", value, "");
167 const std::string& pkg_serial_no = metadata["serialno"];
168 if (!pkg_serial_no.empty() && pkg_serial_no != value) {
169 LOG(ERROR) << "Package is for serial " << pkg_serial_no;
170 return INSTALL_ERROR;
171 }
172
173 if (metadata["ota-type"] != "AB") {
174 LOG(ERROR) << "Package is not A/B";
175 return INSTALL_ERROR;
176 }
177
178 // Incremental updates should match the current build.
179 property_get("ro.build.version.incremental", value, "");
180 const std::string& pkg_pre_build = metadata["pre-build-incremental"];
181 if (!pkg_pre_build.empty() && pkg_pre_build != value) {
182 LOG(ERROR) << "Package is for source build " << pkg_pre_build << " but expected " << value;
183 return INSTALL_ERROR;
184 }
185 property_get("ro.build.fingerprint", value, "");
186 const std::string& pkg_pre_build_fingerprint = metadata["pre-build"];
187 if (!pkg_pre_build_fingerprint.empty() &&
188 pkg_pre_build_fingerprint != value) {
189 LOG(ERROR) << "Package is for source build " << pkg_pre_build_fingerprint
190 << " but expected " << value;
191 return INSTALL_ERROR;
192 }
193
194 // Check for downgrade version.
195 int64_t build_timestamp = property_get_int64(
196 "ro.build.date.utc", std::numeric_limits<int64_t>::max());
197 int64_t pkg_post_timestamp = 0;
198 // We allow to full update to the same version we are running, in case there
199 // is a problem with the current copy of that version.
200 if (metadata["post-timestamp"].empty() ||
201 !android::base::ParseInt(metadata["post-timestamp"].c_str(),
202 &pkg_post_timestamp) ||
203 pkg_post_timestamp < build_timestamp) {
204 if (metadata["ota-downgrade"] != "yes") {
205 LOG(ERROR) << "Update package is older than the current build, expected a build "
206 "newer than timestamp " << build_timestamp << " but package has "
207 "timestamp " << pkg_post_timestamp << " and downgrade not allowed.";
208 return INSTALL_ERROR;
209 }
210 if (pkg_pre_build_fingerprint.empty()) {
211 LOG(ERROR) << "Downgrade package must have a pre-build version set, not allowed.";
212 return INSTALL_ERROR;
213 }
214 }
215
216 return 0;
217}
218
219static int
220update_binary_command(const char* path, ZipArchiveHandle zip, int retry_count,
221 int status_fd, std::vector<std::string>* cmd)
222{
223 int ret = check_newer_ab_build(zip);
224 if (ret) {
225 return ret;
226 }
129 227
228 // For A/B updates we extract the payload properties to a buffer and obtain
229 // the RAW payload offset in the zip file.
230 ZipString property_name(AB_OTA_PAYLOAD_PROPERTIES);
231 ZipEntry properties_entry;
232 if (FindEntry(zip, property_name, &properties_entry) != 0) {
233 LOG(ERROR) << "Can't find " << AB_OTA_PAYLOAD_PROPERTIES;
234 return INSTALL_CORRUPT;
235 }
236 std::vector<uint8_t> payload_properties(
237 properties_entry.uncompressed_length);
238 if (ExtractToMemory(zip, &properties_entry, payload_properties.data(),
239 properties_entry.uncompressed_length) != 0) {
240 LOG(ERROR) << "Can't extract " << AB_OTA_PAYLOAD_PROPERTIES;
241 return INSTALL_CORRUPT;
242 }
243
244 ZipString payload_name(AB_OTA_PAYLOAD);
245 ZipEntry payload_entry;
246 if (FindEntry(zip, payload_name, &payload_entry) != 0) {
247 LOG(ERROR) << "Can't find " << AB_OTA_PAYLOAD;
248 return INSTALL_CORRUPT;
249 }
250 long payload_offset = payload_entry.offset;
251 *cmd = {
252 "/sbin/update_engine_sideload",
253 android::base::StringPrintf("--payload=file://%s", path),
254 android::base::StringPrintf("--offset=%ld", payload_offset),
255 "--headers=" + std::string(payload_properties.begin(),
256 payload_properties.end()),
257 android::base::StringPrintf("--status_fd=%d", status_fd),
258 };
259 return 0;
260}
261
262#else // !AB_OTA_UPDATER
263
264static int
265update_binary_command(const char* path, ZipArchiveHandle zip, int retry_count,
266 int status_fd, std::vector<std::string>* cmd)
267{
268 // On traditional updates we extract the update binary from the package.
130 ZipString binary_name(ASSUMED_UPDATE_BINARY_NAME); 269 ZipString binary_name(ASSUMED_UPDATE_BINARY_NAME);
131 ZipEntry binary_entry; 270 ZipEntry binary_entry;
132 if (FindEntry(zip, binary_name, &binary_entry) != 0) { 271 if (FindEntry(zip, binary_name, &binary_entry) != 0) {
@@ -149,9 +288,36 @@ try_update_binary(const char* path, ZipArchiveHandle zip, bool* wipe_cache,
149 return INSTALL_ERROR; 288 return INSTALL_ERROR;
150 } 289 }
151 290
291 *cmd = {
292 binary,
293 EXPAND(RECOVERY_API_VERSION), // defined in Android.mk
294 std::to_string(status_fd),
295 path,
296 };
297 if (retry_count > 0)
298 cmd->push_back("retry");
299 return 0;
300}
301#endif // !AB_OTA_UPDATER
302
303// If the package contains an update binary, extract it and run it.
304static int
305try_update_binary(const char* path, ZipArchiveHandle zip, bool* wipe_cache,
306 std::vector<std::string>& log_buffer, int retry_count)
307{
308 read_source_target_build(zip, log_buffer);
309
152 int pipefd[2]; 310 int pipefd[2];
153 pipe(pipefd); 311 pipe(pipefd);
154 312
313 std::vector<std::string> args;
314 int ret = update_binary_command(path, zip, retry_count, pipefd[1], &args);
315 if (ret) {
316 close(pipefd[0]);
317 close(pipefd[1]);
318 return ret;
319 }
320
155 // When executing the update binary contained in the package, the 321 // When executing the update binary contained in the package, the
156 // arguments passed are: 322 // arguments passed are:
157 // 323 //
@@ -201,22 +367,27 @@ try_update_binary(const char* path, ZipArchiveHandle zip, bool* wipe_cache,
201 // update attempt. 367 // update attempt.
202 // 368 //
203 369
204 const char* args[6]; 370 // Convert the vector to a NULL-terminated char* array suitable for execv.
205 args[0] = binary; 371 const char* chr_args[args.size() + 1];
206 args[1] = EXPAND(RECOVERY_API_VERSION); // defined in Android.mk 372 chr_args[args.size()] = NULL;
207 char temp[16]; 373 for (size_t i = 0; i < args.size(); i++) {
208 snprintf(temp, sizeof(temp), "%d", pipefd[1]); 374 chr_args[i] = args[i].c_str();
209 args[2] = temp; 375 }
210 args[3] = path;
211 args[4] = retry_count > 0 ? "retry" : NULL;
212 args[5] = NULL;
213 376
214 pid_t pid = fork(); 377 pid_t pid = fork();
378
379 if (pid == -1) {
380 close(pipefd[0]);
381 close(pipefd[1]);
382 PLOG(ERROR) << "Failed to fork update binary";
383 return INSTALL_ERROR;
384 }
385
215 if (pid == 0) { 386 if (pid == 0) {
216 umask(022); 387 umask(022);
217 close(pipefd[0]); 388 close(pipefd[0]);
218 execv(binary, const_cast<char**>(args)); 389 execv(chr_args[0], const_cast<char**>(chr_args));
219 fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno)); 390 fprintf(stdout, "E:Can't run %s (%s)\n", chr_args[0], strerror(errno));
220 _exit(-1); 391 _exit(-1);
221 } 392 }
222 close(pipefd[1]); 393 close(pipefd[1]);
@@ -373,7 +544,7 @@ install_package(const char* path, bool* wipe_cache, const char* install_file,
373 if (!android::base::ReadFileToString(UNCRYPT_STATUS, &uncrypt_status)) { 544 if (!android::base::ReadFileToString(UNCRYPT_STATUS, &uncrypt_status)) {
374 PLOG(WARNING) << "failed to read uncrypt status"; 545 PLOG(WARNING) << "failed to read uncrypt status";
375 } else if (!android::base::StartsWith(uncrypt_status, "uncrypt_")) { 546 } else if (!android::base::StartsWith(uncrypt_status, "uncrypt_")) {
376 LOG(WARNING) << "corrupted uncrypt_status: " << uncrypt_status; 547 PLOG(WARNING) << "corrupted uncrypt_status: " << uncrypt_status;
377 } else { 548 } else {
378 log_buffer.push_back(android::base::Trim(uncrypt_status)); 549 log_buffer.push_back(android::base::Trim(uncrypt_status));
379 } 550 }