我如何清理由“ out”指针参数创建的分配结构?

问题描述 投票:1回答:2

我有一个结构变量,其传递方式如下:

  //function definition
   void function1(const Node* aVAR1)
    {
        Node* value=NULL;
        .....
   }
   int main()
   {
    Node* aVAR=NULL;
    aVAR=x.value;

    function1(aVAR);
   }

[这里,当我在gdb中运行它并进入function1()时,我看到为变量aVAR创建了一个临时内存地址。

GDB:

21     aVAR=x.value;         
(gdb) p aVAR
$5 = (Node *) 0x654321
(gdb) n

Breakpoint 1, function1(aVAR1=0x7ffffffffebcdf ) at debug/../abc.c:12
12 {
(gdb) p aVAR1
$6 = (const Node *) 0x7ffffffffebcdf 

例如,

  1. 最初,aVAR的地址是0x654321
  2. 稍后,直到不执行function1()中的第一条指令,aVAR1会保留在某些临时地址中,例如0x7ffffffffebcdf
  3. 执行完Node* value=NULL;中的第一条指令function1()后,aVar1的地址再次为0x654321
  4. 但是这个临时(0x7ffffffffebcdf)地址没有被清除:即使在函数退出后,0x7ffffffffebcdf也不会被清除

我希望在函数退出后清除0x7ffffffffebcdf,但是0x7ffffffffebcdf地址没有指针,我可以通过该指针访问该内存。在GCC中进行链接时是否可以防止这种情况?

如果我为aVAR添加一个malloc并稍后使用memset和free将其清除,则当我看到时,该问题将在逻辑上得以解决,但我丢失了对malloc()分配的内存块的引用,而我将无法free()分配的内存(导致内存泄漏)。

c pointers memory-address pass-by-pointer
2个回答
1
投票

我希望在函数退出后清除0x7ffffffffebcdf ...

我的想象力有限,但是我可以想像您想要的原因之一是:

  1. 您认为它仍在使用;它不是,它超出范围,并且无法访问。
  2. 如果碰巧是可到达的,因为您已将其地址存储在某个地方,则说明您犯了一个错误,即无法归零。
  3. 您遇到安全问题,并且要确保清除临时内存。

因此,给定[3],有两种选择;在主返回之前将代码更改为零;或将main()更改为mymain():

int mymain() {
    Node* aVAR=NULL;
    aVAR=x.value;

    function1(aVAR);
    return something;
}
void clearstack() {
     int data[1000];
     int fd;
     if ((fd = open("/dev/zero", O_RDONLY)) != -1) {
          read(fd, data, sizeof data);
          close(fd);
     }
}
int main() {
    int r = mymain();
    clearstack();
    return r;
}

this works,因为堆栈地址将在两个函数调用之间重叠,因此您的0x7f-febcdf将落在data []的中间。实现定义的行为合唱团现在应该热身了。但实际上,您最好使用:

int mymain() {
    Node* aVAR=NULL;
    aVAR=x.value;

    function1(aVAR);
    aVAR = 0;
    dummyfunction(&aVAR);
    return aVAR == 0;
}

请注意,通过将aVAR的地址提供给虚拟函数,您会干扰编译器删除可能认为无用的内容的能力。但是,这种行为很难预测,因为它将您的程序源绑定到您可以使用的任何版本的编译器。前景不大。

如果volatile在定义上有严格的要求,在这里会很有用,但没有。

一个更好的方法是使用malloc()来获取变量,然后您受一个合同约束,该合同是内存[而局部变量只能是寄存器],可以在释放之前对其进行清理它。编译器优化清理工作将处于无法接受的行为的外部。它仍然可能使数据保留在某些寄存器中,这可能会泄漏出去。

所有这些都说;如果攻击者真的想发现程序中的纯文本机密,则可能无法阻止它们。他们可以在调试器或管理程序下启动您的程序,然后随意检查数据。

[在某些现代处理器中,有一些概念,CPU可以构造一种安全区域,可以安全地解开秘密;但是有很多缺陷。 ARM TrustZone's Secure/Normal world vs. OS's kernel/user mode or x86's Ring0/1/2/3?有更多信息。


2
投票

在您呈现的内容中,您有两个称为aVAR的变量。第一个是main中的局部变量,第二个是function1的参数。两者都位于自动存储(或您所说的“临时”存储)中,因此当包含它们的函数退出时将不复存在。无需任何特殊操作即可释放它们。

[仅需要释放指向的结构(假设它是malloc的,并且只需要执行一次,无论在其生命周期中有多少个指针指向它。

总之,您只需要每个free / malloc一个calloc。 (尽管请记住,strdup将调用malloc,并且将NULL传递给realloc实际上是malloc。)

© www.soinside.com 2019 - 2024. All rights reserved.