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/bootloader_message.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 "error_code.h"
    122 #include "unique_fd.h"
    123 
    124 #define WINDOW_SIZE 5
    125 
    126 // uncrypt provides three services: SETUP_BCB, CLEAR_BCB and UNCRYPT.
    127 //
    128 // SETUP_BCB and CLEAR_BCB services use socket communication and do not rely
    129 // on /cache partitions. They will handle requests to reboot into recovery
    130 // (for applying updates for non-A/B devices, or factory resets for all
    131 // devices).
    132 //
    133 // UNCRYPT service still needs files on /cache partition (UNCRYPT_PATH_FILE
    134 // and CACHE_BLOCK_MAP). It will be working (and needed) only for non-A/B
    135 // devices, on which /cache partitions always exist.
    136 static const std::string CACHE_BLOCK_MAP = "/cache/recovery/block.map";
    137 static const std::string UNCRYPT_PATH_FILE = "/cache/recovery/uncrypt_file";
    138 static const std::string UNCRYPT_STATUS = "/cache/recovery/uncrypt_status";
    139 static const std::string UNCRYPT_SOCKET = "uncrypt";
    140 
    141 static struct fstab* fstab = nullptr;
    142 
    143 static int write_at_offset(unsigned char* buffer, size_t size, int wfd, off64_t offset) {
    144     if (TEMP_FAILURE_RETRY(lseek64(wfd, offset, SEEK_SET)) == -1) {
    145         ALOGE("error seeking to offset %" PRId64 ": %s", offset, strerror(errno));
    146         return -1;
    147     }
    148     if (!android::base::WriteFully(wfd, buffer, size)) {
    149         ALOGE("error writing offset %" PRId64 ": %s", offset, strerror(errno));
    150         return -1;
    151     }
    152     return 0;
    153 }
    154 
    155 static void add_block_to_ranges(std::vector<int>& ranges, int new_block) {
    156     if (!ranges.empty() && new_block == ranges.back()) {
    157         // If the new block comes immediately after the current range,
    158         // all we have to do is extend the current range.
    159         ++ranges.back();
    160     } else {
    161         // We need to start a new range.
    162         ranges.push_back(new_block);
    163         ranges.push_back(new_block + 1);
    164     }
    165 }
    166 
    167 static struct fstab* read_fstab() {
    168     fstab = NULL;
    169 
    170     // The fstab path is always "/fstab.${ro.hardware}".
    171     char fstab_path[PATH_MAX+1] = "/fstab.";
    172     if (!property_get("ro.hardware", fstab_path+strlen(fstab_path), "")) {
    173         ALOGE("failed to get ro.hardware");
    174         return NULL;
    175     }
    176 
    177     fstab = fs_mgr_read_fstab(fstab_path);
    178     if (!fstab) {
    179         ALOGE("failed to read %s", fstab_path);
    180         return NULL;
    181     }
    182 
    183     return fstab;
    184 }
    185 
    186 static const char* find_block_device(const char* path, bool* encryptable, bool* encrypted) {
    187     // Look for a volume whose mount point is the prefix of path and
    188     // return its block device.  Set encrypted if it's currently
    189     // encrypted.
    190     for (int i = 0; i < fstab->num_entries; ++i) {
    191         struct fstab_rec* v = &fstab->recs[i];
    192         if (!v->mount_point) {
    193             continue;
    194         }
    195         int len = strlen(v->mount_point);
    196         if (strncmp(path, v->mount_point, len) == 0 &&
    197             (path[len] == '/' || path[len] == 0)) {
    198             *encrypted = false;
    199             *encryptable = false;
    200             if (fs_mgr_is_encryptable(v) || fs_mgr_is_file_encrypted(v)) {
    201                 *encryptable = true;
    202                 char buffer[PROPERTY_VALUE_MAX+1];
    203                 if (property_get("ro.crypto.state", buffer, "") &&
    204                     strcmp(buffer, "encrypted") == 0) {
    205                     *encrypted = true;
    206                 }
    207             }
    208             return v->blk_device;
    209         }
    210     }
    211 
    212     return NULL;
    213 }
    214 
    215 static bool write_status_to_socket(int status, int socket) {
    216     int status_out = htonl(status);
    217     return android::base::WriteFully(socket, &status_out, sizeof(int));
    218 }
    219 
    220 // Parse uncrypt_file to find the update package name.
    221 static bool find_uncrypt_package(const std::string& uncrypt_path_file, std::string* package_name) {
    222     CHECK(package_name != nullptr);
    223     std::string uncrypt_path;
    224     if (!android::base::ReadFileToString(uncrypt_path_file, &uncrypt_path)) {
    225         ALOGE("failed to open \"%s\": %s", uncrypt_path_file.c_str(), strerror(errno));
    226         return false;
    227     }
    228 
    229     // Remove the trailing '\n' if present.
    230     *package_name = android::base::Trim(uncrypt_path);
    231     return true;
    232 }
    233 
    234 static int produce_block_map(const char* path, const char* map_file, const char* blk_dev,
    235                              bool encrypted, int socket) {
    236     std::string err;
    237     if (!android::base::RemoveFileIfExists(map_file, &err)) {
    238         ALOGE("failed to remove the existing map file %s: %s", map_file, err.c_str());
    239         return kUncryptFileRemoveError;
    240     }
    241     std::string tmp_map_file = std::string(map_file) + ".tmp";
    242     unique_fd mapfd(open(tmp_map_file.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR));
    243     if (!mapfd) {
    244         ALOGE("failed to open %s: %s\n", tmp_map_file.c_str(), strerror(errno));
    245         return kUncryptFileOpenError;
    246     }
    247 
    248     // Make sure we can write to the socket.
    249     if (!write_status_to_socket(0, socket)) {
    250         ALOGE("failed to write to socket %d\n", socket);
    251         return kUncryptSocketWriteError;
    252     }
    253 
    254     struct stat sb;
    255     if (stat(path, &sb) != 0) {
    256         ALOGE("failed to stat %s", path);
    257         return kUncryptFileStatError;
    258     }
    259 
    260     ALOGI(" block size: %ld bytes", static_cast<long>(sb.st_blksize));
    261 
    262     int blocks = ((sb.st_size-1) / sb.st_blksize) + 1;
    263     ALOGI("  file size: %" PRId64 " bytes, %d blocks", sb.st_size, blocks);
    264 
    265     std::vector<int> ranges;
    266 
    267     std::string s = android::base::StringPrintf("%s\n%" PRId64 " %ld\n",
    268                        blk_dev, sb.st_size, static_cast<long>(sb.st_blksize));
    269     if (!android::base::WriteStringToFd(s, mapfd.get())) {
    270         ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno));
    271         return kUncryptWriteError;
    272     }
    273 
    274     std::vector<std::vector<unsigned char>> buffers;
    275     if (encrypted) {
    276         buffers.resize(WINDOW_SIZE, std::vector<unsigned char>(sb.st_blksize));
    277     }
    278     int head_block = 0;
    279     int head = 0, tail = 0;
    280 
    281     unique_fd fd(open(path, O_RDONLY));
    282     if (!fd) {
    283         ALOGE("failed to open %s for reading: %s", path, strerror(errno));
    284         return kUncryptFileOpenError;
    285     }
    286 
    287     unique_fd wfd(-1);
    288     if (encrypted) {
    289         wfd = open(blk_dev, O_WRONLY);
    290         if (!wfd) {
    291             ALOGE("failed to open fd for writing: %s", strerror(errno));
    292             return kUncryptBlockOpenError;
    293         }
    294     }
    295 
    296     off64_t pos = 0;
    297     int last_progress = 0;
    298     while (pos < sb.st_size) {
    299         // Update the status file, progress must be between [0, 99].
    300         int progress = static_cast<int>(100 * (double(pos) / double(sb.st_size)));
    301         if (progress > last_progress) {
    302             last_progress = progress;
    303             write_status_to_socket(progress, socket);
    304         }
    305 
    306         if ((tail+1) % WINDOW_SIZE == head) {
    307             // write out head buffer
    308             int block = head_block;
    309             if (ioctl(fd.get(), FIBMAP, &block) != 0) {
    310                 ALOGE("failed to find block %d", head_block);
    311                 return kUncryptIoctlError;
    312             }
    313             add_block_to_ranges(ranges, block);
    314             if (encrypted) {
    315                 if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd.get(),
    316                         static_cast<off64_t>(sb.st_blksize) * block) != 0) {
    317                     return kUncryptWriteError;
    318                 }
    319             }
    320             head = (head + 1) % WINDOW_SIZE;
    321             ++head_block;
    322         }
    323 
    324         // read next block to tail
    325         if (encrypted) {
    326             size_t to_read = static_cast<size_t>(
    327                     std::min(static_cast<off64_t>(sb.st_blksize), sb.st_size - pos));
    328             if (!android::base::ReadFully(fd.get(), buffers[tail].data(), to_read)) {
    329                 ALOGE("failed to read: %s", strerror(errno));
    330                 return kUncryptReadError;
    331             }
    332             pos += to_read;
    333         } else {
    334             // If we're not encrypting; we don't need to actually read
    335             // anything, just skip pos forward as if we'd read a
    336             // block.
    337             pos += sb.st_blksize;
    338         }
    339         tail = (tail+1) % WINDOW_SIZE;
    340     }
    341 
    342     while (head != tail) {
    343         // write out head buffer
    344         int block = head_block;
    345         if (ioctl(fd.get(), FIBMAP, &block) != 0) {
    346             ALOGE("failed to find block %d", head_block);
    347             return kUncryptIoctlError;
    348         }
    349         add_block_to_ranges(ranges, block);
    350         if (encrypted) {
    351             if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd.get(),
    352                     static_cast<off64_t>(sb.st_blksize) * block) != 0) {
    353                 return kUncryptWriteError;
    354             }
    355         }
    356         head = (head + 1) % WINDOW_SIZE;
    357         ++head_block;
    358     }
    359 
    360     if (!android::base::WriteStringToFd(
    361             android::base::StringPrintf("%zu\n", ranges.size() / 2), mapfd.get())) {
    362         ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno));
    363         return kUncryptWriteError;
    364     }
    365     for (size_t i = 0; i < ranges.size(); i += 2) {
    366         if (!android::base::WriteStringToFd(
    367                 android::base::StringPrintf("%d %d\n", ranges[i], ranges[i+1]), mapfd.get())) {
    368             ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno));
    369             return kUncryptWriteError;
    370         }
    371     }
    372 
    373     if (fsync(mapfd.get()) == -1) {
    374         ALOGE("failed to fsync \"%s\": %s", tmp_map_file.c_str(), strerror(errno));
    375         return kUncryptFileSyncError;
    376     }
    377     if (close(mapfd.get()) == -1) {
    378         ALOGE("failed to close %s: %s", tmp_map_file.c_str(), strerror(errno));
    379         return kUncryptFileCloseError;
    380     }
    381     mapfd = -1;
    382 
    383     if (encrypted) {
    384         if (fsync(wfd.get()) == -1) {
    385             ALOGE("failed to fsync \"%s\": %s", blk_dev, strerror(errno));
    386             return kUncryptFileSyncError;
    387         }
    388         if (close(wfd.get()) == -1) {
    389             ALOGE("failed to close %s: %s", blk_dev, strerror(errno));
    390             return kUncryptFileCloseError;
    391         }
    392         wfd = -1;
    393     }
    394 
    395     if (rename(tmp_map_file.c_str(), map_file) == -1) {
    396         ALOGE("failed to rename %s to %s: %s", tmp_map_file.c_str(), map_file, strerror(errno));
    397         return kUncryptFileRenameError;
    398     }
    399     // Sync dir to make rename() result written to disk.
    400     std::string file_name = map_file;
    401     std::string dir_name = dirname(&file_name[0]);
    402     unique_fd dfd(open(dir_name.c_str(), O_RDONLY | O_DIRECTORY));
    403     if (!dfd) {
    404         ALOGE("failed to open dir %s: %s", dir_name.c_str(), strerror(errno));
    405         return kUncryptFileOpenError;
    406     }
    407     if (fsync(dfd.get()) == -1) {
    408         ALOGE("failed to fsync %s: %s", dir_name.c_str(), strerror(errno));
    409         return kUncryptFileSyncError;
    410     }
    411     if (close(dfd.get()) == -1) {
    412         ALOGE("failed to close %s: %s", dir_name.c_str(), strerror(errno));
    413         return kUncryptFileCloseError;
    414     }
    415     dfd = -1;
    416     return 0;
    417 }
    418 
    419 static int uncrypt(const char* input_path, const char* map_file, const int socket) {
    420     ALOGI("update package is \"%s\"", input_path);
    421 
    422     // Turn the name of the file we're supposed to convert into an
    423     // absolute path, so we can find what filesystem it's on.
    424     char path[PATH_MAX+1];
    425     if (realpath(input_path, path) == NULL) {
    426         ALOGE("failed to convert \"%s\" to absolute path: %s", input_path, strerror(errno));
    427         return 1;
    428     }
    429 
    430     bool encryptable;
    431     bool encrypted;
    432     const char* blk_dev = find_block_device(path, &encryptable, &encrypted);
    433     if (blk_dev == NULL) {
    434         ALOGE("failed to find block device for %s", path);
    435         return 1;
    436     }
    437 
    438     // If the filesystem it's on isn't encrypted, we only produce the
    439     // block map, we don't rewrite the file contents (it would be
    440     // pointless to do so).
    441     ALOGI("encryptable: %s", encryptable ? "yes" : "no");
    442     ALOGI("  encrypted: %s", encrypted ? "yes" : "no");
    443 
    444     // Recovery supports installing packages from 3 paths: /cache,
    445     // /data, and /sdcard.  (On a particular device, other locations
    446     // may work, but those are three we actually expect.)
    447     //
    448     // On /data we want to convert the file to a block map so that we
    449     // can read the package without mounting the partition.  On /cache
    450     // and /sdcard we leave the file alone.
    451     if (strncmp(path, "/data/", 6) == 0) {
    452         ALOGI("writing block map %s", map_file);
    453         return produce_block_map(path, map_file, blk_dev, encrypted, socket);
    454     }
    455 
    456     return 0;
    457 }
    458 
    459 static void log_uncrypt_error_code(UncryptErrorCode error_code) {
    460     if (!android::base::WriteStringToFile(android::base::StringPrintf(
    461             "uncrypt_error: %d\n", error_code), UNCRYPT_STATUS)) {
    462         ALOGW("failed to write to %s: %s", UNCRYPT_STATUS.c_str(), strerror(errno));
    463     }
    464 }
    465 
    466 static bool uncrypt_wrapper(const char* input_path, const char* map_file, const int socket) {
    467     // Initialize the uncrypt error to kUncryptErrorPlaceholder.
    468     log_uncrypt_error_code(kUncryptErrorPlaceholder);
    469 
    470     std::string package;
    471     if (input_path == nullptr) {
    472         if (!find_uncrypt_package(UNCRYPT_PATH_FILE, &package)) {
    473             write_status_to_socket(-1, socket);
    474             // Overwrite the error message.
    475             log_uncrypt_error_code(kUncryptPackageMissingError);
    476             return false;
    477         }
    478         input_path = package.c_str();
    479     }
    480     CHECK(map_file != nullptr);
    481 
    482     auto start = std::chrono::system_clock::now();
    483     int status = uncrypt(input_path, map_file, socket);
    484     std::chrono::duration<double> duration = std::chrono::system_clock::now() - start;
    485     int count = static_cast<int>(duration.count());
    486 
    487     std::string uncrypt_message = android::base::StringPrintf("uncrypt_time: %d\n", count);
    488     if (status != 0) {
    489         // Log the time cost and error code if uncrypt fails.
    490         uncrypt_message += android::base::StringPrintf("uncrypt_error: %d\n", status);
    491         if (!android::base::WriteStringToFile(uncrypt_message, UNCRYPT_STATUS)) {
    492             ALOGW("failed to write to %s: %s", UNCRYPT_STATUS.c_str(), strerror(errno));
    493         }
    494 
    495         write_status_to_socket(-1, socket);
    496         return false;
    497     }
    498 
    499     if (!android::base::WriteStringToFile(uncrypt_message, UNCRYPT_STATUS)) {
    500         ALOGW("failed to write to %s: %s", UNCRYPT_STATUS.c_str(), strerror(errno));
    501     }
    502 
    503     write_status_to_socket(100, socket);
    504 
    505     return true;
    506 }
    507 
    508 static bool clear_bcb(const int socket) {
    509     std::string err;
    510     if (!clear_bootloader_message(&err)) {
    511         ALOGE("failed to clear bootloader message: %s", err.c_str());
    512         write_status_to_socket(-1, socket);
    513         return false;
    514     }
    515     write_status_to_socket(100, socket);
    516     return true;
    517 }
    518 
    519 static bool setup_bcb(const int socket) {
    520     // c5. receive message length
    521     int length;
    522     if (!android::base::ReadFully(socket, &length, 4)) {
    523         ALOGE("failed to read the length: %s", strerror(errno));
    524         return false;
    525     }
    526     length = ntohl(length);
    527 
    528     // c7. receive message
    529     std::string content;
    530     content.resize(length);
    531     if (!android::base::ReadFully(socket, &content[0], length)) {
    532         ALOGE("failed to read the length: %s", strerror(errno));
    533         return false;
    534     }
    535     ALOGI("  received command: [%s] (%zu)", content.c_str(), content.size());
    536     std::vector<std::string> options = android::base::Split(content, "\n");
    537     std::string wipe_package;
    538     for (auto& option : options) {
    539         if (android::base::StartsWith(option, "--wipe_package=")) {
    540             std::string path = option.substr(strlen("--wipe_package="));
    541             if (!android::base::ReadFileToString(path, &wipe_package)) {
    542                 ALOGE("failed to read %s: %s", path.c_str(), strerror(errno));
    543                 return false;
    544             }
    545             option = android::base::StringPrintf("--wipe_package_size=%zu", wipe_package.size());
    546         }
    547     }
    548 
    549     // c8. setup the bcb command
    550     std::string err;
    551     if (!write_bootloader_message(options, &err)) {
    552         ALOGE("failed to set bootloader message: %s", err.c_str());
    553         write_status_to_socket(-1, socket);
    554         return false;
    555     }
    556     if (!wipe_package.empty() && !write_wipe_package(wipe_package, &err)) {
    557         ALOGE("failed to set wipe package: %s", err.c_str());
    558         write_status_to_socket(-1, socket);
    559         return false;
    560     }
    561     // c10. send "100" status
    562     write_status_to_socket(100, socket);
    563     return true;
    564 }
    565 
    566 static void usage(const char* exename) {
    567     fprintf(stderr, "Usage of %s:\n", exename);
    568     fprintf(stderr, "%s [<package_path> <map_file>]  Uncrypt ota package.\n", exename);
    569     fprintf(stderr, "%s --clear-bcb  Clear BCB data in misc partition.\n", exename);
    570     fprintf(stderr, "%s --setup-bcb  Setup BCB data by command file.\n", exename);
    571 }
    572 
    573 int main(int argc, char** argv) {
    574     enum { UNCRYPT, SETUP_BCB, CLEAR_BCB } action;
    575     const char* input_path = nullptr;
    576     const char* map_file = CACHE_BLOCK_MAP.c_str();
    577 
    578     if (argc == 2 && strcmp(argv[1], "--clear-bcb") == 0) {
    579         action = CLEAR_BCB;
    580     } else if (argc == 2 && strcmp(argv[1], "--setup-bcb") == 0) {
    581         action = SETUP_BCB;
    582     } else if (argc == 1) {
    583         action = UNCRYPT;
    584     } else if (argc == 3) {
    585         input_path = argv[1];
    586         map_file = argv[2];
    587         action = UNCRYPT;
    588     } else {
    589         usage(argv[0]);
    590         return 2;
    591     }
    592 
    593     if ((fstab = read_fstab()) == nullptr) {
    594         log_uncrypt_error_code(kUncryptFstabReadError);
    595         return 1;
    596     }
    597 
    598     // c3. The socket is created by init when starting the service. uncrypt
    599     // will use the socket to communicate with its caller.
    600     unique_fd service_socket(android_get_control_socket(UNCRYPT_SOCKET.c_str()));
    601     if (!service_socket) {
    602         ALOGE("failed to open socket \"%s\": %s", UNCRYPT_SOCKET.c_str(), strerror(errno));
    603         log_uncrypt_error_code(kUncryptSocketOpenError);
    604         return 1;
    605     }
    606     fcntl(service_socket.get(), F_SETFD, FD_CLOEXEC);
    607 
    608     if (listen(service_socket.get(), 1) == -1) {
    609         ALOGE("failed to listen on socket %d: %s", service_socket.get(), strerror(errno));
    610         log_uncrypt_error_code(kUncryptSocketListenError);
    611         return 1;
    612     }
    613 
    614     unique_fd socket_fd(accept4(service_socket.get(), nullptr, nullptr, SOCK_CLOEXEC));
    615     if (!socket_fd) {
    616         ALOGE("failed to accept on socket %d: %s", service_socket.get(), strerror(errno));
    617         log_uncrypt_error_code(kUncryptSocketAcceptError);
    618         return 1;
    619     }
    620 
    621     bool success = false;
    622     switch (action) {
    623         case UNCRYPT:
    624             success = uncrypt_wrapper(input_path, map_file, socket_fd.get());
    625             break;
    626         case SETUP_BCB:
    627             success = setup_bcb(socket_fd.get());
    628             break;
    629         case CLEAR_BCB:
    630             success = clear_bcb(socket_fd.get());
    631             break;
    632         default:  // Should never happen.
    633             ALOGE("Invalid uncrypt action code: %d", action);
    634             return 1;
    635     }
    636 
    637     // c13. Read a 4-byte code from the client before uncrypt exits. This is to
    638     // ensure the client to receive the last status code before the socket gets
    639     // destroyed.
    640     int code;
    641     if (android::base::ReadFully(socket_fd.get(), &code, 4)) {
    642         ALOGI("  received %d, exiting now", code);
    643     } else {
    644         ALOGE("failed to read the code: %s", strerror(errno));
    645     }
    646     return success ? 0 : 1;
    647 }
    648