1 /*
2 * Copyright (C) 2009 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 "updater/install.h"
18
19 #include <ctype.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <ftw.h>
23 #include <inttypes.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/capability.h>
29 #include <sys/mount.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 #include <sys/wait.h>
33 #include <sys/xattr.h>
34 #include <time.h>
35 #include <unistd.h>
36 #include <utime.h>
37
38 #include <memory>
39 #include <string>
40 #include <vector>
41
42 #include <android-base/file.h>
43 #include <android-base/logging.h>
44 #include <android-base/parsedouble.h>
45 #include <android-base/parseint.h>
46 #include <android-base/properties.h>
47 #include <android-base/stringprintf.h>
48 #include <android-base/strings.h>
49 #include <android-base/unique_fd.h>
50 #include <applypatch/applypatch.h>
51 #include <bootloader_message/bootloader_message.h>
52 #include <ext4_utils/wipe.h>
53 #include <openssl/sha.h>
54 #include <selinux/label.h>
55 #include <selinux/selinux.h>
56 #include <tune2fs.h>
57 #include <ziparchive/zip_archive.h>
58
59 #include "edify/expr.h"
60 #include "otautil/dirutil.h"
61 #include "otautil/error_code.h"
62 #include "otautil/mounts.h"
63 #include "otautil/print_sha1.h"
64 #include "otautil/sysutil.h"
65 #include "updater/updater.h"
66
67 // Send over the buffer to recovery though the command pipe.
uiPrint(State * state,const std::string & buffer)68 static void uiPrint(State* state, const std::string& buffer) {
69 UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
70
71 // "line1\nline2\n" will be split into 3 tokens: "line1", "line2" and "".
72 // So skip sending empty strings to UI.
73 std::vector<std::string> lines = android::base::Split(buffer, "\n");
74 for (auto& line : lines) {
75 if (!line.empty()) {
76 fprintf(ui->cmd_pipe, "ui_print %s\n", line.c_str());
77 }
78 }
79
80 // On the updater side, we need to dump the contents to stderr (which has
81 // been redirected to the log file). Because the recovery will only print
82 // the contents to screen when processing pipe command ui_print.
83 LOG(INFO) << buffer;
84 }
85
uiPrintf(State * _Nonnull state,const char * _Nonnull format,...)86 void uiPrintf(State* _Nonnull state, const char* _Nonnull format, ...) {
87 std::string error_msg;
88
89 va_list ap;
90 va_start(ap, format);
91 android::base::StringAppendV(&error_msg, format, ap);
92 va_end(ap);
93
94 uiPrint(state, error_msg);
95 }
96
97 // This is the updater side handler for ui_print() in edify script. Contents will be sent over to
98 // the recovery side for on-screen display.
UIPrintFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)99 Value* UIPrintFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
100 std::vector<std::string> args;
101 if (!ReadArgs(state, argv, &args)) {
102 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
103 }
104
105 std::string buffer = android::base::Join(args, "");
106 uiPrint(state, buffer);
107 return StringValue(buffer);
108 }
109
110 // package_extract_file(package_file[, dest_file])
111 // Extracts a single package_file from the update package and writes it to dest_file,
112 // overwriting existing files if necessary. Without the dest_file argument, returns the
113 // contents of the package file as a binary blob.
PackageExtractFileFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)114 Value* PackageExtractFileFn(const char* name, State* state,
115 const std::vector<std::unique_ptr<Expr>>& argv) {
116 if (argv.size() < 1 || argv.size() > 2) {
117 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %zu", name,
118 argv.size());
119 }
120
121 if (argv.size() == 2) {
122 // The two-argument version extracts to a file.
123
124 std::vector<std::string> args;
125 if (!ReadArgs(state, argv, &args)) {
126 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name,
127 argv.size());
128 }
129 const std::string& zip_path = args[0];
130 const std::string& dest_path = args[1];
131
132 ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
133 ZipString zip_string_path(zip_path.c_str());
134 ZipEntry entry;
135 if (FindEntry(za, zip_string_path, &entry) != 0) {
136 LOG(ERROR) << name << ": no " << zip_path << " in package";
137 return StringValue("");
138 }
139
140 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
141 open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)));
142 if (fd == -1) {
143 PLOG(ERROR) << name << ": can't open " << dest_path << " for write";
144 return StringValue("");
145 }
146
147 bool success = true;
148 int32_t ret = ExtractEntryToFile(za, &entry, fd);
149 if (ret != 0) {
150 LOG(ERROR) << name << ": Failed to extract entry \"" << zip_path << "\" ("
151 << entry.uncompressed_length << " bytes) to \"" << dest_path
152 << "\": " << ErrorCodeString(ret);
153 success = false;
154 }
155 if (fsync(fd) == -1) {
156 PLOG(ERROR) << "fsync of \"" << dest_path << "\" failed";
157 success = false;
158 }
159
160 if (close(fd.release()) != 0) {
161 PLOG(ERROR) << "close of \"" << dest_path << "\" failed";
162 success = false;
163 }
164
165 return StringValue(success ? "t" : "");
166 } else {
167 // The one-argument version returns the contents of the file as the result.
168
169 std::vector<std::string> args;
170 if (!ReadArgs(state, argv, &args)) {
171 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name,
172 argv.size());
173 }
174 const std::string& zip_path = args[0];
175
176 ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
177 ZipString zip_string_path(zip_path.c_str());
178 ZipEntry entry;
179 if (FindEntry(za, zip_string_path, &entry) != 0) {
180 return ErrorAbort(state, kPackageExtractFileFailure, "%s(): no %s in package", name,
181 zip_path.c_str());
182 }
183
184 std::string buffer;
185 buffer.resize(entry.uncompressed_length);
186
187 int32_t ret =
188 ExtractToMemory(za, &entry, reinterpret_cast<uint8_t*>(&buffer[0]), buffer.size());
189 if (ret != 0) {
190 return ErrorAbort(state, kPackageExtractFileFailure,
191 "%s: Failed to extract entry \"%s\" (%zu bytes) to memory: %s", name,
192 zip_path.c_str(), buffer.size(), ErrorCodeString(ret));
193 }
194
195 return new Value(Value::Type::BLOB, buffer);
196 }
197 }
198
199 // patch_partition_check(target_partition, source_partition)
200 // Checks if the target and source partitions have the desired checksums to be patched. It returns
201 // directly, if the target partition already has the expected checksum. Otherwise it in turn
202 // checks the integrity of the source partition and the backup file on /cache.
203 //
204 // For example, patch_partition_check(
205 // "EMMC:/dev/block/boot:12342568:8aaacf187a6929d0e9c3e9e46ea7ff495b43424d",
206 // "EMMC:/dev/block/boot:12363048:06b0b16299dcefc94900efed01e0763ff644ffa4")
PatchPartitionCheckFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)207 Value* PatchPartitionCheckFn(const char* name, State* state,
208 const std::vector<std::unique_ptr<Expr>>& argv) {
209 if (argv.size() != 2) {
210 return ErrorAbort(state, kArgsParsingFailure,
211 "%s(): Invalid number of args (expected 2, got %zu)", name, argv.size());
212 }
213
214 std::vector<std::string> args;
215 if (!ReadArgs(state, argv, &args, 0, 2)) {
216 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
217 }
218
219 std::string err;
220 auto target = Partition::Parse(args[0], &err);
221 if (!target) {
222 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse target \"%s\": %s", name,
223 args[0].c_str(), err.c_str());
224 }
225
226 auto source = Partition::Parse(args[1], &err);
227 if (!source) {
228 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse source \"%s\": %s", name,
229 args[1].c_str(), err.c_str());
230 }
231
232 bool result = PatchPartitionCheck(target, source);
233 return StringValue(result ? "t" : "");
234 }
235
236 // patch_partition(target, source, patch)
237 // Applies the given patch to the source partition, and writes the result to the target partition.
238 //
239 // For example, patch_partition(
240 // "EMMC:/dev/block/boot:12342568:8aaacf187a6929d0e9c3e9e46ea7ff495b43424d",
241 // "EMMC:/dev/block/boot:12363048:06b0b16299dcefc94900efed01e0763ff644ffa4",
242 // package_extract_file("boot.img.p"))
PatchPartitionFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)243 Value* PatchPartitionFn(const char* name, State* state,
244 const std::vector<std::unique_ptr<Expr>>& argv) {
245 if (argv.size() != 3) {
246 return ErrorAbort(state, kArgsParsingFailure,
247 "%s(): Invalid number of args (expected 3, got %zu)", name, argv.size());
248 }
249
250 std::vector<std::string> args;
251 if (!ReadArgs(state, argv, &args, 0, 2)) {
252 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
253 }
254
255 std::string err;
256 auto target = Partition::Parse(args[0], &err);
257 if (!target) {
258 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse target \"%s\": %s", name,
259 args[0].c_str(), err.c_str());
260 }
261
262 auto source = Partition::Parse(args[1], &err);
263 if (!source) {
264 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse source \"%s\": %s", name,
265 args[1].c_str(), err.c_str());
266 }
267
268 std::vector<std::unique_ptr<Value>> values;
269 if (!ReadValueArgs(state, argv, &values, 2, 1) || values[0]->type != Value::Type::BLOB) {
270 return ErrorAbort(state, kArgsParsingFailure, "%s(): Invalid patch arg", name);
271 }
272
273 bool result = PatchPartition(target, source, *values[0], nullptr);
274 return StringValue(result ? "t" : "");
275 }
276
277 // mount(fs_type, partition_type, location, mount_point)
278 // mount(fs_type, partition_type, location, mount_point, mount_options)
279
280 // fs_type="ext4" partition_type="EMMC" location=device
MountFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)281 Value* MountFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
282 if (argv.size() != 4 && argv.size() != 5) {
283 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %zu", name,
284 argv.size());
285 }
286
287 std::vector<std::string> args;
288 if (!ReadArgs(state, argv, &args)) {
289 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
290 }
291 const std::string& fs_type = args[0];
292 const std::string& partition_type = args[1];
293 const std::string& location = args[2];
294 const std::string& mount_point = args[3];
295 std::string mount_options;
296
297 if (argv.size() == 5) {
298 mount_options = args[4];
299 }
300
301 if (fs_type.empty()) {
302 return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
303 }
304 if (partition_type.empty()) {
305 return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
306 name);
307 }
308 if (location.empty()) {
309 return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
310 }
311 if (mount_point.empty()) {
312 return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
313 name);
314 }
315
316 {
317 char* secontext = nullptr;
318
319 if (sehandle) {
320 selabel_lookup(sehandle, &secontext, mount_point.c_str(), 0755);
321 setfscreatecon(secontext);
322 }
323
324 mkdir(mount_point.c_str(), 0755);
325
326 if (secontext) {
327 freecon(secontext);
328 setfscreatecon(nullptr);
329 }
330 }
331
332 if (mount(location.c_str(), mount_point.c_str(), fs_type.c_str(),
333 MS_NOATIME | MS_NODEV | MS_NODIRATIME, mount_options.c_str()) < 0) {
334 uiPrintf(state, "%s: Failed to mount %s at %s: %s", name, location.c_str(), mount_point.c_str(),
335 strerror(errno));
336 return StringValue("");
337 }
338
339 return StringValue(mount_point);
340 }
341
342 // is_mounted(mount_point)
IsMountedFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)343 Value* IsMountedFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
344 if (argv.size() != 1) {
345 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
346 }
347
348 std::vector<std::string> args;
349 if (!ReadArgs(state, argv, &args)) {
350 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
351 }
352 const std::string& mount_point = args[0];
353 if (mount_point.empty()) {
354 return ErrorAbort(state, kArgsParsingFailure,
355 "mount_point argument to unmount() can't be empty");
356 }
357
358 scan_mounted_volumes();
359 MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point.c_str());
360 if (vol == nullptr) {
361 return StringValue("");
362 }
363
364 return StringValue(mount_point);
365 }
366
UnmountFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)367 Value* UnmountFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
368 if (argv.size() != 1) {
369 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
370 }
371 std::vector<std::string> args;
372 if (!ReadArgs(state, argv, &args)) {
373 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
374 }
375 const std::string& mount_point = args[0];
376 if (mount_point.empty()) {
377 return ErrorAbort(state, kArgsParsingFailure,
378 "mount_point argument to unmount() can't be empty");
379 }
380
381 scan_mounted_volumes();
382 MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point.c_str());
383 if (vol == nullptr) {
384 uiPrintf(state, "Failed to unmount %s: No such volume", mount_point.c_str());
385 return nullptr;
386 } else {
387 int ret = unmount_mounted_volume(vol);
388 if (ret != 0) {
389 uiPrintf(state, "Failed to unmount %s: %s", mount_point.c_str(), strerror(errno));
390 }
391 }
392
393 return StringValue(mount_point);
394 }
395
exec_cmd(const std::vector<std::string> & args)396 static int exec_cmd(const std::vector<std::string>& args) {
397 CHECK(!args.empty());
398 auto argv = StringVectorToNullTerminatedArray(args);
399
400 pid_t child;
401 if ((child = vfork()) == 0) {
402 execv(argv[0], argv.data());
403 _exit(EXIT_FAILURE);
404 }
405
406 int status;
407 waitpid(child, &status, 0);
408 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
409 LOG(ERROR) << args[0] << " failed with status " << WEXITSTATUS(status);
410 }
411 return WEXITSTATUS(status);
412 }
413
414 // format(fs_type, partition_type, location, fs_size, mount_point)
415 //
416 // fs_type="ext4" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location>
417 // fs_type="f2fs" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location>
418 // if fs_size == 0, then make fs uses the entire partition.
419 // if fs_size > 0, that is the size to use
420 // if fs_size < 0, then reserve that many bytes at the end of the partition (not for "f2fs")
FormatFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)421 Value* FormatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
422 if (argv.size() != 5) {
423 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %zu", name,
424 argv.size());
425 }
426
427 std::vector<std::string> args;
428 if (!ReadArgs(state, argv, &args)) {
429 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
430 }
431 const std::string& fs_type = args[0];
432 const std::string& partition_type = args[1];
433 const std::string& location = args[2];
434 const std::string& fs_size = args[3];
435 const std::string& mount_point = args[4];
436
437 if (fs_type.empty()) {
438 return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
439 }
440 if (partition_type.empty()) {
441 return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
442 name);
443 }
444 if (location.empty()) {
445 return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
446 }
447 if (mount_point.empty()) {
448 return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
449 name);
450 }
451
452 int64_t size;
453 if (!android::base::ParseInt(fs_size, &size)) {
454 return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse int in %s", name,
455 fs_size.c_str());
456 }
457
458 if (fs_type == "ext4") {
459 std::vector<std::string> mke2fs_args = {
460 "/system/bin/mke2fs", "-t", "ext4", "-b", "4096", location
461 };
462 if (size != 0) {
463 mke2fs_args.push_back(std::to_string(size / 4096LL));
464 }
465
466 if (auto status = exec_cmd(mke2fs_args); status != 0) {
467 LOG(ERROR) << name << ": mke2fs failed (" << status << ") on " << location;
468 return StringValue("");
469 }
470
471 if (auto status = exec_cmd({ "/system/bin/e2fsdroid", "-e", "-a", mount_point, location });
472 status != 0) {
473 LOG(ERROR) << name << ": e2fsdroid failed (" << status << ") on " << location;
474 return StringValue("");
475 }
476 return StringValue(location);
477 }
478
479 if (fs_type == "f2fs") {
480 if (size < 0) {
481 LOG(ERROR) << name << ": fs_size can't be negative for f2fs: " << fs_size;
482 return StringValue("");
483 }
484 std::vector<std::string> f2fs_args = {
485 "/system/bin/make_f2fs", "-g", "android", "-w", "512", location
486 };
487 if (size >= 512) {
488 f2fs_args.push_back(std::to_string(size / 512));
489 }
490 if (auto status = exec_cmd(f2fs_args); status != 0) {
491 LOG(ERROR) << name << ": make_f2fs failed (" << status << ") on " << location;
492 return StringValue("");
493 }
494
495 if (auto status = exec_cmd({ "/system/bin/sload_f2fs", "-t", mount_point, location });
496 status != 0) {
497 LOG(ERROR) << name << ": sload_f2fs failed (" << status << ") on " << location;
498 return StringValue("");
499 }
500
501 return StringValue(location);
502 }
503
504 LOG(ERROR) << name << ": unsupported fs_type \"" << fs_type << "\" partition_type \""
505 << partition_type << "\"";
506 return nullptr;
507 }
508
ShowProgressFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)509 Value* ShowProgressFn(const char* name, State* state,
510 const std::vector<std::unique_ptr<Expr>>& argv) {
511 if (argv.size() != 2) {
512 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
513 argv.size());
514 }
515
516 std::vector<std::string> args;
517 if (!ReadArgs(state, argv, &args)) {
518 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
519 }
520 const std::string& frac_str = args[0];
521 const std::string& sec_str = args[1];
522
523 double frac;
524 if (!android::base::ParseDouble(frac_str.c_str(), &frac)) {
525 return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse double in %s", name,
526 frac_str.c_str());
527 }
528 int sec;
529 if (!android::base::ParseInt(sec_str.c_str(), &sec)) {
530 return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse int in %s", name,
531 sec_str.c_str());
532 }
533
534 UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
535 fprintf(ui->cmd_pipe, "progress %f %d\n", frac, sec);
536
537 return StringValue(frac_str);
538 }
539
SetProgressFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)540 Value* SetProgressFn(const char* name, State* state,
541 const std::vector<std::unique_ptr<Expr>>& argv) {
542 if (argv.size() != 1) {
543 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
544 }
545
546 std::vector<std::string> args;
547 if (!ReadArgs(state, argv, &args)) {
548 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
549 }
550 const std::string& frac_str = args[0];
551
552 double frac;
553 if (!android::base::ParseDouble(frac_str.c_str(), &frac)) {
554 return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse double in %s", name,
555 frac_str.c_str());
556 }
557
558 UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
559 fprintf(ui->cmd_pipe, "set_progress %f\n", frac);
560
561 return StringValue(frac_str);
562 }
563
GetPropFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)564 Value* GetPropFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
565 if (argv.size() != 1) {
566 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
567 }
568 std::string key;
569 if (!Evaluate(state, argv[0], &key)) {
570 return nullptr;
571 }
572 std::string value = android::base::GetProperty(key, "");
573
574 return StringValue(value);
575 }
576
577 // file_getprop(file, key)
578 //
579 // interprets 'file' as a getprop-style file (key=value pairs, one
580 // per line. # comment lines, blank lines, lines without '=' ignored),
581 // and returns the value for 'key' (or "" if it isn't defined).
FileGetPropFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)582 Value* FileGetPropFn(const char* name, State* state,
583 const std::vector<std::unique_ptr<Expr>>& argv) {
584 if (argv.size() != 2) {
585 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
586 argv.size());
587 }
588
589 std::vector<std::string> args;
590 if (!ReadArgs(state, argv, &args)) {
591 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
592 }
593 const std::string& filename = args[0];
594 const std::string& key = args[1];
595
596 std::string buffer;
597 if (!android::base::ReadFileToString(filename, &buffer)) {
598 ErrorAbort(state, kFreadFailure, "%s: failed to read %s", name, filename.c_str());
599 return nullptr;
600 }
601
602 std::vector<std::string> lines = android::base::Split(buffer, "\n");
603 for (size_t i = 0; i < lines.size(); i++) {
604 std::string line = android::base::Trim(lines[i]);
605
606 // comment or blank line: skip to next line
607 if (line.empty() || line[0] == '#') {
608 continue;
609 }
610 size_t equal_pos = line.find('=');
611 if (equal_pos == std::string::npos) {
612 continue;
613 }
614
615 // trim whitespace between key and '='
616 std::string str = android::base::Trim(line.substr(0, equal_pos));
617
618 // not the key we're looking for
619 if (key != str) continue;
620
621 return StringValue(android::base::Trim(line.substr(equal_pos + 1)));
622 }
623
624 return StringValue("");
625 }
626
627 // apply_patch_space(bytes)
ApplyPatchSpaceFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)628 Value* ApplyPatchSpaceFn(const char* name, State* state,
629 const std::vector<std::unique_ptr<Expr>>& argv) {
630 if (argv.size() != 1) {
631 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 args, got %zu", name,
632 argv.size());
633 }
634 std::vector<std::string> args;
635 if (!ReadArgs(state, argv, &args)) {
636 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
637 }
638 const std::string& bytes_str = args[0];
639
640 size_t bytes;
641 if (!android::base::ParseUint(bytes_str.c_str(), &bytes)) {
642 return ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count", name,
643 bytes_str.c_str());
644 }
645
646 // Skip the cache size check if the update is a retry.
647 if (state->is_retry || CheckAndFreeSpaceOnCache(bytes)) {
648 return StringValue("t");
649 }
650 return StringValue("");
651 }
652
WipeCacheFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)653 Value* WipeCacheFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
654 if (!argv.empty()) {
655 return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name,
656 argv.size());
657 }
658 fprintf(static_cast<UpdaterInfo*>(state->cookie)->cmd_pipe, "wipe_cache\n");
659 return StringValue("t");
660 }
661
RunProgramFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)662 Value* RunProgramFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
663 if (argv.size() < 1) {
664 return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
665 }
666
667 std::vector<std::string> args;
668 if (!ReadArgs(state, argv, &args)) {
669 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
670 }
671
672 auto exec_args = StringVectorToNullTerminatedArray(args);
673 LOG(INFO) << "about to run program [" << exec_args[0] << "] with " << argv.size() << " args";
674
675 pid_t child = fork();
676 if (child == 0) {
677 execv(exec_args[0], exec_args.data());
678 PLOG(ERROR) << "run_program: execv failed";
679 _exit(EXIT_FAILURE);
680 }
681
682 int status;
683 waitpid(child, &status, 0);
684 if (WIFEXITED(status)) {
685 if (WEXITSTATUS(status) != 0) {
686 LOG(ERROR) << "run_program: child exited with status " << WEXITSTATUS(status);
687 }
688 } else if (WIFSIGNALED(status)) {
689 LOG(ERROR) << "run_program: child terminated by signal " << WTERMSIG(status);
690 }
691
692 return StringValue(std::to_string(status));
693 }
694
695 // read_file(filename)
696 // Reads a local file 'filename' and returns its contents as a string Value.
ReadFileFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)697 Value* ReadFileFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
698 if (argv.size() != 1) {
699 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
700 }
701
702 std::vector<std::string> args;
703 if (!ReadArgs(state, argv, &args)) {
704 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
705 }
706 const std::string& filename = args[0];
707
708 std::string contents;
709 if (android::base::ReadFileToString(filename, &contents)) {
710 return new Value(Value::Type::STRING, std::move(contents));
711 }
712
713 // Leave it to caller to handle the failure.
714 PLOG(ERROR) << name << ": Failed to read " << filename;
715 return StringValue("");
716 }
717
718 // write_value(value, filename)
719 // Writes 'value' to 'filename'.
720 // Example: write_value("960000", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq")
WriteValueFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)721 Value* WriteValueFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
722 if (argv.size() != 2) {
723 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
724 argv.size());
725 }
726
727 std::vector<std::string> args;
728 if (!ReadArgs(state, argv, &args)) {
729 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
730 }
731
732 const std::string& filename = args[1];
733 if (filename.empty()) {
734 return ErrorAbort(state, kArgsParsingFailure, "%s(): Filename cannot be empty", name);
735 }
736
737 const std::string& value = args[0];
738 if (!android::base::WriteStringToFile(value, filename)) {
739 PLOG(ERROR) << name << ": Failed to write to \"" << filename << "\"";
740 return StringValue("");
741 } else {
742 return StringValue("t");
743 }
744 }
745
746 // Immediately reboot the device. Recovery is not finished normally,
747 // so if you reboot into recovery it will re-start applying the
748 // current package (because nothing has cleared the copy of the
749 // arguments stored in the BCB).
750 //
751 // The argument is the partition name passed to the android reboot
752 // property. It can be "recovery" to boot from the recovery
753 // partition, or "" (empty string) to boot from the regular boot
754 // partition.
RebootNowFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)755 Value* RebootNowFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
756 if (argv.size() != 2) {
757 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
758 argv.size());
759 }
760
761 std::vector<std::string> args;
762 if (!ReadArgs(state, argv, &args)) {
763 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
764 }
765 const std::string& filename = args[0];
766 const std::string& property = args[1];
767
768 // Zero out the 'command' field of the bootloader message. Leave the rest intact.
769 bootloader_message boot;
770 std::string err;
771 if (!read_bootloader_message_from(&boot, filename, &err)) {
772 LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
773 return StringValue("");
774 }
775 memset(boot.command, 0, sizeof(boot.command));
776 if (!write_bootloader_message_to(boot, filename, &err)) {
777 LOG(ERROR) << name << "(): Failed to write to \"" << filename << "\": " << err;
778 return StringValue("");
779 }
780
781 reboot("reboot," + property);
782
783 sleep(5);
784 return ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name);
785 }
786
787 // Store a string value somewhere that future invocations of recovery
788 // can access it. This value is called the "stage" and can be used to
789 // drive packages that need to do reboots in the middle of
790 // installation and keep track of where they are in the multi-stage
791 // install.
792 //
793 // The first argument is the block device for the misc partition
794 // ("/misc" in the fstab), which is where this value is stored. The
795 // second argument is the string to store; it should not exceed 31
796 // bytes.
SetStageFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)797 Value* SetStageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
798 if (argv.size() != 2) {
799 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
800 argv.size());
801 }
802
803 std::vector<std::string> args;
804 if (!ReadArgs(state, argv, &args)) {
805 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
806 }
807 const std::string& filename = args[0];
808 const std::string& stagestr = args[1];
809
810 // Store this value in the misc partition, immediately after the
811 // bootloader message that the main recovery uses to save its
812 // arguments in case of the device restarting midway through
813 // package installation.
814 bootloader_message boot;
815 std::string err;
816 if (!read_bootloader_message_from(&boot, filename, &err)) {
817 LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
818 return StringValue("");
819 }
820 strlcpy(boot.stage, stagestr.c_str(), sizeof(boot.stage));
821 if (!write_bootloader_message_to(boot, filename, &err)) {
822 LOG(ERROR) << name << "(): Failed to write to \"" << filename << "\": " << err;
823 return StringValue("");
824 }
825
826 return StringValue(filename);
827 }
828
829 // Return the value most recently saved with SetStageFn. The argument
830 // is the block device for the misc partition.
GetStageFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)831 Value* GetStageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
832 if (argv.size() != 1) {
833 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
834 }
835
836 std::vector<std::string> args;
837 if (!ReadArgs(state, argv, &args)) {
838 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
839 }
840 const std::string& filename = args[0];
841
842 bootloader_message boot;
843 std::string err;
844 if (!read_bootloader_message_from(&boot, filename, &err)) {
845 LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
846 return StringValue("");
847 }
848
849 return StringValue(boot.stage);
850 }
851
WipeBlockDeviceFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)852 Value* WipeBlockDeviceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
853 if (argv.size() != 2) {
854 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
855 argv.size());
856 }
857
858 std::vector<std::string> args;
859 if (!ReadArgs(state, argv, &args)) {
860 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
861 }
862 const std::string& filename = args[0];
863 const std::string& len_str = args[1];
864
865 size_t len;
866 if (!android::base::ParseUint(len_str.c_str(), &len)) {
867 return nullptr;
868 }
869 android::base::unique_fd fd(open(filename.c_str(), O_WRONLY));
870 if (fd == -1) {
871 PLOG(ERROR) << "Failed to open " << filename;
872 return StringValue("");
873 }
874
875 // The wipe_block_device function in ext4_utils returns 0 on success and 1
876 // for failure.
877 int status = wipe_block_device(fd, len);
878 return StringValue((status == 0) ? "t" : "");
879 }
880
EnableRebootFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)881 Value* EnableRebootFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
882 if (!argv.empty()) {
883 return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name,
884 argv.size());
885 }
886 UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
887 fprintf(ui->cmd_pipe, "enable_reboot\n");
888 return StringValue("t");
889 }
890
Tune2FsFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)891 Value* Tune2FsFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
892 if (argv.empty()) {
893 return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %zu", name, argv.size());
894 }
895
896 std::vector<std::string> args;
897 if (!ReadArgs(state, argv, &args)) {
898 return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name);
899 }
900
901 // tune2fs expects the program name as its first arg.
902 args.insert(args.begin(), "tune2fs");
903 auto tune2fs_args = StringVectorToNullTerminatedArray(args);
904
905 // tune2fs changes the filesystem parameters on an ext2 filesystem; it returns 0 on success.
906 if (auto result = tune2fs_main(tune2fs_args.size() - 1, tune2fs_args.data()); result != 0) {
907 return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", name, result);
908 }
909 return StringValue("t");
910 }
911
RegisterInstallFunctions()912 void RegisterInstallFunctions() {
913 RegisterFunction("mount", MountFn);
914 RegisterFunction("is_mounted", IsMountedFn);
915 RegisterFunction("unmount", UnmountFn);
916 RegisterFunction("format", FormatFn);
917 RegisterFunction("show_progress", ShowProgressFn);
918 RegisterFunction("set_progress", SetProgressFn);
919 RegisterFunction("package_extract_file", PackageExtractFileFn);
920
921 RegisterFunction("getprop", GetPropFn);
922 RegisterFunction("file_getprop", FileGetPropFn);
923
924 RegisterFunction("apply_patch_space", ApplyPatchSpaceFn);
925 RegisterFunction("patch_partition", PatchPartitionFn);
926 RegisterFunction("patch_partition_check", PatchPartitionCheckFn);
927
928 RegisterFunction("wipe_block_device", WipeBlockDeviceFn);
929
930 RegisterFunction("read_file", ReadFileFn);
931 RegisterFunction("write_value", WriteValueFn);
932
933 RegisterFunction("wipe_cache", WipeCacheFn);
934
935 RegisterFunction("ui_print", UIPrintFn);
936
937 RegisterFunction("run_program", RunProgramFn);
938
939 RegisterFunction("reboot_now", RebootNowFn);
940 RegisterFunction("get_stage", GetStageFn);
941 RegisterFunction("set_stage", SetStageFn);
942
943 RegisterFunction("enable_reboot", EnableRebootFn);
944 RegisterFunction("tune2fs", Tune2FsFn);
945 }
946