我读到Linux中的进程描述符(在x86上)存储在内核数据段中,但存储在PAGE_OFFSET下面的地址(即用户地址空间中)。由于内核数据段和用户数据段都覆盖了完整的4GB地址空间,因此如果用户数据的地址已知,则可能通过用户数据段访问进程描述符。这是正确的,如果是的话,它不是安全漏洞吗?
一个相关问题:有一个断言,即流程描述符的线性地址可以作为唯一的进程ID。但是,由于线性地址使用页表进行转换,并且页面表对于PAGE_OFFSET以下的地址的每个进程都不同,那么两个进程是否可以将它们的进程描述符存储在相同的线性地址?
答案 0 :(得分:4)
在linux中,"进程描述符"是struct task_struct
[和其他一些人]。它们存储在用户空间的内核地址空间[上方PAGE_OFFSET
]和不中。
这与32位内核更相关,其中PAGE_OFFSET
设置为0xc0000000。
在32位内核中,用户进程虚拟地址空间限制为PAGE_OFFSET
64位内核有些不同,限制并不重要。 PAGE_OFFSET
是0xffff880000000000
此外,内核具有自己的单个地址空间映射。
每个进程/线程都有自己的虚拟地址空间,除了.so库的共享内存和线程的共享内存是唯一的。它不映射到内核地址空间中的任何内容。
即使[如果有]公共地址空间映射,内核页面也会被用户进程读/写保护。
相关问题:
这实际上是两个问题
有一个断言,即流程描述符的线性地址可以作为唯一的进程ID。
没有。由于某些原因,不可以完成。
只有内核才能访问({"知道")task_struct
地址。
其次,如果一个进程终止,它就是一个僵尸,直到父进程" reaps"它通过wait
。内核必须记住哪些进程是僵尸(即他们的pids
将不重新用于新进程),直到父进程收到它们。
task_struct
相当大。因此,当进程进入僵尸时,内核会抓取task_struct
数据的小部分(例如pid
和status
)并将其保存在&#中34;僵尸"结构。然后,内核可以立即重用task_struct
[使用不同的 pid]。
例如,虽然具有pid 37的进程可能在地址(例如)0x1000处有一个任务结构,但是在终止之后但在收到之前,pid 37有 no 任务结构地址并且0x1000处的任务结构可能已经分配给pid 23727
但是,由于线性地址使用页表进行转换,并且页面表对于PAGE_OFFSET以下的地址的每个进程都不同,那么两个进程是否不能将它们的进程描述符存储在相同的线性地址?
再一次,没有。