当前位置: 首页 > news >正文

网站会员整合广州最新疫情情况

网站会员整合,广州最新疫情情况,nginx wordpress 固定链接 404,广东省疫情最新消息今天一:背景 1. 讲故事 高级调试训练营里的一位朋友找到我,说他们跑在linux上的.NET程序出现了内存泄露的情况,上windbg观察发现内存都是IMAGE给吃掉了,那些image都标记了 doublemapper__deleted_ 字样,问我为啥会这样&a…

一:背景

1. 讲故事

高级调试训练营里的一位朋友找到我,说他们跑在linux上的.NET程序出现了内存泄露的情况,上windbg观察发现内存都是IMAGE给吃掉了,那些image都标记了 doublemapper__deleted_ 字样,问我为啥会这样?说实话作为我们这些调试者非常喜欢和这样的人打交道,毕竟沟通起来顺畅,也特别能激发对方的探索欲,这也是训练营给予的一种魅力吧。

二:内存暴涨分析

1. 为什么会暴涨

看过我这个系列的朋友都知道观察内存用 !address -summary 命令,但这个命令是为 windows 打造的,所以在 linux 上行不通,为此sos提供了一个专门的命令 !maddress 来替代,接下来使用 !maddress -orderBySize 观察下内存分布情况。


0:000> !maddress -orderBySize+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Memory Kind         |        StartAddr |        EndAddr-1 |         Size | Type        | State       | Protect           | Image                                                             | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Image               |     7f4000000000 |     7f4007ff6000 |     127.96mb | MEM_IMAGE   | MEM_COMMIT  | PAGE_READWRITE    | doublemapper__deleted_                                            | | Image               |     7f3fc4000000 |     7f3fcbff5000 |     127.96mb | MEM_IMAGE   | MEM_COMMIT  | PAGE_READWRITE    | doublemapper__deleted_                                            | | Image               |     7f404c021000 |     7f4051b4c000 |      91.17mb | MEM_IMAGE   | MEM_UNKNOWN | PAGE_UNKNOWN      | doublemapper__deleted_                                            | | Image               |     7f3fae82e000 |     7f3fb4000000 |      87.82mb | MEM_IMAGE   | MEM_COMMIT  | PAGE_EXECUTE_READ | doublemapper__deleted_                                            | | Image               |     7f406c021000 |     7f40701ff000 |      65.87mb | MEM_IMAGE   | MEM_UNKNOWN | PAGE_UNKNOWN      | doublemapper__deleted_    ...+----------------------------------------------------------------------+ | Memory Type         |          Count |         Size |   Size (bytes) | +----------------------------------------------------------------------+ | Image               |            980 |       3.54gb |  3,801,517,056 | | PAGE_READWRITE      |          1,178 |       1.17gb |  1,255,059,968 | | Stack               |             66 |     499.35mb |    523,604,992 | 
...| NewStubPrecodeHeap  |              4 |      64.00kb |         65,536 | +----------------------------------------------------------------------+ | [TOTAL]             |          8,254 |       6.01gb |  6,451,347,968 | +----------------------------------------------------------------------+ 

从卦象看,总计 6.4G 的内存使用,Image 就吃了 3.8G,从 details 看确实都标记了 doublemapper__deleted_,说实话我分析了300多例的dump,Image 吃了大头是第二次遇到,这种故障案例一般是可遇不可求的,接下来我们探究下 doublemapper__deleted_ 为何方神圣。

2. doublemapper__deleted_ 是什么

要想找到这个答案,先从 coreclr 源代码中寻找蛛丝马迹,全局检索之后很快发现了关键词 doublemapper相关的代码:


bool VMToOSInterface::CreateDoubleMemoryMapper(void** pHandle, size_t *pMaxExecutableCodeSize)
{
#ifndef TARGET_OSX#ifdef TARGET_FREEBSDint fd = shm_open(SHM_ANON, O_RDWR | O_CREAT, S_IRWXU);
#elif defined(TARGET_SUNOS) // has POSIX implementationchar name[24];sprintf(name, "/shm-dotnet-%d", getpid());name[sizeof(name) - 1] = '\0';shm_unlink(name);int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600);
#else // TARGET_FREEBSDint fd = memfd_create("doublemapper", MFD_CLOEXEC);
#endif // TARGET_FREEBSD*pMaxExecutableCodeSize = MaxDoubleMappedSize;*pHandle = (void*)(size_t)fd;
#else // !TARGET_OSX*pMaxExecutableCodeSize = SIZE_MAX;*pHandle = NULL;
#endif // !TARGET_OSXreturn true;
}

从卦象看,真尼玛乱,coreclr 为了兼容各种操作系统核,加了无数的 if,else 判断,无语了,最后在非OSX,非FREEBSD,非SUNOS的情况下走了 memfd_create 函数,到这里事情有了一些进展了。

熟悉 Linux 的朋友应该知道 memfd_create 是一个 Linux 系统调用,用于创建一个匿名文件描述符,如果在 Windows 上找等价函数的话,那就是 win32api 中的 CreateFileMapping 函数,即内存映射文件,这个在源码目录中也能观之一二:

可能有些朋友对 memfd_create 的使用还是有些模糊,我让 chatgpt 帮我生成一段简单的 demo 辅助大家理解下,简化后如下:


int main() {const char *name = "example_memfd";int fd;size_t size = 1024; // 1 KBvoid *map;const char *text = "Hello, memfd_create!";// Create the memory file descriptorfd = memfd_create(name, MFD_CLOEXEC);// Resize the memory file to the desired sizeftruncate(fd, size)// Map the memory file into the address spacemap = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);// Write some data to the memory filestrncpy(map, text, strlen(text));// Print the data from the memory fileprintf("Data in memory file: %s\n", (char *)map);// Unmap the memorymunmap(map, size)// Close the file descriptorclose(fd);return 0;
}

卦中的逻辑非常简单,需要注意的是这里有一个重要步骤就是通过 mmap 将 fd 挂上物理内存,即 fd -> mmap <- memory,挂上之后就可以轻松的往里面写数据了。

有了这些基础之后,大家再看 doublemapper__deleted_ 字样是不是有种豁然开朗的感觉?大概就是资源释放中只执行了 close(fd),但没有执行 mummap,参考如下:

// Unmap the memory (某种原因未执行)//munmap(map, size)  // Close the file descriptorclose(fd);

哈哈,当然我的推测不一样对,熟悉 linux 的朋友可以指点指点。 接下来研究方向在哪里呢?既然我已经推测出貌似存在某种逻辑bug,但 coreclr 代码不是我们写的,所以我能不能绕过去呢?

3. 可以绕过 memfd_create 吗?

要想知道能不能绕过去,还得从源代码中寻找答案,天不负有心人,还真给找到了,简化后的代码如下:


bool ExecutableAllocator::Initialize()
{if (IsDoubleMappingEnabled()){if (!VMToOSInterface::CreateDoubleMemoryMapper(&m_doubleMemoryMapperHandle, &m_maxExecutableCodeSize)){g_isWXorXEnabled = false;return true;}m_CriticalSection = ClrCreateCriticalSection(CrstExecutableAllocatorLock,CrstFlags(CRST_UNSAFE_ANYMODE | CRST_DEBUGGER_THREAD));}return true;
}bool ExecutableAllocator::IsDoubleMappingEnabled()
{#if defined(HOST_OSX) && defined(HOST_ARM64)return false;
#elsereturn g_isWXorXEnabled;
#endif
}bool ExecutableAllocator::g_isWXorXEnabled = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_EnableWriteXorExecute) != 0;RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableWriteXorExecute, W("EnableWriteXorExecute"), 1, "Enable W^X for executable memory.");

从卦中代码看,最终是由 EnableWriteXorExecute 外部变量控制的,那这个变量是什么意思呢?其实它是操作系统和CPU联合提供的功能,在 https://en.wikipedia.org/wiki/W%5EX 上对 W^X 特性做了介绍,大概意思就是:

它是一种内存保护策略,根据该策略,进程或内核地址空间中的每个页面要么是可写的,要么是可执行的,但不能同时具备这两种属性,如果没有这种保护,程序就可以在原本用于存储数据的内存区域中写入(作为数据 “W”)CPU 指令,然后运行(作为可执行代码 “X”;或读 - 执行 “RX”)这些指令。如果写入内存的一方怀有恶意,这就会带来危险。

而且 EnableWriteXorExecute 这东西导致的问题在 github 上有很多的讨论:

  1. https://github.com/dotnet/runtime/issues/97765
  2. https://stackoverflow.com/questions/77164379/how-do-i-debug-a-net-core-console-app-with-windbg-by-launch-executable
  3. https://github.com/dotnet/runtime/issues/79469

大家给出的建议都是将其关闭,操作方式如下:


export DOTNET_EnableWriteXorExecute=0

让朋友关闭了这个选项之后,朋友反馈程序运行正常。

4. 到底是什么代码导致的

虽然可以通过 export DOTNET_EnableWriteXorExecute=0 搞定这个问题,那到底是什么业务导致产生了很多的 doublemapper 呢?这就需要从这些内存段上寻找答案了,仔细想想,既然是内存文件嘛,大概率承载了 .NET 的 dll 文件,而 dll 文件都是魔术 MZ 开头的。所以使用 s-a 抽查其中一个内存段。


0:000> s-a 7f3fc4000000 7f3fcbff5000-0x1 "MZ"
00007f3f`c4059ce4  4d 5a 00 00 00 00 00 00-00 00 00 00 7c 00 00 00  MZ..........|...
00007f3f`c44f2989  4d 5a 3c 40 7f 00 00 b1-05 00 00 94 99 00 00 80  MZ<@............
00007f3f`c44f2b69  4d 5a 3c 40 7f 00 00 b1-05 00 00 98 99 00 00 40  MZ<@...........@
00007f3f`c44f3d99  4d 5a 3c 40 7f 00 00 b2-05 00 00 ac 99 00 00 80  MZ<@............
00007f3f`c44f4d49  4d 5a 3c 40 7f 00 00 b2-05 00 00 b6 99 00 00 80  MZ<@............
00007f3f`c45a3c61  4d 5a c4 3f 7f 00 00 00-00 00 00 00 00 00 00 cd  MZ.?............
00007f3f`c45a3ca1  4d 5a c4 3f 7f 00 00 00-00 00 00 00 00 00 00 cd  MZ.?............
00007f3f`c45a3ce1  4d 5a c4 3f 7f 00 00 00-00 00 00 00 00 00 00 cd  MZ.?............
00007f3f`c45a3d21  4d 5a c4 3f 7f 00 00 00-00 00 00 00 00 00 00 cd  MZ.?............
...

然后用了一段私藏的脚本导出来后,发现是大量的项目dll,这个就不截图了,朋友也有说他们程序有动态生成代码的逻辑。

四:总结

EnableWriteXorExecute 特性是在 .NET7 之后默认将0设为1的,在某些开源linux上会因为各种兼容性问题导致各种奇葩的问题发生,这东西我感觉目前还是能禁掉就禁掉吧。

http://www.yidumall.com/news/22320.html

相关文章:

  • 网站网站设计的公司项目推广计划书
  • 机械公司简介模板潍坊seo建站
  • 六安做网站公司关键词排名优化品牌
  • 黑马网站建设长沙百度开户
  • 越秀营销型网站站长工具外链查询
  • c 可以做网站吗网络营销策划ppt范例
  • 如何制作手机版网页福建优化seo
  • 温州网站建设制作爱站网挖掘词
  • 一流的五屏网站建设推广的软件有哪些
  • 淄博知名的做网站推广网络服务器是指什么
  • 东莞高端品牌网站建设手机注册网站
  • 基于jsp的网站建设论文上海百度搜索排名优化
  • wordpress制作xmlseo每天一贴
  • 汕头网站推广网络营销论文5000字
  • 做360手机网站优小广告怎么能弄干净
  • 自己做的网站怎么备案无锡seo优化
  • 现在有哪些网站是做批发的品牌策划方案模板
  • 郑州php网站开发培训百度站长工具seo
  • 数据开放网站建设内容域名访问网站入口
  • 网站备案能查到什么东西南京seo排名
  • 网站开发用什么简单seo排名赚挂机赚钱软件下载
  • 看b站直播有哪些网站建设首页
  • 湖南又出现5例天津seo顾问
  • 哪里有做网站公司的济南网站推广
  • 重庆vi设计公司百度seo排名优
  • 网站开发加维护需要多少钱seo自媒体运营技巧
  • 小企业财务软件免费版搜索引擎优化的含义和目标
  • 网站飘动广告代码全国新冠疫情最新消息
  • 网站做联盟收入seo外链建设方法
  • 做鱼网站的域名网站推广和精准seo