Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70432065 authored by Tao Bao's avatar Tao Bao Committed by Gerrit Code Review
Browse files

Merge "IO fault injection for OTA packages"

parents 6a7bf1d9 a7b9a466
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@ include $(LOCAL_PATH)/minui/Android.mk \
    $(LOCAL_PATH)/tools/Android.mk \
    $(LOCAL_PATH)/edify/Android.mk \
    $(LOCAL_PATH)/uncrypt/Android.mk \
    $(LOCAL_PATH)/otafault/Android.mk \
    $(LOCAL_PATH)/updater/Android.mk \
    $(LOCAL_PATH)/update_verifier/Android.mk \
    $(LOCAL_PATH)/applypatch/Android.mk
+2 −2
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ LOCAL_SRC_FILES := applypatch.cpp bspatch.cpp freecache.cpp imgpatch.cpp utils.c
LOCAL_MODULE := libapplypatch
LOCAL_MODULE_TAGS := eng
LOCAL_C_INCLUDES += bootable/recovery
LOCAL_STATIC_LIBRARIES += libbase libmtdutils libcrypto_static libbz libz
LOCAL_STATIC_LIBRARIES += libbase libotafault libmtdutils libcrypto_static libbz libz

include $(BUILD_STATIC_LIBRARY)

@@ -55,7 +55,7 @@ LOCAL_CLANG := true
LOCAL_SRC_FILES := main.cpp
LOCAL_MODULE := applypatch
LOCAL_C_INCLUDES += bootable/recovery
LOCAL_STATIC_LIBRARIES += libapplypatch libbase libmtdutils libcrypto_static libbz libedify
LOCAL_STATIC_LIBRARIES += libapplypatch libbase libotafault libmtdutils libcrypto_static libbz libedify
LOCAL_SHARED_LIBRARIES += libz libcutils libc

include $(BUILD_EXECUTABLE)
+27 −26
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include "mtdutils/mtdutils.h"
#include "edify/expr.h"
#include "print_sha1.h"
#include "otafault/ota_io.h"

static int LoadPartitionContents(const char* filename, FileContents* file);
static ssize_t FileSink(const unsigned char* data, ssize_t len, void* token);
@@ -79,19 +80,19 @@ int LoadFileContents(const char* filename, FileContents* file) {
        return -1;
    }

    FILE* f = fopen(filename, "rb");
    FILE* f = ota_fopen(filename, "rb");
    if (f == NULL) {
        printf("failed to open \"%s\": %s\n", filename, strerror(errno));
        return -1;
    }

    size_t bytes_read = fread(data.get(), 1, file->size, f);
    size_t bytes_read = ota_fread(data.get(), 1, file->size, f);
    if (bytes_read != static_cast<size_t>(file->size)) {
        printf("short read of \"%s\" (%zu bytes of %zd)\n", filename, bytes_read, file->size);
        fclose(f);
        ota_fclose(f);
        return -1;
    }
    fclose(f);
    ota_fclose(f);
    file->data = data.release();
    SHA1(file->data, file->size, file->sha1);
    return 0;
@@ -180,7 +181,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
        }

        case EMMC:
            dev = fopen(partition, "rb");
            dev = ota_fopen(partition, "rb");
            if (dev == NULL) {
                printf("failed to open emmc partition \"%s\": %s\n", partition, strerror(errno));
                return -1;
@@ -209,7 +210,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
                    break;

                case EMMC:
                    read = fread(p, 1, next, dev);
                    read = ota_fread(p, 1, next, dev);
                    break;
            }
            if (next != read) {
@@ -255,7 +256,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
            break;

        case EMMC:
            fclose(dev);
            ota_fclose(dev);
            break;
    }

@@ -282,7 +283,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
// Save the contents of the given FileContents object under the given
// filename.  Return 0 on success.
int SaveFileContents(const char* filename, const FileContents* file) {
    int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR);
    int fd = ota_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR);
    if (fd < 0) {
        printf("failed to open \"%s\" for write: %s\n", filename, strerror(errno));
        return -1;
@@ -292,14 +293,14 @@ int SaveFileContents(const char* filename, const FileContents* file) {
    if (bytes_written != file->size) {
        printf("short write of \"%s\" (%zd bytes of %zd) (%s)\n",
               filename, bytes_written, file->size, strerror(errno));
        close(fd);
        ota_close(fd);
        return -1;
    }
    if (fsync(fd) != 0) {
    if (ota_fsync(fd) != 0) {
        printf("fsync of \"%s\" failed: %s\n", filename, strerror(errno));
        return -1;
    }
    if (close(fd) != 0) {
    if (ota_close(fd) != 0) {
        printf("close of \"%s\" failed: %s\n", filename, strerror(errno));
        return -1;
    }
@@ -382,7 +383,7 @@ int WriteToPartition(const unsigned char* data, size_t len, const char* target)
        case EMMC: {
            size_t start = 0;
            bool success = false;
            int fd = open(partition, O_RDWR | O_SYNC);
            int fd = ota_open(partition, O_RDWR | O_SYNC);
            if (fd < 0) {
                printf("failed to open %s: %s\n", partition, strerror(errno));
                return -1;
@@ -397,22 +398,22 @@ int WriteToPartition(const unsigned char* data, size_t len, const char* target)
                    size_t to_write = len - start;
                    if (to_write > 1<<20) to_write = 1<<20;

                    ssize_t written = TEMP_FAILURE_RETRY(write(fd, data+start, to_write));
                    ssize_t written = TEMP_FAILURE_RETRY(ota_write(fd, data+start, to_write));
                    if (written == -1) {
                        printf("failed write writing to %s: %s\n", partition, strerror(errno));
                        return -1;
                    }
                    start += written;
                }
                if (fsync(fd) != 0) {
                if (ota_fsync(fd) != 0) {
                   printf("failed to sync to %s (%s)\n", partition, strerror(errno));
                   return -1;
                }
                if (close(fd) != 0) {
                if (ota_close(fd) != 0) {
                   printf("failed to close %s (%s)\n", partition, strerror(errno));
                   return -1;
                }
                fd = open(partition, O_RDONLY);
                fd = ota_open(partition, O_RDONLY);
                if (fd < 0) {
                   printf("failed to reopen %s for verify (%s)\n", partition, strerror(errno));
                   return -1;
@@ -421,13 +422,13 @@ int WriteToPartition(const unsigned char* data, size_t len, const char* target)
                // Drop caches so our subsequent verification read
                // won't just be reading the cache.
                sync();
                int dc = open("/proc/sys/vm/drop_caches", O_WRONLY);
                if (TEMP_FAILURE_RETRY(write(dc, "3\n", 2)) == -1) {
                int dc = ota_open("/proc/sys/vm/drop_caches", O_WRONLY);
                if (TEMP_FAILURE_RETRY(ota_write(dc, "3\n", 2)) == -1) {
                    printf("write to /proc/sys/vm/drop_caches failed: %s\n", strerror(errno));
                } else {
                    printf("  caches dropped\n");
                }
                close(dc);
                ota_close(dc);
                sleep(1);

                // verify
@@ -447,7 +448,7 @@ int WriteToPartition(const unsigned char* data, size_t len, const char* target)
                    size_t so_far = 0;
                    while (so_far < to_read) {
                        ssize_t read_count =
                                TEMP_FAILURE_RETRY(read(fd, buffer+so_far, to_read-so_far));
                                TEMP_FAILURE_RETRY(ota_read(fd, buffer+so_far, to_read-so_far));
                        if (read_count == -1) {
                            printf("verify read error %s at %zu: %s\n",
                                   partition, p, strerror(errno));
@@ -479,7 +480,7 @@ int WriteToPartition(const unsigned char* data, size_t len, const char* target)
                return -1;
            }

            if (close(fd) != 0) {
            if (ota_close(fd) != 0) {
                printf("error closing %s (%s)\n", partition, strerror(errno));
                return -1;
            }
@@ -589,7 +590,7 @@ ssize_t FileSink(const unsigned char* data, ssize_t len, void* token) {
    ssize_t done = 0;
    ssize_t wrote;
    while (done < len) {
        wrote = TEMP_FAILURE_RETRY(write(fd, data+done, len-done));
        wrote = TEMP_FAILURE_RETRY(ota_write(fd, data+done, len-done));
        if (wrote == -1) {
            printf("error writing %zd bytes: %s\n", (len-done), strerror(errno));
            return done;
@@ -934,7 +935,7 @@ static int GenerateTarget(FileContents* source_file,
            token = &memory_sink_str;
        } else {
            // We write the decoded output to "<tgt-file>.patch".
            output_fd = open(tmp_target_filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_SYNC,
            output_fd = ota_open(tmp_target_filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_SYNC,
                                 S_IRUSR | S_IWUSR);
            if (output_fd < 0) {
                printf("failed to open output file %s: %s\n", tmp_target_filename.c_str(),
@@ -958,12 +959,12 @@ static int GenerateTarget(FileContents* source_file,
        }

        if (!target_is_partition) {
            if (fsync(output_fd) != 0) {
            if (ota_fsync(output_fd) != 0) {
                printf("failed to fsync file \"%s\" (%s)\n", tmp_target_filename.c_str(),
                       strerror(errno));
                result = 1;
            }
            if (close(output_fd) != 0) {
            if (ota_close(output_fd) != 0) {
                printf("failed to close file \"%s\" (%s)\n", tmp_target_filename.c_str(),
                       strerror(errno));
                result = 1;

otafault/Android.mk

0 → 100644
+58 −0
Original line number Diff line number Diff line
# Copyright 2015 The ANdroid Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# 	   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific languae governing permissions and
# limitations under the License.

LOCAL_PATH := $(call my-dir)

empty :=
space := $(empty) $(empty)
comma := ,

ifneq ($(TARGET_INJECT_FAULTS),)
TARGET_INJECT_FAULTS := $(subst $(comma),$(space),$(strip $(TARGET_INJECT_FAULTS)))
endif

include $(CLEAR_VARS)

LOCAL_SRC_FILES := ota_io.cpp
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := libotafault
LOCAL_CLANG := true

ifneq ($(TARGET_INJECT_FAULTS),)
$(foreach ft,$(TARGET_INJECT_FAULTS),\
	$(eval LOCAL_CFLAGS += -DTARGET_$(ft)_FAULT=$(TARGET_$(ft)_FAULT_FILE)))
LOCAL_CFLAGS += -Wno-unused-parameter
LOCAL_CFLAGS += -DTARGET_INJECT_FAULTS
endif

LOCAL_STATIC_LIBRARIES := libc

include $(BUILD_STATIC_LIBRARY)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := ota_io.cpp test.cpp
LOCAL_MODULE_TAGS := tests
LOCAL_MODULE := otafault_test
LOCAL_STATIC_LIBRARIES := libc
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_CFLAGS += -Wno-unused-parameter -Wno-writable-strings

ifneq ($(TARGET_INJECT_FAULTS),)
$(foreach ft,$(TARGET_INJECT_FAULTS),\
	$(eval LOCAL_CFLAGS += -DTARGET_$(ft)_FAULT=$(TARGET_$(ft)_FAULT_FILE)))
LOCAL_CFLAGS += -DTARGET_INJECT_FAULTS
endif

include $(BUILD_EXECUTABLE)

otafault/ota_io.cpp

0 → 100644
+160 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#if defined (TARGET_INJECT_FAULTS)
#include <map>
#endif

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

#include "ota_io.h"

#if defined (TARGET_INJECT_FAULTS)
static std::map<int, const char*> FilenameCache;
static std::string FaultFileName =
#if defined (TARGET_READ_FAULT)
        TARGET_READ_FAULT;
#elif defined (TARGET_WRITE_FAULT)
        TARGET_WRITE_FAULT;
#elif defined (TARGET_FSYNC_FAULT)
        TARGET_FSYNC_FAULT;
#endif // defined (TARGET_READ_FAULT)
#endif // defined (TARGET_INJECT_FAULTS)

int ota_open(const char* path, int oflags) {
#if defined (TARGET_INJECT_FAULTS)
    // Let the caller handle errors; we do not care if open succeeds or fails
    int fd = open(path, oflags);
    FilenameCache[fd] = path;
    return fd;
#else
    return open(path, oflags);
#endif
}

int ota_open(const char* path, int oflags, mode_t mode) {
#if defined (TARGET_INJECT_FAULTS)
    int fd = open(path, oflags, mode);
    FilenameCache[fd] = path;
    return fd;
#else
    return open(path, oflags, mode);
#endif
}

FILE* ota_fopen(const char* path, const char* mode) {
#if defined (TARGET_INJECT_FAULTS)
    FILE* fh = fopen(path, mode);
    FilenameCache[(intptr_t)fh] = path;
    return fh;
#else
    return fopen(path, mode);
#endif
}

int ota_close(int fd) {
#if defined (TARGET_INJECT_FAULTS)
    // descriptors can be reused, so make sure not to leave them in the cahce
    FilenameCache.erase(fd);
#endif
    return close(fd);
}

int ota_fclose(FILE* fh) {
#if defined (TARGET_INJECT_FAULTS)
    FilenameCache.erase((intptr_t)fh);
#endif
    return fclose(fh);
}

size_t ota_fread(void* ptr, size_t size, size_t nitems, FILE* stream) {
#if defined (TARGET_READ_FAULT)
    if (FilenameCache.find((intptr_t)stream) != FilenameCache.end()
            && FilenameCache[(intptr_t)stream] == FaultFileName) {
        FaultFileName = "";
        errno = EIO;
        return 0;
    } else {
        return fread(ptr, size, nitems, stream);
    }
#else
    return fread(ptr, size, nitems, stream);
#endif
}

ssize_t ota_read(int fd, void* buf, size_t nbyte) {
#if defined (TARGET_READ_FAULT)
    if (FilenameCache.find(fd) != FilenameCache.end()
            && FilenameCache[fd] == FaultFileName) {
        FaultFileName = "";
        errno = EIO;
        return -1;
    } else {
        return read(fd, buf, nbyte);
    }
#else
    return read(fd, buf, nbyte);
#endif
}

size_t ota_fwrite(const void* ptr, size_t size, size_t count, FILE* stream) {
#if defined (TARGET_WRITE_FAULT)
    if (FilenameCache.find((intptr_t)stream) != FilenameCache.end()
            && FilenameCache[(intptr_t)stream] == FaultFileName) {
        FaultFileName = "";
        errno = EIO;
        return 0;
    } else {
        return fwrite(ptr, size, count, stream);
    }
#else
    return fwrite(ptr, size, count, stream);
#endif
}

ssize_t ota_write(int fd, const void* buf, size_t nbyte) {
#if defined (TARGET_WRITE_FAULT)
    if (FilenameCache.find(fd) != FilenameCache.end()
            && FilenameCache[fd] == FaultFileName) {
        FaultFileName = "";
        errno = EIO;
        return -1;
    } else {
        return write(fd, buf, nbyte);
    }
#else
    return write(fd, buf, nbyte);
#endif
}

int ota_fsync(int fd) {
#if defined (TARGET_FSYNC_FAULT)
    if (FilenameCache.find(fd) != FilenameCache.end()
            && FilenameCache[fd] == FaultFileName) {
        FaultFileName = "";
        errno = EIO;
        return -1;
    } else {
        return fsync(fd);
    }
#else
    return fsync(fd);
#endif
}
Loading