mmap - 当 mmap 和 memcpy 特定文件(/sys/devices/pci~~ 递归文件)时内核崩溃
问题描述
我看到resource0~4文件是/sys/devices/pci0000:00:xx.x的子文件之一,在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;
}
解决方案
这是正常的,如果读取某些硬件会更改状态。除非您了解相应硬件的行为方式以及您的更改如何影响控制同一硬件的其他软件,否则请勿访问这些文件。
推荐阅读
- c++ - reference to std::shared:ptr to avoid reference counting
- angular - 将 JSON 对象数组解析为 TypeScript 对象数组
- r - R sf: Points of LinearRing do not form a closed linestring
- mongodb - Class 'MongoDB\Driver\WriteConcern' not found in /var/www/html/jobget_admin_latest/system/core/Loader.php on line 1278
- swift - Avoiding Vapor migrations on a new database
- javascript - 如何防止在 JavaScript 数组中保存重复的段落?
- javascript - 开玩笑 - 不输出测试结果
- java - 异常:java.lang.IllegalStateException:无法转换 OneToOne 映射的类型值
- python - Django:非活动帐户的电话验证
- delphi - 将 Report Builder 报告发送到打印机时,DBText 字段会向下移动