如何防止进程使用其他进程使用的内存?

时间:2015-12-16 07:04:45

标签: c memory-management

假设有两个进程:一个是我自己的进程,另一个进程生成随机内存地址并修改其中的内容(我们无法控制它)。

第一个过程(我自己的过程):

// Process 1
int *ptr = (int*)malloc(sizeof(int)); // Suppose the address is 0x138145800
*ptr = 45;
printf("%d", *ptr);
sleep();
printf("%d", *ptr);

第二个过程(我无法控制的外部过程):

// Process 2
int *ptr1;
ptr1 = (int*)0x138145800; // Random memory address is generated
*ptr1 = 25;
printf("%d", *ptr1);

当第一个进程处于休眠状态时,我们没有任何控制权的第二个进程会修改进程1使用的值。

如何通过仅更改第一个进程来防止第二个进程这样做?

一种可能的方法是使用锁。但是,为每个变量进程使用锁1使用效率非常低。有没有有效的方法来解决这个问题?

1 个答案:

答案 0 :(得分:2)

操作系统阻止程序通过设计访问另一个程序堆栈中的内存。没有程序需要担心这一点。

为了便于说明,我在CentOS映像上运行了这个场景:

计划1:

int main() {
  char *p = "Hello World";
}

当运行时产生:

Dump of assembler code for function main:
   0x00000000004004f0 <+0>:   push   %rbp
   0x00000000004004f1 <+1>:   mov    %rsp,%rbp
=> 0x00000000004004f4 <+4>:   movq   $0x4005a0,-0x8(%rbp)
   0x00000000004004fc <+12>:  mov    $0x0,%eax
   0x0000000000400501 <+17>:  pop    %rbp
   0x0000000000400502 <+18>:  retq   
End of assembler dump.

我们可以看到注册0x4005a0持有"Hello World"

(gdb) x /s 0x4005a0
0x4005a0:   "Hello World"

在不杀死前一个进程的情况下,我们可以运行另一个访问该寄存器的C程序:

int main() {
  char * hello_world = (char *) 0x4005a0;
  printf("%s", hello_world);
}

运行时,产生:

L??L??D??A??H??H9?u?H?[]A\A]A^A_?ff.?

在一个单独的GDB会话中(与两个程序分开):

(gdb) x /s 0x4005a0
0x4005a0:   <Address 0x4005a0 out of bounds>

因此,我们可以在这里观察现代记忆体系结构的一些原理。操作系统正在管理程序的内存,以便您所描述的方案不会发生。

在程序的第二次运行中,它实际上能够打印出一些文本(乱码),因为当程序运行时,实际上是分配了一个虚拟地址空间,根据定义,它是一组范围操作系统可用于进程的虚拟地址。虽然这两个程序使用相同的虚拟地址(0x4005a0),但在第二个实例中它只是空闲内存。

如果一个程序走出这个边界,操作系统将发送经典SIGSEGV并终止该程序。操作系统会根据内存访问冲突触发定义的分段错误。

从程序化的角度来看,没有什么可以做,也不需要做,因为这个内存管理由操作系统处理。你的程序在这方面是安全的,假设它在现代操作系统上运行。