4

我可以将elf中的默认虚拟地址(ph_vaddr)更改为0x0吗?这将允许访问空指针吗?还是内核不允许在地址 0 加载?

我只想知道,如果我将某些部分的 p_vaddr 说 .text 更改为 0x0,linux 是否允许这样做?是否存在一些限制,虚拟地址只能在某个值之后开始?每当我尝试使用 ld --section-start 在 0 到 9999 之间的任何位置设置 .text vaddr 时,它都会被杀死。我想知道这是怎么回事??

4

2 回答 2

3

我可以将elf中的默认虚拟地址(ph_vaddr)更改为0x0吗?

是的,实际上这就是PIE(位置无关的)可执行文件通常是如何链接的。

echo "int main() { return 0; }" | gcc -xc - -fPIE -pie -o a.out
readelf -l a.out | grep LOAD | head -1

LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000

注意:上面生成了一个类型为ET_DYN.

这将允许访问空指针吗?

不会。当内核发现.e_type == ET_DYN可执行文件的时候,它将把它的所有段重新定位到别处。

您还可以使用 制作类型的可执行文件ET_EXEC.p_vaddr == 0如下所示:

echo "int main() { return 0; }" | gcc -xc - -o a.out -Wl,-Ttext=0
readelf -l a.out | grep LOAD | head -1
  LOAD           0x0000000000200000 0x0000000000000000 0x0000000000000000

内核将拒绝运行它:

./a.out
Killed
于 2013-10-19T15:41:51.823 回答
0

您可以mmap(2)开始MAP_FIXED的段,(void*)0但我认为您不应该这样做。

我不知道改变elf(5)中的虚拟地址是否会做同样的事情。你说的p_vaddr是某个细分市场吗?

实际上,您真的不应该NULL在 Linux 上的应用程序代码中使用地址,尤其是如果其中一些代码是用 C 编码的,因为NULL指针具有非常特殊的含义,包括对编译器的含义。特别是,一些优化是基于NULL不可取消引用的事实进行的。

众所周知,GCC 确实进行了优化,例如,

 x = *p;
 if (!p) goto wasnull;

into 只是x= *p;因为 ifp已被取消引用,它不能是NULL; GCC 对应用程序代码进行优化是正确的(而不是独立的)。

内核通常也在做Address Space Layout Randomization

于 2013-10-18T04:22:35.297 回答