diff options
author | Lucas Fryzek <lucas.fryzek@fryzekconcepts.com> | 2024-07-07 23:56:35 +0100 |
---|---|---|
committer | Lucas Fryzek <lucas.fryzek@fryzekconcepts.com> | 2024-07-07 23:56:35 +0100 |
commit | 87542bf71f0f594c5d567ea815439c2f98754754 (patch) | |
tree | 852f53ada37a29cc3166d2efae7ee371aa825460 /drvemu.c | |
parent | cfebe5825512d187ce2d4ff98ee74e8da8eb901e (diff) |
Get LD_PRELOAD library to highjack driver
Diffstat (limited to 'drvemu.c')
-rw-r--r-- | drvemu.c | 155 |
1 files changed, 153 insertions, 2 deletions
@@ -1,25 +1,176 @@ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> +#include <stdint.h> +#include <stdarg.h> +#include <string.h> #include <assert.h> #include <dlfcn.h> +#include <dirent.h> + +#include <sys/mman.h> +#include <sys/syscall.h> + +#include <asm-generic/ioctl.h> + +#include "xf86drm.h" + +#define DRM_PVR_RESERVED1 (DRM_COMMAND_BASE + 0) +#define DRM_PVR_RESERVED2 (DRM_COMMAND_BASE + 1) +#define DRM_PVR_RESERVED3 (DRM_COMMAND_BASE + 2) +#define DRM_PVR_RESERVED4 (DRM_COMMAND_BASE + 3) +#define DRM_PVR_RESERVED5 (DRM_COMMAND_BASE + 4) +#define DRM_PVR_RESERVED6 (DRM_COMMAND_BASE + 5) + +/* PVR includes */ +#define SUPPORT_MEMINFO_IDS +#define SUPPORT_DRI_DRM_EXT +#include <config_kernel.h> +#include <sgxfeaturedefs.h> +#include <pvr_bridge.h> +#include <sgx_bridge.h> +#include <pvr_drm_shared.h> +#include <sgxconfig.h> +#include <sgx_mkif_km.h> +//#include <pvr_drm.h> + +static int false_fd = 10241024; + #define PROLOG(func) \ static typeof(func) *orig_##func = NULL; \ if(!orig_##func) \ orig_##func = dlsym(RTLD_NEXT, #func); +int open(const char *pathname, int flags, mode_t mode) { + printf("Called open on %s (%d)\n", pathname, flags); + PROLOG(open); + return orig_open(pathname, flags, mode); +} + int open64(const char *pathname, int flags, ...) { printf("Called open64 on %s (%d)\n", pathname, flags); PROLOG(open64); int fd = orig_open64(pathname, flags); - //check_fd(fd, pathname); + if (strcmp(pathname, "/dev/dri/renderD128") == 0) { + printf("Spoofing FD!\n"); + return false_fd; + } return fd; } +#define DEV_NAME "pvr" +#define DEV_DATE "20110701" +#define DEV_DESC "Imagination Technologies PVR DRM" + +static bool spoof_ioctl(int fd, int request, void *ptr) { + int ioctl_nr = _IOC_NR(request); + switch(ioctl_nr) { + case _IOC_NR(DRM_IOCTL_VERSION): { + printf("Spoofing device info\n"); + drmVersionPtr version = (drmVersionPtr)ptr; + version->version_major = 1; + version->version_minor = 13; + version->version_patchlevel = 3341330; + version->name_len = sizeof(DEV_NAME); + version->date_len = sizeof(DEV_DATE); + version->desc_len = sizeof(DEV_DESC); + + if (version->name) + strcpy(version->name, DEV_NAME); + if (version->date) + strcpy(version->date, DEV_DATE); + if (version->desc) + strcpy(version->desc, DEV_DESC); + + break; + } + +#if 0 + case _IOC_NR(DRM_IOCTL_GET_MAGIC): + printf(">>> ioctl(DRM_IOCTL_GET_MAGIC)\n"); + break; + case _IOC_NR(DRM_IOCTL_GET_UNIQUE): + printf(">>> ioctl(DRM_IOCTL_GET_UNIQUE)\n"); + break; + case _IOC_NR(DRM_IOCTL_SET_VERSION): + printf(">>> ioctl(DRM_IOCTL_SET_VERSION)\n"); + { + struct drm_set_version *data = ptr; + printf("\t%d %d %d %d\n", data->drm_di_major, + data->drm_di_minor, + data->drm_dd_major, + data->drm_dd_minor); + } + break; +#endif + case _IOC_NR(DRM_IOCTL_DROP_MASTER): + printf(">>> ioctl(DRM_IOCTL_DROP_MASTER)\n"); + return 0; + case PVR_DRM_SRVKM_CMD: + printf("srv command 0x%x\n", PVR_DRM_SRVKM_CMD); + //fwrite(ptr, 1, sizeof(PVRSRV_BRIDGE_PACKAGE), log_file); + //PPRINT(stdout, ptr, PVRSRV_BRIDGE_PACKAGE); + //return pvrsrv_ioctl(fd, ptr); + break; + case PVR_DRM_IS_MASTER_CMD: + printf(">>> ioctl(PVR_DRM_IS_MASTER_CMD) 0x%x\n", PVR_DRM_SRVKM_CMD); + /* From KMD source code this seems to always return 0 */ + break; + default: + printf("Unimplemented ioctl 0x%x\n", ioctl_nr); + assert(false); + break; + } + return 0; +} + +int ioctl(int fd, int request, ...) { + PROLOG(ioctl); + int ioc_size = _IOC_SIZE(request); + bool pvr = fd == false_fd; + + //printf("Size is %d\n", ioc_size); + void *ptr = NULL; + if(ioc_size) { + va_list args; + va_start(args, request); + ptr = va_arg(args, void *); + va_end(args); + } + + printf("Got ioctl %d!\n", fd); + + if (pvr) + return spoof_ioctl(fd, request, ptr); + else + return orig_ioctl(fd, request, ptr); +} + int openat(int dirfd, const char *pathname, int flags, ...) { - assert(false && "openat not implemented"); printf("Called openat on %s (%d) (%d)\n", pathname, dirfd, flags); PROLOG(openat); + return orig_openat(dirfd, pathname, flags); } + +int openat64(int fd, const char * path, int oflag, ...) { + printf("Called openat64 %s\n", path); + PROLOG(openat64); + return orig_openat64(fd, path, oflag); +} + +DIR *opendir(const char *dirname) { + printf("Opening dir %s\n", dirname); + PROLOG(opendir); + return orig_opendir(dirname); +} + +struct dirent *readdir(DIR *dirp) { + PROLOG(readdir); + struct dirent *out = orig_readdir(dirp); + if (out) { + //printf("Reading %d %d %s\n", (int)out->d_type, (int)out->d_reclen, (char*)out->d_name); + } + return out; +} |