简体   繁体   English

fstat()在预加载的mmap()系统调用中无法按预期工作

[英]fstat() does not work as expected inside a preloaded mmap() system call

I am trying to get the device minor and major numbers from fstat() . 我正在尝试从fstat()获得设备的次要和主要数字。 The call to fstat() is done inside a preloaded mmap() system call: fstat()的调用是在预加载的mmap()系统调用中完成的:

// preload.so
// compile with:
// gcc  -ldl -Wall -shared -fPIC -o preload.so -D_GNU_SOURCE preload.c
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <dlfcn.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>

#if __GNUC__ >= 4
#define PUBLIC __attribute__ ((visibility("default")))
#else
#define PUBLIC
#endif

PUBLIC void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) {
    printf("preload\n");

    struct stat sb;
    if (fstat(fd, &sb) == -1)
        printf("fstat() failed\n");
    else 
        printf("%u %u\n", major(sb.st_rdev), minor(sb.st_rdev));

    typedef void*(*mmap_t)(void *, size_t, int, int, int, off_t);
    mmap_t o_mmap = dlsym(RTLD_NEXT, "mmap");
    return (*o_mmap)(start, length, prot, flags, fd, offset);
}

The above library can then intercept any mmap() system call from any given program: 然后,上述库可以拦截来自任何给定程序的任何mmap()系统调用:

$ LD_PRELOAD=./preload.so ./my_prog

Why do I keep obtaining 0 and 0 as major and minor number, although my_prog attempts to mmap() a device after opening a real device node? 尽管my_prog在打开实际设备节点后尝试对设备进行mmap() ,但为什么我仍继续获得0和0作为主设备号和次设备号?

Is there any way to obtain the major and minor numbers from within the preloaded mmap() system call without any other informations except the arguments passed to the function itself? 有什么方法可以从预加载的mmap()系统调用中获取主号和副号,而无需传递任何其他信息(传递给函数本身的参数除外)?

mmap() will be called by a lot of other code as well, eg mmap()也将被许多其他代码调用,例如

  • To load/map shared libraries. 加载/映射共享库。
  • To obtain anonymous memory (eg malloc() might call mmap to obtain more memory) 获取匿名内存(例如,malloc()可能会调用mmap以获得更多内存)

In the first case, the mmap()'ed file is just a regular file, and will have have a minor/major of 0. In the second case, the fd passed in is not a valid fd - the app should pass -1 as the fd, but it might not.. 在第一种情况下,mmap()编辑的文件只是常规文件,次要/主要为0。在第二种情况下,传入的fd不是有效的fd-应用程序应通过-1作为fd,但事实并非如此。

You're likely seeing these mmap() calls from the runtime and indirectly from other library calls your application does, not just the mmap() call of a device that your app does. 您可能会在运行时看到这些mmap()调用,而在应用程序中间接看到其他库调用,而不仅仅是应用程序所执行的设备的mmap()调用。

On eg Linux/glibc, and possibly other systems as well, I'd presume an mmap() call could be compiled to call mmap64() instead, depending on compiler flags that's used to enable large file support. 在例如Linux / glibc以及可能的其他系统上,我假设可以编译mmap()调用来代替调用mmap64() ,具体取决于用于启用大文件支持的编译器标志。 You might need to intercept mmap64() as well as mmap() 您可能需要拦截mmap64()mmap()

It's unclear what you're really trying to do, but you could 目前尚不清楚您真正要做什么,但是您可以

  • check that fd is not -1 检查fd不是-1
  • check that the flags does not contain MAP_ANONYMOUS 检查标志是否不包含MAP_ANONYMOUS
  • then perform fstat. 然后执行fstat。
  • check the struct stat .st_mode for S_ISCHR() or S_ISBLK() (see the stat man page) to know if mmap() was for a device file 检查S_ISCHR()或S_ISBLK()的struct stat .st_mode(请参阅stat手册页)以了解mmap()是否用于设备文件
  • if the sb.st_rdev is for the major/minor number your interested in, take action. 如果sb.st_rdev是您感兴趣的主要/次要号码,请采取措施。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM