疑难问题定位案例复盘(二)

news2024/11/23 13:29:52

        今天我们继续分析一个因野指针访问导致的内存异常、出现coredump问题。在上一篇案例中,我们分享了一个在内存被释放后,业务模块仍然在使用导致业务模块自身出现coredump的现象。其实,在使用野指针访问内存时还有一种可能,就是业务模块在使用野指针继续访问内存没有导致业务模块自身出现异常,但由于该块内存已经属于一块空闲内存,它被glibc的ptmalloc虚拟内存分配器管理所管理。ptmalloc分配器会在用户内存块的开头位置的前8个字节(在32位系统上)依次存放两个结构体指针fd和bk,它们分别指向空闲双向链表的前后节点,从而维护空闲链表上空闲内存块的连接(如unsorted bins)。内存块相关结构如下:

 可以想象,当业务模块继续使用野指针,当改写了内存块的头两个指针位置,即fd和bk,此时fd和bk将不再指向空闲双线链表的前后内存块节点。若此时刚好该进程的其他业务模块需要分配内存,ptmalloc刚好选择了该野指针指向的内存块。ptmalloc选择该空闲内存块时会进行相关的一系列校验,包括校验该空闲内存块的fd、bk指针是否指向其前后空闲内存块(如通过fd找到后一个空闲内存块,检查后一个内存块的前向指针bk是否指向自身)。若校验不合格,则说明内存异常,ptmalloc会发送abort信号结束当前进程并产生coredump

        本次分享的案例就是基于上述原因产生的问题。该类问题的难点在于产生coredump时记录的栈回溯只是单纯地利用malloc分配内存,它并不是内存被异常改写的源头,某种意义上它也只是个“受害者”,这给我们找到内存异常被改写源头带来的较大的麻烦。下面基于实例进行讲解,其中具体代码流程进行了简化。

问题现象

        测试环境在进行了将近40个小时的压力测试发现产生了一个coredump。通过初步分析,发现是利用malloc申请一个内存时,在glibc中产生了断言abort错误,从而产生了coredump。

问题分析

        像这类glibc中分配内存时产生abort断言错误,通常是由于内存被改写导致。针对内存被改写,具体又有2种场景,分别如下:

  1. 该内存块被前一个内存块越界改写。
  2. 该内存块已经被释放,但仍然被业务模块改写访问,破坏了管理数据结构,从而出现异常。

针对上述两种可能,我们分别进行分析并排查。

内存越界改写

        当内存块被其前一个内存块越界改写时,异常内存块的管理头结构malloc_chunk数据必将被破坏(暂不考虑跳跃式改写)。因此,为了验证这种可能,我们利用x命令打印出异常内存块的前面数据,发现内存块的管理头结构malloc_chunk数据正常(如表示内存块大小字段正常),并未发现明显改写,因此排除了这种可能。

野指针访问改写

        对于野指针访问改写场景,通常是由于将申请的内存块地址保存在了全局变量指针中,而在某些业务模块通过局部变量指针接受了该全局变量指针,在一些流程中通过局部变量指针释放了该内存块,但并未将全局变量指针置为NULL。而在其他业务模块中发现该全局变量指针不为空,则继续使用甚至改写了该内存,从而出现问题。

        为了验证这种可能,我们查找异常内存块指针是在哪个地方申请使用的。此时我们既可以通过打印相关内存块的特征字符串来查找,也可以通过内存块指针来查找。对于通过内存块指针来查找,我们有2种方法:

  • 一种是通过打印当前进程的相关全局指针变量,查看哪个全局指针变量指向了该异常内存块即为使用内存块的位置。
  • 另一种是通过find命令在当前进程的全局变量区域(即.data段)暴力查找。若找到,通过p /a形式打印该部分内存块即可显示该部分内存属于哪个全局变量。

通过上面两种方法我们可以找到异常内存块具体被哪个全局变量指针引用,这样我们跟踪该全局变量指针具体申请、释放的位置,特别重点排查通过局部变量释放了该内存、但未将全局变量指针置为NULL的情形。根据该思路我们确认了可疑处,确认存在通过局部指针释放了内存、但未将全局指针变量置为NULL,导致后续访问改写导致内存块异常。

相关示例代码如下:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/481964.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

存储资源调优技术——SmartVirtualization异构虚拟化技术

目录 基本概念 相关专业术语 eDevLUN与外部LUN的关系 对异构存储系统接管的方式 基本概念 异构虚拟化技术,仅对块业务生效 当本端存储系统与异构存储系统相互连接后;本端存储系统能够将异构存储系统提供的存储资源当作本地存储资源进行使用并对其进行集中…

模型参数量(Parameters)和计算量(FLOPs)获取【使用thop】

Tips: 针对部分开源代码没有提供相关计算网络参数量和计算量的代码。这里给出一个通用的获取网络的参数量和计算量的方法。 使用thop即可快速获取 1 模型参数量和计算量 参数量#params 即为网络模型中含有多少个参数,与输入的数据无关,主要与模型的结构…

在 windows 端使用 vscode + ubuntu WSL 优雅的使用原生 linux 的 gcc/g++ 编译

当我在windows上进行c的开发时,通常会使用 vs 但缺点也比较明显,他不原生的 gcc 编译器,其次 vs 这个 IDE 太过于庞大,当然也有很多人会使用 vscode 但是,在 windows 中安装 gcc/g 的过程极为复杂,且因为我…

【C++】右值引用完美转发

文章目录 右值引用和左值引用左值和右值概念左值引用 && 右值引用右值引用使用场景和意义左值引用的使用场景**左值引用的短板:**右值引用和移动语义STL容器增加的接口move函数右值引用的其他使用场景 完美转发万能引用完美转发保持值的属性完美转发的使用场景 右值引用…

Python基础合集 练习16(函数的递归)

简单的递归 1.求阶乘 比如输入为3 那么3216 输出就为6 def fun(n): if n1: return 1 return n*fun(n-1) numint(input(‘输入数字:’)) print(‘该数的阶乘为:’,fun(num)) 2.数列 这个数从第三项开始每一项为前一项的两倍 假如输入为6 则[1,1,2,3,5,8] 第六位为…

Python 时间处理模块

import time # 导入时间模块 s_time time.time() # 程序开始的时间 time.sleep(3) # 慢三秒 print(f’cost{time.time()-s_time}’) # 用当前时间减去之前程序开始的时间 print(time.localtime()) # 打印当前的时间 时间对象 print(time.gmtime()) # 打印当前时间&#xff0…

Python基础合集 练习18(类与对象2)

访问限制 class Dog_dog(): def init(self, name) -> None: self.__name name # 定义私有属性 def run(self):print(我跑的很快!我的名字是, self.__name)dog1 Dog_dog(‘papi’) dog1.run() print(dog1._Dog_dog__name) # 加入类名访问 print(’-----分界线-----’) p…

Mix.AI.How is your Chirper?

Chirper.ai是什么? 一个名为Chirper的AI驱动的社交网络平台。Chirper为AI用户建立了一个独立的环境,与传统的人类社交媒体平台有所区别。是一个独特的交互和协作空间,只有AI可以进行交流和互动。 shadow 看看我的AI化身每天都在干什么&#x…

Python---多线程编程、基于Socket完成服务端程序开发、基于Socket完成客户端程序开发

1. 进程: 程序在操作系统内运行,即成为一个运行进程 线程: 进程内部可以有多个线程,程序的运行本质上就是由进程内部的线程在实际工作的。 并行执行: 多个进程同时在运行,即不同的程序同时运行&#xff…

【Floyd】CF1204 Anna, Svyatoslav and Maps

看错题意了一直看不懂题解浪费了好多时间... 思路: 先去考虑特殊的地方: 100 子序列 最短路径 一个个剖析: 100:考虑Floyd 子序列:DP?不懂 最短路径:考虑Floyd 我们要求的是子序列的方案&#xff0…

【MySQL 8.0】搭建一个使用 SSL 加密的 MySQL 主从复制拓扑(基于 Binlog 行复制)

文章目录 先决条件搭建配置源、副本服务器选项文件 验证启用了 SSL 连接创建复制用户获取复制源服务器的二进制日志坐标配置复制源开启复制 验证进阶 之前,我们一起搭建了一个极简 MySQL 主从复制拓扑(基于 Binlog 行复制),这是一…

请问这个网址怎么用httpx 把json数据取出来

点击上方“Python爬虫与数据挖掘”,进行关注 回复“书籍”即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 空山新雨后,天气晚来秋。 大家好,我是皮皮。 一、前言 前几天在Python铂金群【gyx】问了一个Python网络爬虫处理的问题&#xf…

【JavaEE】认识线程

目录 1、什么是线程 2、为什么引入线程 2.1、线程的优缺点 3、CPU的工作原理 4、线程和进程的关系 4.1、线程和进程的入口函数 4.2、线程独享的资源 1、什么是线程 一个进程中可以有一个或者多个线程,每个线程都是一个独立的执行流。多个线程之间,也…

嵌入式开发--无刷电机学习3--帕克变换

帕克变换的物理意义 前面说到克拉克变换的物理意义,是将三相定子线圈产生磁场的过程,等效为2个正交放置的线圈,来产生同样的磁场。通过控制这两个正交线圈即可等效控制三相定子线圈。 还有一个问题,定子线圈产生的磁场&#xff…

集群与存储

所谓集群就是通过高速网络将很多服务器集中起来一起提供一种服务,在客户端看起来就是只有一个服务器 任务调度是集群中的核心系统 HPC高性能计算集群 LB负载均衡 HA高可用 LVS工作模式 NAT 网络地址转换 -m DR 路由模式 节点需要VIP -g TUN 隧道模式 -i 调度…

「Codeforces」D. Big Brush

D. Big Brush https://codeforces.com/contest/1638/problem/D 题目描述 给你一张 n m n\times m nm 大的网格纸,你有一把 2 2 2 \times 2 22 的刷子,每次只能涂满这么多,即 ( i , j ) 、 ( i 1 , j ) 、 ( i , j 1 ) 、 ( i 1 , j …

第二十二章 光照贴图

光照贴图过程将预先计算场景中静态物体表面的亮度,并将结果存储在称为“光照贴图”的纹理中供以后使用。光照贴图可以包含直接光照和间接光照,以及阴影效果。但是,烘焙到光照贴图中的数据无法在运行时更改,这就是为什么移动静态物…

Python入门教程+项目实战-12.1节: 字典的基础概念

目录 12.1.1 理解字典类型 12.1.2 字典的类型名 12.1.3 字典的定义 12.1.4 在循环中遍历字典 12.1.5 字典的键类型 12.1.6 知识要点 12.1.7 系统学习python 12.1.1 理解字典类型 在日常生活中,我们常常会接触到“字典”这种数据类型,例如一本书籍…

排序篇:直接插入、希尔、直接选择和堆排序(C语言)

目录 前言: 一:插入排序 (1)直接插入排序 基础思路(有个印象就行,主要看单趟): 单趟排序: 完整排序: 时间复杂度分析: (2)希尔排序 基础思路(有个印象就行,主要看单趟)&#…

【2023 年第十三届 MathorCup 高校数学建模挑战赛】D 题 航空安全风险分析和飞行技术评估问题 27页论文及代码

【2023 年第十三届 MathorCup 高校数学建模挑战赛】D 题 航空安全风险分析和飞行技术评估问题 27页论文及代码 1 题目 D 题 航空安全风险分析和飞行技术评估问题 飞行安全是民航运输业赖以生存和发展的基础。随着我国民航业的快速发展,针对飞行安全问题的研究显得…