Home | History | Annotate | Download | only in uncrypt
      1 /*
      2  * Copyright (C) 2014 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 // This program takes a file on an ext4 filesystem and produces a list
     18 // of the blocks that file occupies, which enables the file contents
     19 // to be read directly from the block device without mounting the
     20 // filesystem.
     21 //
     22 // If the filesystem is using an encrypted block device, it will also
     23 // read the file and rewrite it to the same blocks of the underlying
     24 // (unencrypted) block device, so the file contents can be read
     25 // without the need for the decryption key.
     26 //
     27 // The output of this program is a "block map" which looks like this:
     28 //
     29 //     /dev/block/platform/msm_sdcc.1/by-name/userdata     # block device
     30 //     49652 4096                        # file size in bytes, block size
     31 //     3                                 # count of block ranges
     32 //     1000 1008                         # block range 0
     33 //     2100 2102                         # ... block range 1
     34 //     30 33                             # ... block range 2
     35 //
     36 // Each block range represents a half-open interval; the line "30 33"
     37 // reprents the blocks [30, 31, 32].
     38 //
     39 // Recovery can take this block map file and retrieve the underlying
     40 // file data to use as an update package.
     41 
     42 /**
     43  * In addition to the uncrypt work, uncrypt also takes care of setting and
     44  * clearing the bootloader control block (BCB) at /misc partition.
     45  *
     46  * uncrypt is triggered as init services on demand. It uses socket to
     47  * communicate with its caller (i.e. system_server). The socket is managed by
     48  * init (i.e. created prior to the service starts, and destroyed when uncrypt
     49  * exits).
     50  *
     51  * Below is the uncrypt protocol.
     52  *
     53  *    a. caller                 b. init                    c. uncrypt
     54  * ---------------            ------------               --------------
     55  *  a1. ctl.start:
     56  *    setup-bcb /
     57  *    clear-bcb /
     58  *    uncrypt
     59  *
     60  *                         b2. create socket at
     61  *                           /dev/socket/uncrypt
     62  *
     63  *                                                   c3. listen and accept
     64  *
     65  *  a4. send a 4-byte int
     66  *    (message length)
     67  *                                                   c5. receive message length
     68  *  a6. send message
     69  *                                                   c7. receive message
     70  *                                                   c8. <do the work; may send
     71  *                                                      the progress>
     72  *  a9. <may handle progress>
     73  *                                                   c10. <upon finishing>
     74  *                                                     send "100" or "-1"
     75  *
     76  *  a11. receive status code
     77  *  a12. send a 4-byte int to
     78  *    ack the receive of the
     79  *    final status code
     80  *                                                   c13. receive and exit
     81  *
     82  *                          b14. destroy the socket
     83  *
     84  * Note that a12 and c13 are necessary to ensure a11 happens before the socket
     85  * gets destroyed in b14.
     86  */
     87 
     88 #include <arpa/inet.h>
     89 #include <errno.h>
     90 #include <fcntl.h>
     91 #include <inttypes.h>
     92 #include <libgen.h>
     93 #include <linux/fs.h>
     94 #include <stdarg.h>
     95 #include <stdio.h>
     96 #include <stdlib.h>
     97 #include <string.h>
     98 #include <sys/mman.h>
     99 #include <sys/socket.h>
    100 #include <sys/stat.h>
    101 #include <sys/types.h>
    102 #include <unistd.h>
    103 
    104 #include <algorithm>
    105 #include <memory>
    106 #include <vector>
    107 
    108 #include <android-base/file.h>
    109 #include <android-base/logging.h>
    110 #include <android-base/stringprintf.h>
    111 #include <android-base/strings.h>
    112 #include <bootloader_message_writer.h>
    113 #include <cutils/android_reboot.h>
    114 #include <cutils/properties.h>
    115 #include <cutils/sockets.h>
    116 #include <fs_mgr.h>
    117 
    118 #define LOG_TAG "uncrypt"
    119 #include <log/log.h>
    120 
    121 #include "unique_fd.h"
    122 
    123 #define WINDOW_SIZE 5
    124 
    125 // uncrypt provides three services: SETUP_BCB, CLEAR_BCB and UNCRYPT.
    126 //
    127 // SETUP_BCB and CLEAR_BCB services use socket communication and do not rely
    128 // on /cache partitions. They will handle requests to reboot into recovery
    129 // (for applying updates for non-A/B devices, or factory resets for all
    130 // devices).
    131 //
    132 // UNCRYPT service still needs files on /cache partition (UNCRYPT_PATH_FILE
    133 // and CACHE_BLOCK_MAP). It will be working (and needed) only for non-A/B
    134 // devices, on which /cache partitions always exist.
    135 static const std::string CACHE_BLOCK_MAP = "/cache/recovery/block.map";
    136 static const std::string UNCRYPT_PATH_FILE = "/cache/recovery/uncrypt_file";
    137 static const std::string UNCRYPT_SOCKET = "uncrypt";
    138 
    139 static struct fstab* fstab = nullptr;
    140 
    141 static int write_at_offset(unsigned char* buffer, size_t size, int wfd, off64_t offset) {
    142     if (TEMP_FAILURE_RETRY(lseek64(wfd, offset, SEEK_SET)) == -1) {
    143         ALOGE("error seeking to offset %" PRId64 ": %s", offset, strerror(errno));
    144         return -1;
    145     }
    146     if (!android::base::WriteFully(wfd, buffer, size)) {
    147         ALOGE("error writing offset %" PRId64 ": %s", offset, strerror(errno));
    148         return -1;
    149     }
    150     return 0;
    151 }
    152 
    153 static void add_block_to_ranges(std::vector<int>& ranges, int new_block) {
    154     if (!ranges.empty() && new_block == ranges.back()) {
    155         // If the new block comes immediately after the current range,
    156         // all we have to do is extend the current range.
    157         ++ranges.back();
    158     } else {
    159         // We need to start a new range.
    160         ranges.push_back(new_block);
    161         ranges.push_back(new_block + 1);
    162     }
    163 }
    164 
    165 static struct fstab* read_fstab() {
    166     fstab = NULL;
    167 
    168     // The fstab path is always "/fstab.${ro.hardware}".
    169     char fstab_path[PATH_MAX+1] = "/fstab.";
    170     if (!property_get("ro.hardware", fstab_path+strlen(fstab_path), "")) {
    171         ALOGE("failed to get ro.hardware");
    172         return NULL;
    173     }
    174 
    175     fstab = fs_mgr_read_fstab(fstab_path);
    176     if (!fstab) {
    177         ALOGE("failed to read %s", fstab_path);
    178         return NULL;
    179     }
    180 
    181     return fstab;
    182 }
    183 
    184 static const char* find_block_device(const char* path, bool* encryptable, bool* encrypted) {
    185     // Look for a volume whose mount point is the prefix of path and
    186     // return its block device.  Set encrypted if it's currently
    187     // encrypted.
    188     for (int i = 0; i < fstab->num_entries; ++i) {
    189         struct fstab_rec* v = &fstab->recs[i];
    190         if (!v->mount_point) {
    191             continue;
    192         }
    193         int len = strlen(v->mount_point);
    194         if (strncmp(path, v->mount_point, len) == 0 &&
    195             (path[len] == '/' || path[len] == 0)) {
    196             *encrypted = false;
    197             *encryptable = false;
    198             if (fs_mgr_is_encryptable(v) || fs_mgr_is_file_encrypted(v)) {
    199                 *encryptable = true;
    200                 char buffer[PROPERTY_VALUE_MAX+1];
    201                 if (property_get("ro.crypto.state", buffer, "") &&
    202                     strcmp(buffer, "encrypted") == 0) {
    203                     *encrypted = true;
    204                 }
    205             }
    206             return v->blk_device;
    207         }
    208     }
    209 
    210     return NULL;
    211 }
    212 
    213 static bool write_status_to_socket(int status, int socket) {
    214     int status_out = htonl(status);
    215     return android::base::WriteFully(socket, &status_out, sizeof(int));
    216 }
    217 
    218 // Parse uncrypt_file to find the update package name.
    219 static bool find_uncrypt_package(const std::string& uncrypt_path_file, std::string* package_name) {
    220     CHECK(package_name != nullptr);
    221     std::string uncrypt_path;
    222     if (!android::base::ReadFileToString(uncrypt_path_file, &uncrypt_path)) {
    223         ALOGE("failed to open \"%s\": %s", uncrypt_path_file.c_str(), strerror(errno));
    224         return false;
    225     }
    226 
    227     // Remove the trailing '\n' if present.
    228     *package_name = android::base::Trim(uncrypt_path);
    229     return true;
    230 }
    231 
    232 static int produce_block_map(const char* path, const char* map_file, const char* blk_dev,
    233                              bool encrypted, int socket) {
    234     std::string err;
    235     if (!android::base::RemoveFileIfExists(map_file, &err)) {
    236         ALOGE("failed to remove the existing map file %s: %s", map_file, err.c_str());
    237         return -1;
    238     }
    239     std::string tmp_map_file = std::string(map_file) + ".tmp";
    240     unique_fd mapfd(open(tmp_map_file.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR));
    241     if (!mapfd) {
    242         ALOGE("failed to open %s: %s\n", tmp_map_file.c_str(), strerror(errno));
    243         return -1;
    244     }
    245 
    246     // Make sure we can write to the socket.
    247     if (!write_status_to_socket(0, socket)) {
    248         ALOGE("failed to write to socket %d\n", socket);
    249         return -1;
    250     }
    251 
    252     struct stat sb;
    253     if (stat(path, &sb) != 0) {
    254         ALOGE("failed to stat %s", path);
    255         return -1;
    256     }
    257 
    258     ALOGI(" block size: %ld bytes", static_cast<long>(sb.st_blksize));
    259 
    260     int blocks = ((sb.st_size-1) / sb.st_blksize) + 1;
    261     ALOGI("  file size: %" PRId64 " bytes, %d blocks", sb.st_size, blocks);
    262 
    263     std::vector<int> ranges;
    264 
    265     std::string s = android::base::StringPrintf("%s\n%" PRId64 " %ld\n",
    266                        blk_dev, sb.st_size, static_cast<long>(sb.st_blksize));
    267     if (!android::base::WriteStringToFd(s, mapfd.get())) {
    268         ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno));
    269         return -1;
    270     }
    271 
    272     std::vector<std::vector<unsigned char>> buffers;
    273     if (encrypted) {
    274         buffers.resize(WINDOW_SIZE, std::vector<unsigned char>(sb.st_blksize));
    275     }
    276     int head_block = 0;
    277     int head = 0, tail = 0;
    278 
    279     unique_fd fd(open(path, O_RDONLY));
    280     if (!fd) {
    281         ALOGE("failed to open %s for reading: %s", path, strerror(errno));
    282         return -1;
    283     }
    284 
    285     unique_fd wfd(-1);
    286     if (encrypted) {
    287         wfd = open(blk_dev, O_WRONLY);
    288         if (!wfd) {
    289             ALOGE("failed to open fd for writing: %s", strerror(errno));
    290             return -1;
    291         }
    292     }
    293 
    294     off64_t pos = 0;
    295     int last_progress = 0;
    296     while (pos < sb.st_size) {
    297         // Update the status file, progress must be between [0, 99].
    298         int progress = static_cast<int>(100 * (double(pos) / double(sb.st_size)));
    299         if (progress > last_progress) {
    300             last_progress = progress;
    301             write_status_to_socket(progress, socket);
    302         }
    303 
    304         if ((tail+1) % WINDOW_SIZE == head) {
    305             // write out head buffer
    306             int block = head_block;
    307             if (ioctl(fd.get(), FIBMAP, &block) != 0) {
    308                 ALOGE("failed to find block %d", head_block);
    309                 return -1;
    310             }
    311             add_block_to_ranges(ranges, block);
    312             if (encrypted) {
    313                 if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd.get(),
    314                         static_cast<off64_t>(sb.st_blksize) * block) != 0) {
    315                     return -1;
    316                 }
    317             }
    318             head = (head + 1) % WINDOW_SIZE;
    319             ++head_block;
    320         }
    321 
    322         // read next block to tail
    323         if (encrypted) {
    324             size_t to_read = static_cast<size_t>(
    325                     std::min(static_cast<off64_t>(sb.st_blksize), sb.st_size - pos));
    326             if (!android::base::ReadFully(fd.get(), buffers[tail].data(), to_read)) {
    327                 ALOGE("failed to read: %s", strerror(errno));
    328                 return -1;
    329             }
    330             pos += to_read;
    331         } else {
    332             // If we're not encrypting; we don't need to actually read
    333             // anything, just skip pos forward as if we'd read a
    334             // block.
    335             pos += sb.st_blksize;
    336         }
    337         tail = (tail+1) % WINDOW_SIZE;
    338     }
    339 
    340     while (head != tail) {
    341         // write out head buffer
    342         int block = head_block;
    343         if (ioctl(fd.get(), FIBMAP, &block) != 0) {
    344             ALOGE("failed to find block %d", head_block);
    345             return -1;
    346         }
    347         add_block_to_ranges(ranges, block);
    348         if (encrypted) {
    349             if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd.get(),
    350                     static_cast<off64_t>(sb.st_blksize) * block) != 0) {
    351                 return -1;
    352             }
    353         }
    354         head = (head + 1) % WINDOW_SIZE;
    355         ++head_block;
    356     }
    357 
    358     if (!android::base::WriteStringToFd(
    359             android::base::StringPrintf("%zu\n", ranges.size() / 2), mapfd.get())) {
    360         ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno));
    361         return -1;
    362     }
    363     for (size_t i = 0; i < ranges.size(); i += 2) {
    364         if (!android::base::WriteStringToFd(
    365                 android::base::StringPrintf("%d %d\n", ranges[i], ranges[i+1]), mapfd.get())) {
    366             ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno));
    367             return -1;
    368         }
    369     }
    370 
    371     if (fsync(mapfd.get()) == -1) {
    372         ALOGE("failed to fsync \"%s\": %s", tmp_map_file.c_str(), strerror(errno));
    373         return -1;
    374     }
    375     if (close(mapfd.get()) == -1) {
    376         ALOGE("failed to close %s: %s", tmp_map_file.c_str(), strerror(errno));
    377         return -1;
    378     }
    379     mapfd = -1;
    380 
    381     if (encrypted) {
    382         if (fsync(wfd.get()) == -1) {
    383             ALOGE("failed to fsync \"%s\": %s", blk_dev, strerror(errno));
    384             return -1;
    385         }
    386         if (close(wfd.get()) == -1) {
    387             ALOGE("failed to close %s: %s", blk_dev, strerror(errno));
    388             return -1;
    389         }
    390         wfd = -1;
    391     }
    392 
    393     if (rename(tmp_map_file.c_str(), map_file) == -1) {
    394         ALOGE("failed to rename %s to %s: %s", tmp_map_file.c_str(), map_file, strerror(errno));
    395         return -1;
    396     }
    397     // Sync dir to make rename() result written to disk.
    398     std::string file_name = map_file;
    399     std::string dir_name = dirname(&file_name[0]);
    400     unique_fd dfd(open(dir_name.c_str(), O_RDONLY | O_DIRECTORY));
    401     if (!dfd) {
    402         ALOGE("failed to open dir %s: %s", dir_name.c_str(), strerror(errno));
    403         return -1;
    404     }
    405     if (fsync(dfd.get()) == -1) {
    406         ALOGE("failed to fsync %s: %s", dir_name.c_str(), strerror(errno));
    407         return -1;
    408     }
    409     if (close(dfd.get()) == -1) {
    410         ALOGE("failed to close %s: %s", dir_name.c_str(), strerror(errno));
    411         return -1;
    412     }
    413     dfd = -1;
    414     return 0;
    415 }
    416 
    417 static int uncrypt(const char* input_path, const char* map_file, const int socket) {
    418     ALOGI("update package is \"%s\"", input_path);
    419 
    420     // Turn the name of the file we're supposed to convert into an
    421     // absolute path, so we can find what filesystem it's on.
    422     char path[PATH_MAX+1];
    423     if (realpath(input_path, path) == NULL) {
    424         ALOGE("failed to convert \"%s\" to absolute path: %s", input_path, strerror(errno));
    425         return 1;
    426     }
    427 
    428     bool encryptable;
    429     bool encrypted;
    430     const char* blk_dev = find_block_device(path, &encryptable, &encrypted);
    431     if (blk_dev == NULL) {
    432         ALOGE("failed to find block device for %s", path);
    433         return 1;
    434     }
    435 
    436     // If the filesystem it's on isn't encrypted, we only produce the
    437     // block map, we don't rewrite the file contents (it would be
    438     // pointless to do so).
    439     ALOGI("encryptable: %s", encryptable ? "yes" : "no");
    440     ALOGI("  encrypted: %s", encrypted ? "yes" : "no");
    441 
    442     // Recovery supports installing packages from 3 paths: /cache,
    443     // /data, and /sdcard.  (On a particular device, other locations
    444     // may work, but those are three we actually expect.)
    445     //
    446     // On /data we want to convert the file to a block map so that we
    447     // can read the package without mounting the partition.  On /cache
    448     // and /sdcard we leave the file alone.
    449     if (strncmp(path, "/data/", 6) == 0) {
    450         ALOGI("writing block map %s", map_file);
    451         if (produce_block_map(path, map_file, blk_dev, encrypted, socket) != 0) {
    452             return 1;
    453         }
    454     }
    455 
    456     return 0;
    457 }
    458 
    459 static bool uncrypt_wrapper(const char* input_path, const char* map_file, const int socket) {
    460     std::string package;
    461     if (input_path == nullptr) {
    462         if (!find_uncrypt_package(UNCRYPT_PATH_FILE, &package)) {
    463             write_status_to_socket(-1, socket);
    464             return false;
    465         }
    466         input_path = package.c_str();
    467     }
    468     CHECK(map_file != nullptr);
    469     int status = uncrypt(input_path, map_file, socket);
    470     if (status != 0) {
    471         write_status_to_socket(-1, socket);
    472         return false;
    473     }
    474     write_status_to_socket(100, socket);
    475     return true;
    476 }
    477 
    478 static bool clear_bcb(const int socket) {
    479     std::string err;
    480     if (!clear_bootloader_message(&err)) {
    481         ALOGE("failed to clear bootloader message: %s", err.c_str());
    482         write_status_to_socket(-1, socket);
    483         return false;
    484     }
    485     write_status_to_socket(100, socket);
    486     return true;
    487 }
    488 
    489 static bool setup_bcb(const int socket) {
    490     // c5. receive message length
    491     int length;
    492     if (!android::base::ReadFully(socket, &length, 4)) {
    493         ALOGE("failed to read the length: %s", strerror(errno));
    494         return false;
    495     }
    496     length = ntohl(length);
    497 
    498     // c7. receive message
    499     std::string content;
    500     content.resize(length);
    501     if (!android::base::ReadFully(socket, &content[0], length)) {
    502         ALOGE("failed to read the length: %s", strerror(errno));
    503         return false;
    504     }
    505     ALOGI("  received command: [%s] (%zu)", content.c_str(), content.size());
    506 
    507     // c8. setup the bcb command
    508     std::string err;
    509     if (!write_bootloader_message({content}, &err)) {
    510         ALOGE("failed to set bootloader message: %s", err.c_str());
    511         write_status_to_socket(-1, socket);
    512         return false;
    513     }
    514     // c10. send "100" status
    515     write_status_to_socket(100, socket);
    516     return true;
    517 }
    518 
    519 static void usage(const char* exename) {
    520     fprintf(stderr, "Usage of %s:\n", exename);
    521     fprintf(stderr, "%s [<package_path> <map_file>]  Uncrypt ota package.\n", exename);
    522     fprintf(stderr, "%s --clear-bcb  Clear BCB data in misc partition.\n", exename);
    523     fprintf(stderr, "%s --setup-bcb  Setup BCB data by command file.\n", exename);
    524 }
    525 
    526 int main(int argc, char** argv) {
    527     enum { UNCRYPT, SETUP_BCB, CLEAR_BCB } action;
    528     const char* input_path = nullptr;
    529     const char* map_file = CACHE_BLOCK_MAP.c_str();
    530 
    531     if (argc == 2 && strcmp(argv[1], "--clear-bcb") == 0) {
    532         action = CLEAR_BCB;
    533     } else if (argc == 2 && strcmp(argv[1], "--setup-bcb") == 0) {
    534         action = SETUP_BCB;
    535     } else if (argc == 1) {
    536         action = UNCRYPT;
    537     } else if (argc == 3) {
    538         input_path = argv[1];
    539         map_file = argv[2];
    540         action = UNCRYPT;
    541     } else {
    542         usage(argv[0]);
    543         return 2;
    544     }
    545 
    546     if ((fstab = read_fstab()) == nullptr) {
    547         return 1;
    548     }
    549 
    550     // c3. The socket is created by init when starting the service. uncrypt
    551     // will use the socket to communicate with its caller.
    552     unique_fd service_socket(android_get_control_socket(UNCRYPT_SOCKET.c_str()));
    553     if (!service_socket) {
    554         ALOGE("failed to open socket \"%s\": %s", UNCRYPT_SOCKET.c_str(), strerror(errno));
    555         return 1;
    556     }
    557     fcntl(service_socket.get(), F_SETFD, FD_CLOEXEC);
    558 
    559     if (listen(service_socket.get(), 1) == -1) {
    560         ALOGE("failed to listen on socket %d: %s", service_socket.get(), strerror(errno));
    561         return 1;
    562     }
    563 
    564     unique_fd socket_fd(accept4(service_socket.get(), nullptr, nullptr, SOCK_CLOEXEC));
    565     if (!socket_fd) {
    566         ALOGE("failed to accept on socket %d: %s", service_socket.get(), strerror(errno));
    567         return 1;
    568     }
    569 
    570     bool success = false;
    571     switch (action) {
    572         case UNCRYPT:
    573             success = uncrypt_wrapper(input_path, map_file, socket_fd.get());
    574             break;
    575         case SETUP_BCB:
    576             success = setup_bcb(socket_fd.get());
    577             break;
    578         case CLEAR_BCB:
    579             success = clear_bcb(socket_fd.get());
    580             break;
    581         default:  // Should never happen.
    582             ALOGE("Invalid uncrypt action code: %d", action);
    583             return 1;
    584     }
    585 
    586     // c13. Read a 4-byte code from the client before uncrypt exits. This is to
    587     // ensure the client to receive the last status code before the socket gets
    588     // destroyed.
    589     int code;
    590     if (android::base::ReadFully(socket_fd.get(), &code, 4)) {
    591         ALOGI("  received %d, exiting now", code);
    592     } else {
    593         ALOGE("failed to read the code: %s", strerror(errno));
    594     }
    595     return success ? 0 : 1;
    596 }
    597