diff --git a/exports.go b/exports.go index e20d4c6..e032412 100644 --- a/exports.go +++ b/exports.go @@ -1,363 +1,9 @@ +//go:build linux + package main /* +#cgo linux LDFLAGS: -ldl -pthread #include "rtld.h" */ import "C" -import ( - "fmt" - "unsafe" - - "golang.org/x/sys/unix" -) - -// There's an issue I don't fully understand which prevents the import -// of . If imported, there are conflicts with the function -// defintions for chmod, mkdir, mknod, and mknodat. - -// The functions __fxstat, __fxstatat, __lxstat, __xstat, and fstat all -// rely on the stat structure defined in . Unsafe pointers -// could be used, but instead we simply define the struct above. - -//export __fxstat -func __fxstat(_ C.int, fd C.int, cstat *C.struct_stat) C.int { - fmt.Println("In __fxstat") - if cstat == nil { - return -1 - } - ustat := (*unix.Stat_t)(unsafe.Pointer(cstat)) - err := unix.Fstat(int(fd), ustat) - if err != nil { - return -1 - } - return 0 -} - -//export __fxstatat -func __fxstatat(_ C.int, dirfd C.int, pathname *C.char, cstat *C.struct_stat, flags C.int) C.int { - fmt.Println("In __fxstatat") - if cstat == nil || pathname == nil { - return -1 - } - ustat := (*unix.Stat_t)(unsafe.Pointer(cstat)) - err := unix.Fstatat(int(dirfd), C.GoString(pathname), ustat, int(flags)) - if err != nil { - return -1 - } - return 0 -} - -//export __lxstat -func __lxstat(_ C.int, pathname *C.char, cstat *C.struct_stat) C.int { - fmt.Println("In __lxstat") - if cstat == nil || pathname == nil { - return -1 - } - ustat := (*unix.Stat_t)(unsafe.Pointer(cstat)) - err := unix.Lstat(C.GoString(pathname), ustat) - if err != nil { - return -1 - } - return 0 -} - -//export __xstat -func __xstat(_ C.int, pathname *C.char, cstat *C.struct_stat) C.int { - fmt.Println("In __xstat") - if cstat == nil || pathname == nil { - return -1 - } - ustat := (*unix.Stat_t)(unsafe.Pointer(cstat)) - err := unix.Stat(C.GoString(pathname), ustat) - if err != nil { - return -1 - } - return 0 -} - -//export access -func access(pathname *C.char, mode C.int) C.int { - fmt.Println("In access") - err := unix.Access(C.GoString(pathname), uint32(mode)) - if err != nil { - return -1 - } - return 0 -} - -//export chmod -func chmod(pathname *C.char, mode C.mode_t) C.int { - fmt.Println("In chmod") - err := unix.Chmod(C.GoString(pathname), uint32(mode)) - if err != nil { - return -1 - } - return 0 -} - -//export chown -func chown(pathname *C.char, owner C.uid_t, group C.gid_t) C.int { - fmt.Println("In chown") - err := unix.Chown(C.GoString(pathname), int(owner), int(group)) - if err != nil { - return -1 - } - return 0 -} - -//export close -func close(fd C.int) C.int { - fmt.Println("In close") - err := unix.Close(int(fd)) - if err != nil { - return -1 - } - return 0 -} - -//export creat -func creat(pathname *C.char, mode C.mode_t) C.int { - fmt.Println("In creat") - fd, err := unix.Creat(C.GoString(pathname), uint32(mode)) - if err != nil { - return -1 - } - return C.int(fd) -} - -//export euidaccess -func euidaccess(pathname *C.char, mode C.int) C.int { - fmt.Println("In euidaccess") - err := unix.Access(C.GoString(pathname), uint32(mode)) - if err != nil { - return -1 - } - return 0 -} - -//export faccessat -func faccessat(dirfd C.int, pathname *C.char, mode C.int, flags C.int) C.int { - fmt.Println("In faccessat") - err := unix.Faccessat(int(dirfd), C.GoString(pathname), uint32(mode), int(flags)) - if err != nil { - return -1 - } - return 0 -} - -//export fgetxattr -func fgetxattr(fd C.int, name *C.char, value unsafe.Pointer, size C.size_t) C.ssize_t { - fmt.Println("In fgetxattr") - buf := make([]byte, size) - n, err := unix.Fgetxattr(int(fd), C.GoString(name), buf) - if err != nil { - return -1 - } - copy(C.GoBytes(value, C.int(size)), buf[:n]) - return C.ssize_t(n) -} - -//export fstat -func fstat(fd C.int, cstat *C.struct_stat) C.int { - fmt.Println("In fstat") - ustat := (*unix.Stat_t)(unsafe.Pointer(cstat)) - error := unix.Fstat(int(fd), ustat) - if error != nil { - return -1 - } - return 0 -} - -//export getxattr -func getxattr(pathname *C.char, name *C.char, value unsafe.Pointer, size C.size_t) C.ssize_t { - fmt.Println("In getxattr") - buf := make([]byte, size) - n, err := unix.Getxattr(C.GoString(pathname), C.GoString(name), buf) - if err != nil { - return -1 - } - copy(C.GoBytes(value, C.int(size)), buf[:n]) - return C.ssize_t(n) -} - -//export lgetxattr -func lgetxattr(pathname *C.char, name *C.char, value unsafe.Pointer, size C.size_t) C.ssize_t { - fmt.Println("In lgetxattr") - buf := make([]byte, size) - n, err := unix.Lgetxattr(C.GoString(pathname), C.GoString(name), buf) - if err != nil { - return -1 - } - copy(C.GoBytes(value, C.int(size)), buf[:n]) - return C.ssize_t(n) -} - -//export link -func link(oldpath *C.char, newpath *C.char) C.int { - fmt.Println("In link") - err := unix.Link(C.GoString(oldpath), C.GoString(newpath)) - if err != nil { - return -1 - } - return 0 -} - -//export lseek -func lseek(fd C.int, offset C.off_t, whence C.int) C.off_t { - fmt.Println("In lseek") - newOffset, err := unix.Seek(int(fd), int64(offset), int(whence)) - if err != nil { - return -1 - } - return C.off_t(newOffset) -} - -//export mkdir -func mkdir(pathname *C.char, mode C.mode_t) C.int { - fmt.Println("In mkdir") - err := unix.Mkdir(C.GoString(pathname), uint32(mode)) - if err != nil { - return -1 - } - return 0 -} - -//export mknod -func mknod(pathname *C.char, mode C.mode_t, dev C.dev_t) C.int { - fmt.Println("In mknod") - err := unix.Mknod(C.GoString(pathname), uint32(mode), int(dev)) - if err != nil { - return -1 - } - return 0 -} - -//export mknodat -func mknodat(dirfd C.int, pathname *C.char, mode C.mode_t, dev C.dev_t) C.int { - fmt.Println("In mknodat") - err := unix.Mknodat(int(dirfd), C.GoString(pathname), uint32(mode), int(dev)) - if err != nil { - return -1 - } - return 0 -} - -//export open -func open(pathname *C.char, flags C.int, mode C.mode_t) C.int { - fmt.Println("In open") - fd, err := unix.Open(C.GoString(pathname), int(flags), uint32(mode)) - if err != nil { - return -1 - } - return C.int(fd) -} - -//export openat -func openat(dirfd C.int, pathname *C.char, flags C.int, mode C.mode_t) C.int { - fmt.Println("In openat") - fd, err := unix.Openat(int(dirfd), C.GoString(pathname), int(flags), uint32(mode)) - if err != nil { - return -1 - } - return C.int(fd) -} - -//export pread -func pread(fd C.int, buf unsafe.Pointer, count C.size_t, offset C.off_t) C.ssize_t { - fmt.Println("In pread") - n, err := unix.Pread(int(fd), (*[1 << 30]byte)(buf)[:count], int64(offset)) - if err != nil { - return -1 - } - return C.ssize_t(n) -} - -//export pwrite -func pwrite(fd C.int, buf unsafe.Pointer, count C.size_t, offset C.off_t) C.ssize_t { - fmt.Println("In pwrite") - n, err := unix.Pwrite(int(fd), (*[1 << 30]byte)(buf)[:count], int64(offset)) - if err != nil { - return -1 - } - return C.ssize_t(n) -} - -//export read -func read(fd C.int, buf unsafe.Pointer, count C.size_t) C.ssize_t { - fmt.Println("In read") - n, err := unix.Read(int(fd), (*[1 << 30]byte)(buf)[:count]) - if err != nil { - return -1 - } - return C.ssize_t(n) -} - -//export readlink -func readlink(pathname *C.char, buf unsafe.Pointer, bufsiz C.size_t) C.ssize_t { - fmt.Println("In readlink") - n, err := unix.Readlink(C.GoString(pathname), (*[1 << 30]byte)(buf)[:bufsiz]) - if err != nil { - return -1 - } - return C.ssize_t(n) -} - -//export rename -func rename(oldpath *C.char, newpath *C.char) C.int { - fmt.Println("In rename") - err := unix.Rename(C.GoString(oldpath), C.GoString(newpath)) - if err != nil { - return -1 - } - return 0 -} - -//export rmdir -func rmdir(pathname *C.char) C.int { - fmt.Println("In rmdir") - err := unix.Rmdir(C.GoString(pathname)) - if err != nil { - return -1 - } - return 0 -} - -//export symlink -func symlink(target *C.char, linkpath *C.char) C.int { - fmt.Println("In symlink") - err := unix.Symlink(C.GoString(target), C.GoString(linkpath)) - if err != nil { - return -1 - } - return 0 -} - -//export truncate -func truncate(pathname *C.char, length C.off_t) C.int { - fmt.Println("In truncate") - err := unix.Truncate(C.GoString(pathname), int64(length)) - if err != nil { - return -1 - } - return 0 -} - -//export unlink -func unlink(pathname *C.char) C.int { - fmt.Println("In unlink") - err := unix.Unlink(C.GoString(pathname)) - if err != nil { - return -1 - } - return 0 -} - -//export write -func write(fd C.int, buf unsafe.Pointer, count C.size_t) C.ssize_t { - fmt.Println("In write") - n, err := unix.Write(int(fd), (*[1 << 30]byte)(buf)[:count]) - if err != nil { - return -1 - } - return C.ssize_t(n) -} diff --git a/rtld.c b/rtld.c index 26e3dfd..0be5095 100644 --- a/rtld.c +++ b/rtld.c @@ -1,227 +1,431 @@ -#define RTLD_NEXT ((void *) -1L) +//go:build linux +// +build linux + +#define _GNU_SOURCE + #include "rtld.h" + #include +#include +#include +#include + +typedef int (*xstat_fn)(int, const char *, struct stat *); +typedef int (*fxstat_fn)(int, int, struct stat *); +typedef int (*fxstatat_fn)(int, int, const char *, struct stat *, int); +typedef int (*access_fn)(const char *, int); +typedef int (*chmod_fn)(const char *, mode_t); +typedef int (*chown_fn)(const char *, uid_t, gid_t); +typedef int (*close_fn)(int); +typedef int (*creat_fn)(const char *, mode_t); +typedef int (*euidaccess_fn)(const char *, int); +typedef int (*faccessat_fn)(int, const char *, int, int); +typedef ssize_t (*xattr_fn)(const char *, const char *, void *, size_t); +typedef ssize_t (*fxattr_fn)(int, const char *, void *, size_t); +typedef int (*fstat_fn)(int, struct stat *); +typedef int (*link_fn)(const char *, const char *); +typedef off_t (*lseek_fn)(int, off_t, int); +typedef int (*mkdir_fn)(const char *, mode_t); +typedef int (*mknod_fn)(const char *, mode_t, dev_t); +typedef int (*mknodat_fn)(int, const char *, mode_t, dev_t); +typedef int (*open_fn)(const char *, int, ...); +typedef int (*openat_fn)(int, const char *, int, ...); +typedef ssize_t (*pread_fn)(int, void *, size_t, off_t); +typedef ssize_t (*pwrite_fn)(int, const void *, size_t, off_t); +typedef ssize_t (*read_fn)(int, void *, size_t); +typedef ssize_t (*readlink_fn)(const char *, char *, size_t); +typedef int (*rename_fn)(const char *, const char *); +typedef int (*rmdir_fn)(const char *); +typedef int (*symlink_fn)(const char *, const char *); +typedef int (*truncate_fn)(const char *, off_t); +typedef int (*unlink_fn)(const char *); +typedef ssize_t (*write_fn)(int, const void *, size_t); + +static pthread_once_t resolve_once = PTHREAD_ONCE_INIT; + +static fxstat_fn real___fxstat; +static fxstatat_fn real___fxstatat; +static xstat_fn real___lxstat; +static xstat_fn real___xstat; +static access_fn real_access; +static chmod_fn real_chmod; +static chown_fn real_chown; +static close_fn real_close; +static creat_fn real_creat; +static euidaccess_fn real_euidaccess; +static faccessat_fn real_faccessat; +static fxattr_fn real_fgetxattr; +static fstat_fn real_fstat; +static xattr_fn real_getxattr; +static xattr_fn real_lgetxattr; +static link_fn real_link; +static lseek_fn real_lseek; +static mkdir_fn real_mkdir; +static mknod_fn real_mknod; +static mknodat_fn real_mknodat; +static open_fn real_open; +static openat_fn real_openat; +static pread_fn real_pread; +static pwrite_fn real_pwrite; +static read_fn real_read; +static readlink_fn real_readlink; +static rename_fn real_rename; +static rmdir_fn real_rmdir; +static symlink_fn real_symlink; +static truncate_fn real_truncate; +static unlink_fn real_unlink; +static write_fn real_write; + +static void resolve_symbols(void) { + real___fxstat = (fxstat_fn)dlsym(RTLD_NEXT, "__fxstat"); + real___fxstatat = (fxstatat_fn)dlsym(RTLD_NEXT, "__fxstatat"); + real___lxstat = (xstat_fn)dlsym(RTLD_NEXT, "__lxstat"); + real___xstat = (xstat_fn)dlsym(RTLD_NEXT, "__xstat"); + real_access = (access_fn)dlsym(RTLD_NEXT, "access"); + real_chmod = (chmod_fn)dlsym(RTLD_NEXT, "chmod"); + real_chown = (chown_fn)dlsym(RTLD_NEXT, "chown"); + real_close = (close_fn)dlsym(RTLD_NEXT, "close"); + real_creat = (creat_fn)dlsym(RTLD_NEXT, "creat"); + real_euidaccess = (euidaccess_fn)dlsym(RTLD_NEXT, "euidaccess"); + real_faccessat = (faccessat_fn)dlsym(RTLD_NEXT, "faccessat"); + real_fgetxattr = (fxattr_fn)dlsym(RTLD_NEXT, "fgetxattr"); + real_fstat = (fstat_fn)dlsym(RTLD_NEXT, "fstat"); + real_getxattr = (xattr_fn)dlsym(RTLD_NEXT, "getxattr"); + real_lgetxattr = (xattr_fn)dlsym(RTLD_NEXT, "lgetxattr"); + real_link = (link_fn)dlsym(RTLD_NEXT, "link"); + real_lseek = (lseek_fn)dlsym(RTLD_NEXT, "lseek"); + real_mkdir = (mkdir_fn)dlsym(RTLD_NEXT, "mkdir"); + real_mknod = (mknod_fn)dlsym(RTLD_NEXT, "mknod"); + real_mknodat = (mknodat_fn)dlsym(RTLD_NEXT, "mknodat"); + real_open = (open_fn)dlsym(RTLD_NEXT, "open"); + real_openat = (openat_fn)dlsym(RTLD_NEXT, "openat"); + real_pread = (pread_fn)dlsym(RTLD_NEXT, "pread"); + real_pwrite = (pwrite_fn)dlsym(RTLD_NEXT, "pwrite"); + real_read = (read_fn)dlsym(RTLD_NEXT, "read"); + real_readlink = (readlink_fn)dlsym(RTLD_NEXT, "readlink"); + real_rename = (rename_fn)dlsym(RTLD_NEXT, "rename"); + real_rmdir = (rmdir_fn)dlsym(RTLD_NEXT, "rmdir"); + real_symlink = (symlink_fn)dlsym(RTLD_NEXT, "symlink"); + real_truncate = (truncate_fn)dlsym(RTLD_NEXT, "truncate"); + real_unlink = (unlink_fn)dlsym(RTLD_NEXT, "unlink"); + real_write = (write_fn)dlsym(RTLD_NEXT, "write"); +} + +static void ensure_symbols(void) { + pthread_once(&resolve_once, resolve_symbols); +} + +#define REQUIRE_SYMBOL(sym) \ + do { \ + ensure_symbols(); \ + if ((sym) == NULL) {\ + errno = ENOSYS; \ + return -1; \ + } \ + } while (0) int orig___fxstat(int ver, int fd, struct stat *cstat) { - typedef int (*orig_fstat_t)(int, int, struct stat*); - orig_fstat_t orig_fstat = (orig_fstat_t) dlsym(RTLD_NEXT, "__fxstat"); - if (!orig_fstat) return -1; - return orig_fstat(ver, fd, cstat); + REQUIRE_SYMBOL(real___fxstat); + return real___fxstat(ver, fd, cstat); } int orig___fxstatat(int ver, int dirfd, const char *pathname, struct stat *cstat, int flags) { - typedef int (*orig_fxstatat_t)(int, int, const char*, struct stat*, int); - orig_fxstatat_t orig_fxstatat = (orig_fxstatat_t) dlsym(RTLD_NEXT, "__fxstatat"); - if (!orig_fxstatat) return -1; - return orig_fxstatat(ver, dirfd, pathname, cstat, flags); + REQUIRE_SYMBOL(real___fxstatat); + return real___fxstatat(ver, dirfd, pathname, cstat, flags); } int orig___lxstat(int ver, const char *pathname, struct stat *cstat) { - typedef int (*orig_lxstat_t)(int, const char*, struct stat*); - orig_lxstat_t orig_lxstat = (orig_lxstat_t) dlsym(RTLD_NEXT, "__lxstat"); - if (!orig_lxstat) return -1; - return orig_lxstat(ver, pathname, cstat); + REQUIRE_SYMBOL(real___lxstat); + return real___lxstat(ver, pathname, cstat); } int orig___xstat(int ver, const char *pathname, struct stat *cstat) { - typedef int (*orig_xstat_t)(int, const char*, struct stat*); - orig_xstat_t orig_xstat = (orig_xstat_t) dlsym(RTLD_NEXT, "__xstat"); - if (!orig_xstat) return -1; - return orig_xstat(ver, pathname, cstat); + REQUIRE_SYMBOL(real___xstat); + return real___xstat(ver, pathname, cstat); } int orig_access(const char *pathname, int mode) { - typedef int (*orig_access_t)(const char*, int); - orig_access_t orig_access = (orig_access_t) dlsym(RTLD_NEXT, "access"); - if (!orig_access) return -1; - return orig_access(pathname, mode); + REQUIRE_SYMBOL(real_access); + return real_access(pathname, mode); } int orig_chmod(const char *pathname, mode_t mode) { - typedef int (*orig_chmod_t)(const char*, mode_t); - orig_chmod_t orig_chmod = (orig_chmod_t) dlsym(RTLD_NEXT, "chmod"); - if (!orig_chmod) return -1; - return orig_chmod(pathname, mode); + REQUIRE_SYMBOL(real_chmod); + return real_chmod(pathname, mode); } int orig_chown(const char *pathname, uid_t owner, gid_t group) { - typedef int (*orig_chown_t)(const char*, uid_t, gid_t); - orig_chown_t orig_chown = (orig_chown_t) dlsym(RTLD_NEXT, "chown"); - if (!orig_chown) return -1; - return orig_chown(pathname, owner, group); + REQUIRE_SYMBOL(real_chown); + return real_chown(pathname, owner, group); } int orig_close(int fd) { - typedef int (*orig_close_t)(int); - orig_close_t orig_close = (orig_close_t) dlsym(RTLD_NEXT, "close"); - if (!orig_close) return -1; - return orig_close(fd); + REQUIRE_SYMBOL(real_close); + return real_close(fd); } int orig_creat(const char *pathname, mode_t mode) { - typedef int (*orig_creat_t)(const char*, mode_t); - orig_creat_t orig_creat = (orig_creat_t) dlsym(RTLD_NEXT, "creat"); - if (!orig_creat) return -1; - return orig_creat(pathname, mode); + REQUIRE_SYMBOL(real_creat); + return real_creat(pathname, mode); } int orig_euidaccess(const char *pathname, int mode) { - typedef int (*orig_euidaccess_t)(const char*, int); - orig_euidaccess_t orig_euidaccess = (orig_euidaccess_t) dlsym(RTLD_NEXT, "euidaccess"); - if (!orig_euidaccess) return -1; - return orig_euidaccess(pathname, mode); + REQUIRE_SYMBOL(real_euidaccess); + return real_euidaccess(pathname, mode); } int orig_faccessat(int dirfd, const char *pathname, int mode, int flags) { - typedef int (*orig_faccessat_t)(int, const char*, int, int); - orig_faccessat_t orig_faccessat = (orig_faccessat_t) dlsym(RTLD_NEXT, "faccessat"); - if (!orig_faccessat) return -1; - return orig_faccessat(dirfd, pathname, mode, flags); + REQUIRE_SYMBOL(real_faccessat); + return real_faccessat(dirfd, pathname, mode, flags); } ssize_t orig_fgetxattr(int fd, const char *name, void *value, size_t size) { - typedef ssize_t (*orig_fgetxattr_t)(int, const char*, void*, size_t); - orig_fgetxattr_t orig_fgetxattr = (orig_fgetxattr_t) dlsym(RTLD_NEXT, "fgetxattr"); - if (!orig_fgetxattr) return -1; - return orig_fgetxattr(fd, name, value, size); + REQUIRE_SYMBOL(real_fgetxattr); + return real_fgetxattr(fd, name, value, size); } int orig_fstat(int fd, struct stat *cstat) { - typedef int (*orig_fstat_t)(int, struct stat*); - orig_fstat_t orig_fstat = (orig_fstat_t) dlsym(RTLD_NEXT, "fstat"); - if (!orig_fstat) return -1; - return orig_fstat(fd, cstat); + REQUIRE_SYMBOL(real_fstat); + return real_fstat(fd, cstat); } ssize_t orig_getxattr(const char *pathname, const char *name, void *value, size_t size) { - typedef ssize_t (*orig_getxattr_t)(const char*, const char*, void*, size_t); - orig_getxattr_t orig_getxattr = (orig_getxattr_t) dlsym(RTLD_NEXT, "getxattr"); - if (!orig_getxattr) return -1; - return orig_getxattr(pathname, name, value, size); + REQUIRE_SYMBOL(real_getxattr); + return real_getxattr(pathname, name, value, size); } ssize_t orig_lgetxattr(const char *pathname, const char *name, void *value, size_t size) { - typedef ssize_t (*orig_lgetxattr_t)(const char*, const char*, void*, size_t); - orig_lgetxattr_t orig_lgetxattr = (orig_lgetxattr_t) dlsym(RTLD_NEXT, "lgetxattr"); - if (!orig_lgetxattr) return -1; - return orig_lgetxattr(pathname, name, value, size); + REQUIRE_SYMBOL(real_lgetxattr); + return real_lgetxattr(pathname, name, value, size); } int orig_link(const char *oldpath, const char *newpath) { - typedef int (*orig_link_t)(const char*, const char*); - orig_link_t orig_link = (orig_link_t) dlsym(RTLD_NEXT, "link"); - if (!orig_link) return -1; - return orig_link(oldpath, newpath); + REQUIRE_SYMBOL(real_link); + return real_link(oldpath, newpath); } off_t orig_lseek(int fd, off_t offset, int whence) { - typedef off_t (*orig_lseek_t)(int, off_t, int); - orig_lseek_t orig_lseek = (orig_lseek_t) dlsym(RTLD_NEXT, "lseek"); - if (!orig_lseek) return -1; - return orig_lseek(fd, offset, whence); + REQUIRE_SYMBOL(real_lseek); + return real_lseek(fd, offset, whence); } int orig_mkdir(const char *pathname, mode_t mode) { - typedef int (*orig_mkdir_t)(const char*, mode_t); - orig_mkdir_t orig_mkdir = (orig_mkdir_t) dlsym(RTLD_NEXT, "mkdir"); - if (!orig_mkdir) return -1; - return orig_mkdir(pathname, mode); + REQUIRE_SYMBOL(real_mkdir); + return real_mkdir(pathname, mode); } int orig_mknod(const char *pathname, mode_t mode, dev_t dev) { - typedef int (*orig_mknod_t)(const char*, mode_t, dev_t); - orig_mknod_t orig_mknod = (orig_mknod_t) dlsym(RTLD_NEXT, "mknod"); - if (!orig_mknod) return -1; - return orig_mknod(pathname, mode, dev); + REQUIRE_SYMBOL(real_mknod); + return real_mknod(pathname, mode, dev); } int orig_mknodat(int dirfd, const char *pathname, mode_t mode, dev_t dev) { - typedef int (*orig_mknodat_t)(int, const char*, mode_t, dev_t); - orig_mknodat_t orig_mknodat = (orig_mknodat_t) dlsym(RTLD_NEXT, "mknodat"); - if (!orig_mknodat) return -1; - return orig_mknodat(dirfd, pathname, mode, dev); + REQUIRE_SYMBOL(real_mknodat); + return real_mknodat(dirfd, pathname, mode, dev); } int orig_open(const char *pathname, int flags, mode_t mode) { - typedef int (*orig_open_t)(const char*, int, mode_t); - orig_open_t orig_open = (orig_open_t) dlsym(RTLD_NEXT, "open"); - if (!orig_open) return -1; - return orig_open(pathname, flags, mode); + REQUIRE_SYMBOL(real_open); + return real_open(pathname, flags, mode); } int orig_openat(int dirfd, const char *pathname, int flags, mode_t mode) { - typedef int (*orig_openat_t)(int, const char*, int, mode_t); - orig_openat_t orig_openat = (orig_openat_t) dlsym(RTLD_NEXT, "openat"); - if (!orig_openat) return -1; - return orig_openat(dirfd, pathname, flags, mode); + REQUIRE_SYMBOL(real_openat); + return real_openat(dirfd, pathname, flags, mode); } ssize_t orig_pread(int fd, void *buf, size_t count, off_t offset) { - typedef ssize_t (*orig_pread_t)(int, void*, size_t, off_t); - orig_pread_t orig_pread = (orig_pread_t) dlsym(RTLD_NEXT, "pread"); - if (!orig_pread) return -1; - return orig_pread(fd, buf, count, offset); + REQUIRE_SYMBOL(real_pread); + return real_pread(fd, buf, count, offset); } ssize_t orig_pwrite(int fd, const void *buf, size_t count, off_t offset) { - typedef ssize_t (*orig_pwrite_t)(int, const void*, size_t, off_t); - orig_pwrite_t orig_pwrite = (orig_pwrite_t) dlsym(RTLD_NEXT, "pwrite"); - if (!orig_pwrite) return -1; - return orig_pwrite(fd, buf, count, offset); + REQUIRE_SYMBOL(real_pwrite); + return real_pwrite(fd, buf, count, offset); } ssize_t orig_read(int fd, void *buf, size_t count) { - typedef ssize_t (*orig_read_t)(int, void*, size_t); - orig_read_t orig_read = (orig_read_t) dlsym(RTLD_NEXT, "read"); - if (!orig_read) return -1; - return orig_read(fd, buf, count); + REQUIRE_SYMBOL(real_read); + return real_read(fd, buf, count); } ssize_t orig_readlink(const char *pathname, void *buf, size_t bufsiz) { - typedef ssize_t (*orig_readlink_t)(const char*, void*, size_t); - orig_readlink_t orig_readlink = (orig_readlink_t) dlsym(RTLD_NEXT, "readlink"); - if (!orig_readlink) return -1; - return orig_readlink(pathname, buf, bufsiz); + REQUIRE_SYMBOL(real_readlink); + return real_readlink(pathname, (char *)buf, bufsiz); } int orig_rename(const char *oldpath, const char *newpath) { - typedef int (*orig_rename_t)(const char*, const char*); - orig_rename_t orig_rename = (orig_rename_t) dlsym(RTLD_NEXT, "rename"); - if (!orig_rename) return -1; - return orig_rename(oldpath, newpath); + REQUIRE_SYMBOL(real_rename); + return real_rename(oldpath, newpath); } int orig_rmdir(const char *pathname) { - typedef int (*orig_rmdir_t)(const char*); - orig_rmdir_t orig_rmdir = (orig_rmdir_t) dlsym(RTLD_NEXT, "rmdir"); - if (!orig_rmdir) return -1; - return orig_rmdir(pathname); + REQUIRE_SYMBOL(real_rmdir); + return real_rmdir(pathname); } int orig_symlink(const char *target, const char *linkpath) { - typedef int (*orig_symlink_t)(const char*, const char*); - orig_symlink_t orig_symlink = (orig_symlink_t) dlsym(RTLD_NEXT, "symlink"); - if (!orig_symlink) return -1; - return orig_symlink(target, linkpath); + REQUIRE_SYMBOL(real_symlink); + return real_symlink(target, linkpath); } int orig_truncate(const char *pathname, off_t length) { - typedef int (*orig_truncate_t)(const char*, off_t); - orig_truncate_t orig_truncate = (orig_truncate_t) dlsym(RTLD_NEXT, "truncate"); - if (!orig_truncate) return -1; - return orig_truncate(pathname, length); + REQUIRE_SYMBOL(real_truncate); + return real_truncate(pathname, length); } int orig_unlink(const char *pathname) { - typedef int (*orig_unlink_t)(const char*); - orig_unlink_t orig_unlink = (orig_unlink_t) dlsym(RTLD_NEXT, "unlink"); - if (!orig_unlink) return -1; - return orig_unlink(pathname); + REQUIRE_SYMBOL(real_unlink); + return real_unlink(pathname); } ssize_t orig_write(int fd, const void *buf, size_t count) { - typedef ssize_t (*orig_write_t)(int, const void*, size_t); - orig_write_t orig_write = (orig_write_t) dlsym(RTLD_NEXT, "write"); - if (!orig_write) return -1; + REQUIRE_SYMBOL(real_write); + return real_write(fd, buf, count); +} + +int __fxstat(int ver, int fd, struct stat *cstat) { + return orig___fxstat(ver, fd, cstat); +} + +int __fxstatat(int ver, int dirfd, const char *pathname, struct stat *cstat, int flags) { + return orig___fxstatat(ver, dirfd, pathname, cstat, flags); +} + +int __lxstat(int ver, const char *pathname, struct stat *cstat) { + return orig___lxstat(ver, pathname, cstat); +} + +int __xstat(int ver, const char *pathname, struct stat *cstat) { + return orig___xstat(ver, pathname, cstat); +} + +int access(const char *pathname, int mode) { + return orig_access(pathname, mode); +} + +int chmod(const char *pathname, mode_t mode) { + return orig_chmod(pathname, mode); +} + +int chown(const char *pathname, uid_t owner, gid_t group) { + return orig_chown(pathname, owner, group); +} + +int close(int fd) { + return orig_close(fd); +} + +int creat(const char *pathname, mode_t mode) { + return orig_creat(pathname, mode); +} + +int euidaccess(const char *pathname, int mode) { + return orig_euidaccess(pathname, mode); +} + +int faccessat(int dirfd, const char *pathname, int mode, int flags) { + return orig_faccessat(dirfd, pathname, mode, flags); +} + +ssize_t fgetxattr(int fd, const char *name, void *value, size_t size) { + return orig_fgetxattr(fd, name, value, size); +} + +int fstat(int fd, struct stat *cstat) { + return orig_fstat(fd, cstat); +} + +ssize_t getxattr(const char *pathname, const char *name, void *value, size_t size) { + return orig_getxattr(pathname, name, value, size); +} + +ssize_t lgetxattr(const char *pathname, const char *name, void *value, size_t size) { + return orig_lgetxattr(pathname, name, value, size); +} + +int link(const char *oldpath, const char *newpath) { + return orig_link(oldpath, newpath); +} + +off_t lseek(int fd, off_t offset, int whence) { + return orig_lseek(fd, offset, whence); +} + +int mkdir(const char *pathname, mode_t mode) { + return orig_mkdir(pathname, mode); +} + +int mknod(const char *pathname, mode_t mode, dev_t dev) { + return orig_mknod(pathname, mode, dev); +} + +int mknodat(int dirfd, const char *pathname, mode_t mode, dev_t dev) { + return orig_mknodat(dirfd, pathname, mode, dev); +} + +int open(const char *pathname, int flags, ...) { + mode_t mode = 0; + + if (flags & (O_CREAT | O_TMPFILE)) { + va_list args; + va_start(args, flags); + mode = (mode_t)va_arg(args, int); + va_end(args); + } + + return orig_open(pathname, flags, mode); +} + +int openat(int dirfd, const char *pathname, int flags, ...) { + mode_t mode = 0; + + if (flags & (O_CREAT | O_TMPFILE)) { + va_list args; + va_start(args, flags); + mode = (mode_t)va_arg(args, int); + va_end(args); + } + + return orig_openat(dirfd, pathname, flags, mode); +} + +ssize_t pread(int fd, void *buf, size_t count, off_t offset) { + return orig_pread(fd, buf, count, offset); +} + +ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset) { + return orig_pwrite(fd, buf, count, offset); +} + +ssize_t read(int fd, void *buf, size_t count) { + return orig_read(fd, buf, count); +} + +ssize_t readlink(const char *pathname, char *buf, size_t bufsiz) { + return orig_readlink(pathname, buf, bufsiz); +} + +int rename(const char *oldpath, const char *newpath) { + return orig_rename(oldpath, newpath); +} + +int rmdir(const char *pathname) { + return orig_rmdir(pathname); +} + +int symlink(const char *target, const char *linkpath) { + return orig_symlink(target, linkpath); +} + +int truncate(const char *pathname, off_t length) { + return orig_truncate(pathname, length); +} + +int unlink(const char *pathname) { + return orig_unlink(pathname); +} + +ssize_t write(int fd, const void *buf, size_t count) { return orig_write(fd, buf, count); } diff --git a/rtld.h b/rtld.h index 507e2ff..270b0bf 100644 --- a/rtld.h +++ b/rtld.h @@ -1,31 +1,17 @@ -typedef unsigned int mode_t; -typedef unsigned int uid_t; -typedef unsigned int gid_t; -typedef unsigned long dev_t; -typedef long off_t; -typedef long ssize_t; -typedef unsigned long size_t; +#ifndef RTLD_H +#define RTLD_H -typedef struct { - long tv_sec; - long tv_nsec; -} timespec; +#ifndef __linux__ +#error "rtld.h is only supported on Linux" +#endif -struct stat{ - unsigned long st_dev; - unsigned long st_ino; - unsigned long st_nlink; - unsigned int st_mode; - unsigned int st_uid; - unsigned int st_gid; - unsigned long st_rdev; - long st_size; - long st_blksize; - long st_blocks; - timespec st_atim; - timespec st_mtim; - timespec st_ctim; -}; +#define _GNU_SOURCE + +#include +#include +#include +#include +#include int orig___fxstat(int ver, int fd, struct stat *cstat); int orig___fxstatat(int ver, int dirfd, const char *pathname, struct stat *cstat, int flags); @@ -58,4 +44,6 @@ int orig_rmdir(const char *pathname); int orig_symlink(const char *target, const char *linkpath); int orig_truncate(const char *pathname, off_t length); int orig_unlink(const char *pathname); -ssize_t orig_write(int fd, const void *buf, size_t count); \ No newline at end of file +ssize_t orig_write(int fd, const void *buf, size_t count); + +#endif