From 165788e15fb72e04d4ff068bb2c20623ae726671 Mon Sep 17 00:00:00 2001 From: "Wiktor S. Ovalle Correa" Date: Fri, 15 Jan 2021 09:32:08 +0100 Subject: [PATCH] [EGD-5139] Add some missing POSIX calls This commit adds interceptions for common POSIX calls. Issue [EGD-4551] has shown that some calls can be made from stdlibc++ that we didn't trace or intercept so far. Our goal here is to improve our POSIX coverage. --- .../libiosyscalls/src/syscalls_posix.cpp | 124 ++++++++++++++++-- board/linux/libiosyscalls/version.txt | 14 +- 2 files changed, 121 insertions(+), 17 deletions(-) diff --git a/board/linux/libiosyscalls/src/syscalls_posix.cpp b/board/linux/libiosyscalls/src/syscalls_posix.cpp index 9ef4962946c1174136a2e2881ff1246dcc05ba73..bedad8012291261c8810499ffbcd24fc4aa5ff18 100644 --- a/board/linux/libiosyscalls/src/syscalls_posix.cpp +++ b/board/linux/libiosyscalls/src/syscalls_posix.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include #include // for va_* @@ -52,6 +54,15 @@ namespace __REAL_DECL(__fxstat64); __REAL_DECL(read); + __REAL_DECL(write); + __REAL_DECL(lseek); + __REAL_DECL(lseek64); + + __REAL_DECL(mount); + __REAL_DECL(umount); + + __REAL_DECL(ioctl); + __REAL_DECL(poll); } // namespace real void __attribute__((constructor)) _lib_posix_initialize() @@ -85,6 +96,15 @@ namespace __REAL_DLSYM(__fxstat64); __REAL_DLSYM(read); + __REAL_DLSYM(write); + __REAL_DLSYM(lseek); + __REAL_DLSYM(lseek64); + + __REAL_DLSYM(mount); + __REAL_DLSYM(umount); + + __REAL_DLSYM(ioctl); + __REAL_DLSYM(poll); if (!(real::link && real::unlink && real::symlink && real::fcntl && real::fcntl64 && real::chdir && real::fchdir && real::getcwd && real::getwd @@ -92,7 +112,8 @@ namespace && real::fsync && real::fdatasync && real::__xstat && real::__lxstat && real::__fxstat && real::__xstat64 && real::__lxstat64 && real::__fxstat64 - && real::read)) + && real::read && real::write && real::lseek && real::lseek64 + && real::mount && real::umount && real::ioctl && real::poll)) { abort(); } @@ -105,17 +126,102 @@ extern "C" { int _iosys_read(int __fd, void *__buf, size_t __nbyte) { + int ret; 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); + TRACE_SYSCALLN("(%d, %p, %u) -> VFS", __fd, __buf, __nbyte); + ret = vfs::invoke_fs(&fs::read,vfs::to_image_fd(__fd),(char*)__buf,__nbyte); } else { - TRACE_SYSCALLN("(%d) -> linux fs", __fd); + TRACE_SYSCALLN("(%d, %p, %u) -> linux fs", __fd, __buf, __nbyte); + // returning result via a variable causes strange + // sanitizer errors on debug build return real::read(__fd, __buf, __nbyte); } + TRACE_SYSCALLN("(%d, %p, %u) = %d", __fd, __buf, __nbyte, ret); + return ret; } __asm__(".symver _iosys_read,read@GLIBC_2.2.5"); + int _iosys_write(int __fd, const void *__buf, size_t __nbyte) + { + int ret; + if (vfs::is_image_fd(__fd)) + { + TRACE_SYSCALLN("(%d, %p, %u) -> VFS", __fd, __buf, __nbyte); + ret = vfs::invoke_fs(&fs::write,vfs::to_image_fd(__fd),(const char*)__buf,__nbyte); + } else { + TRACE_SYSCALLN("(%d, %p, %u) -> linux fs", __fd, __buf, __nbyte); + ret = real::write(__fd, __buf, __nbyte); + } + TRACE_SYSCALLN("(%d, %p, %u) = %d", __fd, __buf, __nbyte, ret); + return ret; + } + __asm__(".symver _iosys_write,write@GLIBC_2.2.5"); + + int _iosys_lseek(int __fildes, off_t __offset, int __whence) + { + if (vfs::is_image_fd(__fildes)) + { + TRACE_SYSCALLN("(%d) -> VFS", __fildes); + return vfs::invoke_fs(&fs::seek,vfs::to_image_fd(__fildes),__offset,__whence); + } else { + TRACE_SYSCALLN("(%d) -> linux fs", __fildes); + return real::lseek(__fildes, __offset, __whence); + } + } + __asm__(".symver _iosys_lseek,lseek@GLIBC_2.2.5"); + + int _iosys_lseek64(int __fd, loff_t __offset, int __whence) + { + if (vfs::is_image_fd(__fd)) + { + TRACE_SYSCALLN("%s", "-> lseek"); + return lseek(__fd, __offset, __whence); + } else { + TRACE_SYSCALLN("(%d) -> linux fs", __fd); + return real::lseek64(__fd, __offset, __whence); + } + } + __asm__(".symver _iosys_lseek64,lseek64@GLIBC_2.2.5"); + + int _iosys_ioctl(int __fd, unsigned long int __request, ...) + { + int ret; + uintptr_t param; + va_list args; + va_start(args,__request); + param = va_arg(args,uintptr_t); + if (vfs::is_image_fd(__fd)) { + TRACE_SYSCALLN("(%d) -> VFS", __fd); + // VFS's ioctl works on paths, not file descriptors + // so we can't handle it the easy way, f ex. + // ret = vfs::invoke_fs(__VFS(ioctl), __fd, __request, param); + errno = ENOTSUP; + std::cerr << "Unsupported syscall " << __PRETTY_FUNCTION__ << std::endl; + ret = -1; + } else { + TRACE_SYSCALLN("(%d) -> linux fs", __fd); + ret = real::ioctl(__fd, __request, param); + } + va_end(args); + return ret; + } + __asm__(".symver _iosys_ioctl,ioctl@GLIBC_2.2.5"); + + int _iosys_poll(struct pollfd *__fds, nfds_t __nfds, int __timeout) + { + if (__fds && vfs::is_image_fd(__fds->fd)) { + TRACE_SYSCALLN("(%d) -> VFS", __fds->fd); + // there's no point in translating this call + errno = ENOTSUP; + std::cerr << "Unsupported syscall " << __PRETTY_FUNCTION__ << std::endl; + return -1; + } + TRACE_SYSCALLN("(%d) -> linux fs", __fds ? __fds->fd : 0); + return real::poll(__fds, __nfds, __timeout); + } + __asm__(".symver _iosys_poll,poll@GLIBC_2.2.5"); + int _iosys_link(const char *oldpath, const char *newpath) { if(vfs::redirect_to_image(oldpath)) @@ -566,13 +672,13 @@ extern "C" { { if(vfs::redirect_to_image(dir)) { + TRACE_SYSCALLN("(%s, %s, %s, %08lx, %p) -> VFS", special_file, dir, fstype, rwflag, data); return vfs::invoke_fs(&fs::mount, special_file, dir, fstype, rwflag ); } else { - //NOTE: Always return zero because we will use fileystem which is always RW - TRACE_SYSCALLN("(%s, %s, %s, %08lx,%p) -> linux fs", special_file, dir,fstype, rwflag, data); - return 0; + TRACE_SYSCALLN("(%s, %s, %s, %08lx,%p) -> linux fs", special_file, dir, fstype, rwflag, data); + return real::mount(special_file, dir, fstype, rwflag, data); } } __asm__(".symver _iosys_mount,mount@GLIBC_2.2.5"); @@ -581,13 +687,13 @@ extern "C" { { if(vfs::redirect_to_image(mount_point)) { + TRACE_SYSCALLN("(%s) -> VFS", mount_point); return vfs::invoke_fs(&fs::umount, mount_point ); } else { - //NOTE: Always return zero because we will use fileystem which is always RW TRACE_SYSCALLN("(%s) -> linux fs", mount_point); - return 0; + return real::umount(mount_point); } } __asm__(".symver _iosys_umount,umount@GLIBC_2.2.5"); diff --git a/board/linux/libiosyscalls/version.txt b/board/linux/libiosyscalls/version.txt index c95dd19ecdd248cc970109fd9f9b722c7bc48f19..620048fb43031764c4f9535e5583891de201e571 100644 --- a/board/linux/libiosyscalls/version.txt +++ b/board/linux/libiosyscalls/version.txt @@ -32,7 +32,7 @@ GLIBC_2.2.5 { fscanf; vfscanf; # ungetc; -# stdio - disabled +# stdio - buffering disabled setbuf; setvbuf; setbuffer; @@ -63,6 +63,11 @@ GLIBC_2.2.5 { __lxstat64; __fxstat64; read; + write; + lseek; + lseek64; + ioctl; + poll; mount; umount; # posix - dirent @@ -73,13 +78,6 @@ GLIBC_2.2.5 { rewinddir; seekdir; telldir; -# posix - not implemented -# write; -# lseek; -# lseek64; -# ioctl; -# poll; - local: *; };