~aleteoryx/muditaos

5bc3a96dbd602fe4a7d763332d3e23afca02257e — Wiktor S. Ovalle Correa 5 years ago e8d1fd2
[EGD-4551] Add missing read() interception

Fix error caused by libstdc++ passing our fd to native read()
M board/linux/libiosyscalls/CMakeLists.txt => board/linux/libiosyscalls/CMakeLists.txt +4 -0
@@ 43,3 43,7 @@ target_link_options(${PROJECT_NAME} PRIVATE
target_include_directories(${PROJECT_NAME} PUBLIC ${INCLUDES} )
target_link_libraries( ${PROJECT_NAME} dl )
target_compile_definitions( ${PROJECT_NAME} PUBLIC TARGET_Linux )

if (${ENABLE_TESTS})
    add_subdirectory(test)
endif ()

M board/linux/libiosyscalls/include/iosyscalls.hpp => board/linux/libiosyscalls/include/iosyscalls.hpp +2 -1
@@ 22,7 22,8 @@ namespace vfsn::linux::internal
        int ungetchar {-1};
    };

    int get_native_fd(FILEX*);
    int to_native_fd(int fd);
    int to_image_fd(int fd);

    FILEX* allocate_filex(int fd);
    bool is_filex(const void* fd);

M board/linux/libiosyscalls/src/iosyscalls.cpp => board/linux/libiosyscalls/src/iosyscalls.cpp +8 -2
@@ 27,6 27,7 @@ namespace {
        "/proc",
        "/dev/shm",
        "PurePhone.img",
        "MuditaOS.log",
        nullptr,
    };
    constexpr const char * EXCLUDED_PATHS[] = {


@@ 104,9 105,14 @@ namespace vfsn::linux::internal
        return false;
    }

    int get_native_fd(FILEX* file)
    int to_native_fd(int fd)
    {
        return file ? (FIRST_FILEDESC + file->fd) : -1;
        return FIRST_FILEDESC + fd;
    }

    int to_image_fd(int fd)
    {
        return fd - FIRST_FILEDESC;
    }

    bool is_image_fd(int fd)

M board/linux/libiosyscalls/src/syscalls_posix.cpp => board/linux/libiosyscalls/src/syscalls_posix.cpp +24 -7
@@ 50,6 50,8 @@ namespace
        __REAL_DECL(__xstat64);
        __REAL_DECL(__lxstat64);
        __REAL_DECL(__fxstat64);

        __REAL_DECL(read);
    } // namespace real

    void __attribute__((constructor)) _lib_posix_initialize()


@@ 82,13 84,15 @@ namespace
        __REAL_DLSYM(__lxstat64);
        __REAL_DLSYM(__fxstat64);

        __REAL_DLSYM(read);

        if (!(real::link && real::unlink && real::symlink && real::fcntl && real::fcntl64
            && real::chdir && real::fchdir && real::getcwd && real::getwd
            && real::get_current_dir_name && real::mkdir && real::chmod && real::fchmod
            && real::fsync && real::fdatasync
            && real::__xstat && real::__lxstat && real::__fxstat
            && real::__xstat64 && real::__lxstat64 && real::__fxstat64))
            && real::__xstat64 && real::__lxstat64 && real::__fxstat64
            && real::read))
        {
            abort();
        }


@@ 99,6 103,19 @@ extern "C" {
    namespace vfs = vfsn::linux::internal;
    using fs = purefs::fs::filesystem;

    int _iosys_read(int __fd, void *__buf, size_t __nbyte)
    {
        if (vfs::is_image_fd(__fd))
        {
            TRACE_SYSCALLN("(%d) -> VFS", __fd);
            return vfs::invoke_fs(&fs::read,vfs::to_image_fd(__fd),(char*)__buf,__nbyte);
        } else {
            TRACE_SYSCALLN("(%d) -> linux fs", __fd);
            return real::read(__fd, __buf, __nbyte);
        }
    }
    __asm__(".symver _iosys_read,read@GLIBC_2.2.5");

    int _iosys_link(const char *oldpath, const char *newpath)
    {
        if(vfs::redirect_to_image(oldpath))


@@ 175,7 192,7 @@ extern "C" {
        if(vfs::is_image_fd(fd))
        {
            TRACE_SYSCALLN("(%d) -> VFS", fd);
            return vfs::invoke_fs(&fs::fstat,fd,*pstat);
            return vfs::invoke_fs(&fs::fstat,vfs::to_image_fd(fd),*pstat);
        }
        else
        {


@@ 371,7 388,7 @@ extern "C" {
        if(vfs::is_image_fd(fd))
        {
            TRACE_SYSCALLN("(%d) -> VFS", fd);
            return vfs::invoke_fs(&fs::fchmod,fd,mode);
            return vfs::invoke_fs(&fs::fchmod,vfs::to_image_fd(fd),mode);
        }
        else
        {


@@ 386,7 403,7 @@ extern "C" {
        if(vfs::is_image_fd(fd))
        {
            TRACE_SYSCALLN("(%d) -> VFS", fd);
            return vfs::invoke_fs(&fs::fsync, fd);
            return vfs::invoke_fs(&fs::fsync, vfs::to_image_fd(fd));
        }
        else
        {


@@ 401,7 418,7 @@ extern "C" {
        if(vfs::is_image_fd(fd))
        {
            TRACE_SYSCALLN("(%d) -> VFS", fd);
            return vfs::invoke_fs(&fs::fsync, fd);
            return vfs::invoke_fs(&fs::fsync, vfs::to_image_fd(fd));
        }
        else
        {


@@ 468,7 485,7 @@ extern "C" {
        if(vfs::is_image_fd(fildes))
        {
            TRACE_SYSCALLN("(%d) -> VFS", fildes);
            return vfs::invoke_fs(&fs::fstat, fildes, *stat_buf);
            return vfs::invoke_fs(&fs::fstat, vfs::to_image_fd(fildes), *stat_buf);
        }
        else
        {


@@ 525,7 542,7 @@ extern "C" {
        if(vfs::is_image_fd(fildes))
        {
            TRACE_SYSCALLN("(%d) -> VFS", fildes);
            return vfs::invoke_fs(&fs::fstat, fildes, *(struct stat*)stat_buf);
            return vfs::invoke_fs(&fs::fstat, vfs::to_image_fd(fildes), *(struct stat*)stat_buf);
        }
        else
        {

M board/linux/libiosyscalls/src/syscalls_stdio.cpp => board/linux/libiosyscalls/src/syscalls_stdio.cpp +1 -1
@@ 378,7 378,7 @@ extern "C"
        if(vfs::is_filex(__stream))
        {
            TRACE_SYSCALLN("(%p) -> VFS", __stream);
            ret =  vfs::get_native_fd(reinterpret_cast<FILEX*>(__stream));
            ret = vfs::to_native_fd(reinterpret_cast<FILEX*>(__stream)->fd);
        }
        else
        {

A board/linux/libiosyscalls/test/CMakeLists.txt => board/linux/libiosyscalls/test/CMakeLists.txt +13 -0
@@ 0,0 1,13 @@
cmake_minimum_required(VERSION 3.12)

# iosyscalls tests
add_catch2_executable(
    NAME
        iosyscalls
    SRCS
        ${CMAKE_CURRENT_LIST_DIR}/unittest_iosys.cpp
    LIBS
        module-vfs iosyscalls
    DEPS
        PurePhone.img-target
)

A board/linux/libiosyscalls/test/unittest_iosys.cpp => board/linux/libiosyscalls/test/unittest_iosys.cpp +36 -0
@@ 0,0 1,36 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#define CATCH_CONFIG_MAIN

#include <catch2/catch.hpp>
#include <purefs/vfs_subsystem.hpp>

#include <filesystem>

TEST_CASE("VFS linux support")
{
    auto vfs = purefs::subsystem::initialize();
    auto err = purefs::subsystem::mount_defaults();
    REQUIRE(err == 0);

    static constexpr auto filenm = "assets/lang/English.json";

    SECTION("std::filesystem") {
        REQUIRE(std::filesystem::file_size(filenm) > 0);
    }

    SECTION("iterators") {
        std::ifstream myfile(filenm);
        REQUIRE (myfile.is_open());

        auto __first = std::istreambuf_iterator<char>(myfile);
        auto __last = std::istreambuf_iterator<char>();
        std::vector<char> testvec(__first, __last);

        testvec.push_back('\0');
        REQUIRE(std::string(testvec.data()).length() > 0);
    }

    REQUIRE(purefs::subsystem::unmount_all() == 0);
}

M board/linux/libiosyscalls/version.txt => board/linux/libiosyscalls/version.txt +1 -1
@@ 62,6 62,7 @@ GLIBC_2.2.5 {
                __xstat64;
                __lxstat64;
                __fxstat64;
                read;
                mount;
                umount;
# posix - dirent


@@ 73,7 74,6 @@ GLIBC_2.2.5 {
                seekdir;
                telldir;
# posix - not implemented
#                read;
#                write;
#                lseek;
#                lseek64;