GMSSL与Net-SNMP冲突的原因与解决方法(security service 3 error parsing ScopedPDU)

问题描述:

  事情的起因,是在项目中添加了使用国密SSL的模块DLT860之后,SNMP修改密码失败,报错信息为:

security service 3 error parsing ScopedPDU
security service 3 error parsing ScopedPDU
security service 3 error parsing ScopedPDU
security service 3 error parsing ScopedPDU
security service 3 error parsing ScopedPDU
security service 3 error parsing ScopedPDU
Timeout: No Response from 127.0.0.1
(......重复四次......)

      研究代码多日,不得原因,网络上也鲜有相关信息。一日偶然发现,修改Makefile中的链接顺序,将Net-SNMP库的链接前移,可解决此问题,但又会导致国产61850协议工作异常。遂怀疑是因为这两个模块的符号冲突,使用以下命令导出静态库的所有符号:

sudo nm libcrypto_gm.a > ~/tmp/gmcrypto.txt
sudo nm libnetsnmp.a > ~/tmp/netsnmp.txt

     对比发现确实有重名符号,且国密SSL与Openssl的部分实现不同,定位问题根源。但由于两个模块需要同时使用,不能舍弃任何一方,因此采用野蛮方法:将net-snmp库中的重名符号全部修改(添加后缀),修改完毕后问题修复(一定不能有遗漏)。

  最后说说,为何链接的顺序会导致此问题出现。UNIX链接器在解析外部引用时,在符号解析的阶段,链接器从左到右按照它们在编译器驱动程序命令行上出现的相同顺序来扫描可重定位目标文件和库文件。在这次扫描中,链接器维持一个可重定位目标文件的集合E(这个集合中的文件会被合并起来形成可执行文件),一个未被解析的符号(即被引用了但是尚未定义的符号)集合U,以及一个在前面输入文件中已定义的符号集合D。初始时,E、U和D都是空的。

 对于命令行上的每个输入文件f,链接器会判断f是一个目标文件还是一个库文件。如果f是一个目标文件,那么链接器把f添加到E,修改U和D来反映f中的符号定义和引用,并继续下一个输入文件。如果f是一个库文件,那么链接器就尝试匹配U中未解析的符号和由库文件成员定义的符号。如果某个库文件成员m定义了一个符号来解析U中的一个引用,那么就将m加到E中,并且链接器修改U和D来反映m中的符号定义和引用。对库文件中所有的成员目标文件都反复进行这个过程,直到U和D都不再发生变化。在此时,任何不包含在E中的成员目标文件都简单地被抛弃,而链接器将继续处理下一个输入文件。

   如果当链接器完成对命令行上输入文件的扫描后,U是非空的,那么链接器就会输出一个错误(即undefined reference)并终止。否则,它会合并和重定位E中的目标文件,从而构建输出的可执行文件。

 在这里,当net-snmp在DLT860之后链接时,对于那些重名的符号,链接器已经扫描到并将其移出未解析符号集合U,因此在链接net-snmp时这些符号就不会被链接进去了,net-snmp实际工作时调用的是国密SSL中定义的那些函数与结构,这也正是交换链接顺序,会修复一个而破坏另一个的原因。

posted @ 2021-09-16 13:59  买菜不买挂  阅读(274)  评论(0编辑  收藏  举报