【问题标题】:Kernel panic when mmap and memcpy specific files(/sys/devices/pci~~ recursive files)当 mmap 和 memcpy 特定文件(/sys/devices/pci~~ 递归文件)时内核崩溃
【发布时间】:2019-04-01 01:58:35
【问题描述】:

看到/sys/devices/pci0000:00:xx.x的子文件之一的resource0~4文件后mmap后memcpy后出现kernel panic的现象。

目前这种现象只在真实的物理服务器中发现,在vm这样的环境中是没有的。

在这种情况下会发生这种情况吗?

这些特殊文件不是内存映射到mmap吗?

调用read()函数时出现errno 5并处理异常。 但, 映射到 mmap 不是 map_failed。

这种行为正常吗? 如果我的应用程序崩溃了,我不知道,但是会出现内核恐慌并询问。

尝试一个简单的示例源代码

#include "errno.h"
#include "fcntl.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "stddef.h"
#include "sys/types.h"
#include "sys/mman.h"
#include "dirent.h"

int recursive_dir(char *dir);
int exec_file(char *file);

main(void) {

    // error 
    recursive_dir((char *)"/sys/devices");

    // not error 
//  recursive_dir((char *)"/tmp");
}

int recursive_dir(char *dir)
{
    DIR            *pdir = NULL;
    char           file[1024];
    struct stat    f_stat;
    struct dirent  entry, *result = NULL;

    if ( (pdir = opendir(dir)) == NULL) {
        printf("opendir(%s) fail.\n", dir);
        return -1;
    }

    while (readdir_r(pdir, &entry, &result) == 0 && result != NULL) {
        if (entry.d_ino == 0) {
            printf("[scan_dir] entry [%s].d_ino is 0. continue\n", entry.d_name);
            continue;
        }

        if (strcmp(entry.d_name, ".") == 0 ||
                strcmp(entry.d_name, "..") == 0) {
            continue;
        }

        if (strcmp(dir, "/") == 0) {
            snprintf(file, sizeof(file), "/%s", entry.d_name);
        } else {
            snprintf(file, sizeof(file), "%s/%s", dir, entry.d_name);
        }

        if (lstat(file, &f_stat) == -1) {
            continue;
        }

        if (S_ISLNK(f_stat.st_mode)) {
            printf("[%s] is symbolic link. continue\n", file);
            continue;
        } else if (S_ISDIR(f_stat.st_mode)) {
            recursive_dir(file);
        } else if (S_ISREG(f_stat.st_mode)) {
            exec_file(file);
        }
    }

    closedir(pdir);
    return 0;
}


int exec_file(char *file)
{
    int   my_offset = 0;
    char  data[101] = {0,};
    int   fd;
    int   len;
    void  *address;
    struct stat f_stat;

    // occurrence error file 
    //if ((fd = open("/sys/devices/pci0000:00/0000:00:1b.0/resource0", O_RDONLY)) == -1) {
    if ((fd = open(file, O_RDONLY)) == -1) {
        return -1;
    }

    if (lstat(file, &f_stat) == -1) {
        close(fd);
        return -1;
    }

    if ((len = f_stat.st_size) == 0) {
        close(fd);
        return -1;
    }
    printf("file [%s] size [%d]\n", file, len);

    my_offset = 0;

    memset(data, 0x00, sizeof(data));

    address =  mmap(NULL,
            len,
            PROT_READ,
            MAP_SHARED,
            fd,
            my_offset);

    if ( address != MAP_FAILED ) {
        memcpy(data, address, 100); /* copy memory */
    }

    munmap(address, len);
    close(fd);

    return 0;
}

【问题讨论】:

    标签: mmap memcpy


    【解决方案1】:

    这是正常的,如果读取某些硬件会改变状态。除非您了解相应硬件的行为方式以及您的更改如何影响控制同一硬件的其他软件,否则请勿访问这些文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-30
      • 1970-01-01
      • 1970-01-01
      • 2019-03-21
      • 1970-01-01
      相关资源
      最近更新 更多