暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

He3DB内存越界问题定位

原创 魏小龙 2023-11-06
309

问题复现场景

目前,ubuntu稳定出现,centos环境不一定复现,启动pg为主He3DB为备,使用psql连接He3DB查询,每次退出时,日志出现无效指针释放问题。

image.png

日志:

image.png

退出客户端:
image.png

日志:

image.png

问题分析

Ubuntu环境He3DB日志在每次psql客户端退出时日志都会打印free函数出现无效指针,同时出现core文件。

#0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=140190718969344) at ./nptl/pthread_kill.c:44

#1 __pthread_kill_internal (signo=6, threadid=140190718969344) at ./nptl/pthread_kill.c:78

#2 __GI___pthread_kill (threadid=140190718969344, signo=signo@entry=6) at ./nptl/pthread_kill.c:89

#3 0x00007f80b1642476 in __GI_raise (sig=sig@entry=6) at …/sysdeps/posix/raise.c:26

#4 0x00007f80b16287f3 in __GI_abort () at ./stdlib/abort.c:79

#5 0x00007f80b1689676 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7f80b17dbb8c “%s\n”) at …/sysdeps/posix/libc_fatal.c:155

#6 0x00007f80b16a0cfc in malloc_printerr (str=str@entry=0x7f80b17d9764 “free(): invalid pointer”) at ./malloc/malloc.c:5664

#7 0x00007f80b16a2a44 in _int_free (av=, p=, have_lock=0) at ./malloc/malloc.c:4439

#8 0x00007f80b16a5453 in __GI___libc_free (mem=) at ./malloc/malloc.c:3391

#9 0x00007f80b395954a in ?? () from /lib/x86_64-linux-gnu/libtasn1.so.6

#10 0x00007f80b3959658 in ?? () from /lib/x86_64-linux-gnu/libtasn1.so.6

#11 0x00007f80b1c7d1a2 in ?? () from /lib/x86_64-linux-gnu/libgnutls.so.30

#12 0x00007f80b3b9624e in _dl_fini () at ./elf/dl-fini.c:142

#13 0x00007f80b1645495 in __run_exit_handlers (status=0, listp=0x7f80b1819838 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at ./stdlib/exit.c:113

#14 0x00007f80b1645610 in __GI_exit (status=) at ./stdlib/exit.c:143

image.png

proc_exit退出时,调用系统exit函数报错,报错的core文件很多信息都打印不出来都是optimized out。因此,要打印最后一个出错的指针,只有在线调试,出现这种报错大概率内存地址被污染了。

image.png

he3db bug定位

定位步骤:

  1. 找到最后一个指针释放出错的地方。

  2. psql 连接到he3db 执行psql -p5433

  3. ps -ef|grep postgres

image.png

  1. gdb -p 150360设置断点为free的地方,因为每次退出都core,我先看下出错时是不是每次都是同一个地址访问

image.png

  1. \q退出客户端

image.png

image.png

  1. 查找最后一个出错的指针。内存越界访问,正常情况下很难定位,而现在每次core的地址都一样相对比较好定位些,现在唯一能做的事情就是看看这地址上存的什么数据,发现是”pagedata”字符串说明代码在存pagedata字符串那块应该有问题

image.png

向前打印一些字符串,这就是本地盘目录

image.png

  1. 查找代码He3DB唯一用到pagedata的地方就是创建本地盘目录数据的地方。

image.png

filePath是申请空间的指针,GetPageDataFile函数给空间赋值的地方

image.png

sprintf是给空间赋值的地方,该函数会在字符串结尾加上\0,因为“%s/%s”多了一个/字符,结尾再多一个\0,那length申请长度不够,这个空间就超了一个字符。

image.png

下面举例看下sprintf
image.png
image.png

虽然没有出现core,但sprintf对内存占用完全没有限制,我理解当内存布局别的地方需要使用越界空间时就会出问题,我们这边先用个临时方案将空间扩大一个,后期需要使用snprintf来限制空间越界。

image.png

  1. 编译重新启动,验证psql连主机退出,发现已经没有再报错。
  2. 另外,还有问题InitPageFile()函数是在ServerLoop函数里面,ServerLoop函数在startup进程启动之后的,如果startup进程调用InitPageFile里面全局变量filePath时,filePath可能还没有初始化的情况,或者目录还没有建的情况,存在一定风险。

小结

一般内存越界问题后期找很难查找,所以预防内存越界在编写代码时需要有严格的边界场景考虑,以免后期无法定位,这次比较幸运的地方打印p (char*)地址时能打印出相关字符串,如果是个随机字符串,那基本很难定位了。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论