深入剖析Linux函数参数压栈顺序,解锁APUE的奥秘 (linux 函数参数压栈顺序 apue)

深入剖析Linux函数参数压栈顺序,解锁APUE的奥秘

在Linux系统中,函数的参数传递是通过栈(Stack)来实现的。当函数被调用时,会将函数的参数从右往左依次压入栈中。而函数使用参数的顺序则是从左往右。这个过程看似简单,实则有其奥秘。

在函数参数传递的过程中,我们可以通过观察汇编代码来了解函数参数的压栈顺序。每次函数的调用都会产生一系列指令,这其中包含了将参数压入栈中的操作。在GCC编译器中,函数参数处理的过程不会产生任何指令序列。而是通过调用C库中实现的函数来完成参数的压栈和参数的传递过程。因此,我们需要查看函数的汇编代码来深入理解函数参数的压栈顺序。

在x86架构中,函数的参数传递是通过栈(Stack)来实现的。CPU中的栈是一个LIFO(后进先出)的结构,可以理解成一个弹夹,每次调用函数都会向栈中插入一颗子弹,当函数返回后,会从栈中取出该子弹。如果有多个函数被嵌套调用,那么栈就会形成多个层次,每个子函数都有自己的栈。因此,我们需要关注的是内层函数的栈上面的元素是如何影响外层函数的栈的。

在函数参数的传递过程中,GCC编译器会将参数从右往左依次压入栈中。这是因为参数的个数在编写代码时是不确定的,通过从右往左压栈的方式可以避免调用方的代码需要优化。从汇编代码中我们可以看到,压栈顺序是和参数顺序相反的,这和我们在C语言中知道的顺序是相反的。这个看似反常的做法是出于一些重要的考虑因素。从右往左压入栈是因为栈是后进先出的数据结构。从而让栈指针指向最后一个参数,使参数在栈中存储的位置是连续的,便于读取。从右往左压入栈便于使用长度可变的参数列表调用函数,例如printf()函数。这样的话,将可变长度参数的地址传递给printf()函数,printf()就可以从这个地址上读取参数。

除了从右往左依次压入栈中,GCC编译器还会将地址全部按8字节对齐。对于64位系统,64位参数的推入栈中是通过两个32位或一个64位值来推入的。这样做是因为整个系统都是64位的,而32位的整数读取比其他大小的整数更加高效。在调用过程中,参数存储在栈的本地变量中。在从栈中取出这些参数并将数据复制到其他地方后,本地变量会被弹出栈。

这里需要注意的是,在使用变长参数列表的函数(如printf()函数)中,压栈顺序和压栈的数量是不确定的。由于变长参数列表是以…结尾的,编译器不知道有多少参数。在编写可变参数函数的代码时,需要了解编译器如何读取这些参数。

在Linux系统中,我们可以通过man手册查看函数的使用方法和函数的参数顺序。但是使用man手册仅仅是了解函数的使用方法,并不能深入理解底层的工作原理。对于程序员来说,只有对底层的工作原理有深刻的理解,才能写出更加高效、安全、稳定的程序。因此,要在程序开发中深入剖析Linux函数参数压栈顺序,才能真正解锁APUE的奥秘。

针对Linux函数参数压栈的深入研究,我们可以拓展以下几个方向:

1. 结合调试工具(gdb)来查看汇编代码中函数参数的压栈顺序,进一步理解函数的实现原理。

2. 研究函数参数传递的过程中,栈的局部性(Locality)和缓存的命中率(Cache Hit)。这可以优化程序的性能。

3. 探索不同架构下函数参数传递的方法,例如ARM、MIPS等架构。

4. 研究可变参数列表的函数实现原理,这对于设计线程安全(Lock-Free)数据结构有很大的帮助。

在中,我们可以明确Linux函数的参数传递是通过栈(Stack)来实现的,每次调用函数都会从右往左依次压入参数。这样的做法是为了避免调用方的代码需要优化和方便使用长度可变的参数列表调用函数。我们还可以通过调试工具(gdb)和研究缓存命中率等方面来进一步剖析其实现原理。只有这样,才能更好的解锁APUE的奥秘。

相关问题拓展阅读:

linux和unix系统函数有区别吗?在两个系统中开发是否相同

基本一样;看APUE就可以,态伍2种服务器都可以开发,当然solaris差别大点,他是微内核的,但是帆渗或系统接口都喊祥差不多,

数据库自主安全防护如何实现 数据库自主安全防护技术介绍【详解】

摘 要: 针对目前主流数据库的安全防护功能配置方式不灵活、不能应变需求的问题,在HOOK技术的基础上融入组态思想,设计并实现了一种适用于不同数据库的自主安全防护系统(DSS)。在SQLITE上的相关实验表明,利用DSS完全可以实现独立于特定数据库的自主安全防护,大大提高了数据安全防护的灵活性。

  关键词: 数据库安全; HOOK API; 访问控制; 数据库审计; SQLITE; 自主安全系统

  近年来,有关数据库的安全事故不断出现,例如银行内部数据信息泄露造成的账户资金失密等。因此,高度重视数据库安全防护很有必要。但一直以来,国内数据库产业化发展缓慢,市场份额中较大一部分被国外大型数据库企业占有。这对于国内用户而言,信息的安全性、稳定性等方面都会受到威胁。有的系统涉及使用多个数据库,并且对每个数据库的安防功能要求各不相同。这样,在保障整个系统安全的目标下就需要对每个数据库进行专门配置管理,不但维护难度很大,而且工作也比较繁重。面对这些实际问题,目前的数据库系统自带的安全防护配置方式已不能胜任,如何提出一个灵活独立的安全防护系统迫在眉睫。

  1 相关安全防护技术介绍

  目前,数据库系统面临的主要威胁有:(1)对数据库的不正确访问引起数据库数据的错误。(2)为了某种目的,故意破坏数据库。(3)非法访问不该访问的信息,且又不留痕迹;未经授权非法修改数据。(4)使用各种技术攻击数据库等。多年来,人们在理论和实践上对数据库系统安全的研究做出了巨大的努力,也取得了很多成果。参考文献介绍了保护数据库安全的常用技术,包括:存取管理技术、安全管理技术、以及数据库加密技术,并给出了一些实现途径。其中,访问控制和安全审计作为数据库安全的主要保障措施受到了人们广宽戚泛关注,参考文献对访问控制技术中的基本策略进行了总结,给出了实现技术及各自的优缺点。参考文献主要针对权限建模过程中的权限粒度问御巧帆题做了分析,并提出一个基于角色的访问控制框架。进入21世纪以后,访问控制模型的研究重点开始逐渐由集中式封闭环境转向开放式网络环境,一方面结合不同的应用,对原有传统模型做改进,另一方面,也提出一些新的访问控制技术和模型,比较著名的有信任管理、数字版权管理和使用控制模型 。审计通过对数据库内活动的记录和分析来发现异常并产生报警的方式来加强数据库的安全性。目前,在我国使用的商品化关系数据库管理系统大都提供了C2级的审计保护功能,但实现方式和功能侧重有所不同。周洪昊等人分析了Oracle、SQL Server、DB2、Sybase的审计功能,分别从审计系统的独立性、自我保护能力、全面性和查阅能力四个方面对审计功能做出改进。参考文献则针对审计信息冗余、审计配置方式死板以及数据统计分析能力不足等问题,在数据库系统已有的审计模块基础上,重新设计和实现了一种新型的数据库安全审计系统。

  但所有的这些工作都是从 数据库 系统的角度出发,并没有从镇雹本质上解决安全防护对数据库系统的依赖性问题,用户还是很难对数据库提供自主的安全防护功能。如果能将安全防护从数据库管理系统中彻底独立出来,针对不同的应用需求允许用户自己实现安全防护功能模块并在逻辑上加入到数据库应用系统中,这样问题也就迎刃而解了。

  通过以上分析,本文提出一种独立于具体数据库、可组态的安全防护模型,并给出具体的实现方法。该模型将安全防护从数据库完全独立出来,在多数据库应用中实现集中配置安防,满足用户对于自主防护功能的需求。并在开源的嵌入式数据库产品SQLITE中做了功能测试,实验结果表明,该模型切实可行,达到了预想的效果,既能实现对系统的保护,又大大提高了系统的灵活性。

  2 自主安全防护系统的设计与实现

  自主安全防护系统DSS(Discretionary Safety System)的主要功能是阻止用户对信息的非法访问,在可疑行为发生时自动启动预设的告警流程,尽可能防范数据库风险的发生,在非法操作发生时,触发事先设置好的防御策略,实行阻断,实现主动防御,并按照设置对所发生的操作进行详细记录,以便事后的分析和追查。

  2.1 系统结构

  在DSS中,安全管理员使用角色机制对用户的权限进行管理,通过制定安全策略来设置核心部件Sensor以及访问控制部件。核心部件Sensor侦听用户的数据库操作请求,采用命令映射表将不同的命令映射为系统识别的命令,提取出安全检查所需要的信息,发送到访问控制模块进行安检。安检通过了则允许用户访问数据库,否则拒绝访问,同时根据审计规则生成记录存入审计日志。

  DSS作为独立的功能模块主要通过向Sensor提供数据库的调用接口的方式保障对数据库信息安全合理地访问。系统有一个默认的访问控制流程,用户也可以自己设定安全策略,系统自动生成相应访问控制流程。本文约定被访问的对象为客体,请求操作的用户为主体。

  2.2 系统实现

  系统实现主要分为系统数据字典设计、用户登录与用户管理、系统相关策略制定、侦听器(Sensor)的实现、访问控制以及日志审计六部分。原数据库API信息(dll)、用户的自主防护策略作为输入,Sensor核心一方面将用户的防护策略融合在原数据库的API接口中,另一方面记录用户对数据库的操作并生成日志,提供给用户做审计。用户在使用过程中不需要修改原有系统,即可实现自主防护。

  Sensor由API处理模块、访问控制模块(Access Control)、Sensor核心模块(Core)、注射模块四部分组成。Core是Sensor的核心部件,主要负责拦截接口,解析并分离接口中的重要信息,使程序转入自定义的安检程序中执行安全检查。Access Control组件实现不同级别的访问控制,根据用户提供的安检信息,组态出对应的安防模块,并在合适的时候调用其进行访问控制。API(dll)主要将数据库系统提供的接口信息,转化为dll以便Sensor侦听时使用。Inject/Eject为Sensor提供远程注射的功能。

  Core通过拦截对API的调用来实现定制功能。程序在调用API函数之前,首先要把API所在的动态链接库载入到程序中;然后将API函数的参数、返回地址(也就是函数执行完后,下一条语句的地址)、系统当前的环境(主要是一些寄存器的值)压入系统调用栈;接着,进入到API函数的入口处开始执行API函数,执行过程中从系统调用栈中取出参数,执行函数的功能,返回值存放在EAX寄存器中,最终从堆栈中取出函数的返回值并返回(参数压栈的顺序还要受到调用约定的控制,本文不详细介绍)。

  举例说明函数调用时堆栈的情况。假设调用约定采用_stdcall,堆栈由高向低递减,API为Int func(int a, int b, int c)。

  拦截主要通过HOOK API技术实现,可以拦截的操作包括DOS下的中断、Windows中的API调用、中断服务、IFS和NDIS过滤等。目前微软提供了一个实现HOOK的函数库Detours。其实现原理是:将目标函数的前几个字节改为jmp指令跳转到自己的函数地址,以此接管对目标函数的调用,并插入自己的处理代码。

  HOOK API技术的实质是改变程序流程。在CPU的指令集中,能够改变程序流程的指令包括JMP、CALL、INT、RET、RETF、IRET等。理论上只要改变API入口和出口的任何机器码,都可以实现HOOK。但实际实现上要复杂得多,主要需要考虑如何处理好以下问题:(1)CPU指令长度。在32 bit系统中,一条JMP/CALL指令的长度是5 B,因此只需要替换API中入口处的前5 B的内容,否则会产生不可预料的后果。(2)参数。为了访问原API的参数,需要通过EBP或ESP来引用参数,因此需要明确HOOK代码中此时的EBP/ESP的值。(3)时机问题。有些HOOK必须在API的开头,如CreateFileA( )。有些必须在API的尾部,如RECV()。(4)程序上下文内容的保存。在程序执行中会涉及修改系统栈的内容,因此注意保存栈中原有内容,以便还原。(5)在HOOK代码里尽量杜绝全局变量的使用,以降低程序之间的耦合性。通过以上的分析,整理出如图4所示的实现的流程。

  DSS与传统数据库的安全防护功能相比,具有以下特点:

  (1)独立于具体的数据库。这种独立性体现在:①DSS只需要数据库提供其接口信息即可工作。②支持不同标准的SQL语句,通过数据库命令映射表可将非标准的SQL语句映射为系统设置的SQL命令。③系统自身数据的物理存储是独立于数据库的。

  (2)灵活性和针对性的统一。用户可以根据自己的需要配置针对特定应用的相关规则。

  (3)完善的自我安全保护措施。DSS只有数据库安全管理员和安全审计员才能访问。安全管理员和安全审计员是一类特殊的用户,他们只负责安全方面的操作,而不能访问数据库中的数据。这与Oracle等的数据库不同,在这些数据库中,DBA可以进行所有的操作。DSS系统本身具有故障恢复能力,能使系统出现问题时恢复到一个安全的状态。

  (4)完备的信息查阅和报警功能。在DSS中,本文提供了便利的设计查阅工具,方便用户对系统进行监控。另外,用户也可以自己定义报警条件和报警处理措施,一旦满足报警条件,系统就会自动地做出响应。

  3 实验及结果分析

  DSS的开发主要采用VS 2023实现,开发完成后在一台主频为2.8 GHz、内存2 GB、装有Windows 2023操作系统的普通 PC机上对其进行了功能和性能的测试,使用的数据库是开源的嵌入式数据库SQLite 3.6。为了搭建测试环境,需要在SQLite中添加初始化系统自身的数据字典,并开发应用程序。测试内容包括:登录、用户管理、Sensor、访问控制、日志审计以及增加DSS前后数据库系统安全性变化等功能性测试和增加DSS系统后对数据库性能的影响两方面。其中,性能测试主要从时间和资源的增加情况来说明,针对不同数据库对象分别在五个级别(20 000、40 000、60 000、80 000、)的数据上进行了插入和查询操作测试。为了做好性能对比,在SQLite中也添加了相同的访问控制功能,记为Inline Processing。

  从功能测试结果可以看出,DSS可以为数据库系统提供自主防护。从性能测试的结果中看出,查询操作和插入操作耗时相差比较大,这主要是SQLite工作方式引起的,在执行用户的插入操作时,数据库需将内存中的数据写入磁盘数据库文件中,占用了一部分时间。而查询时,SQLite会将数据库文件部分内容缓存起来,加快了查询的速度。另外,增加DSS会对性能有略微的影响,但是它能实现对数据库系统自主保护。

关于linux 函数参数压栈顺序 apue的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » 深入剖析Linux函数参数压栈顺序,解锁APUE的奥秘 (linux 函数参数压栈顺序 apue)