Linux进程描述符在哪里存储,什么可以访问?

我读过Linux中的进程描述符(在x86上)存储在内核数据段中,但在PAGE_OFFSET(即在用户地址空间中)的地址中。 由于内核数据段和用户数据段都覆盖了全部4GB的地址空间,因此如果用户代码知道其地址,则可能通过用户数据段访问进程描述符。 这是正确的,如果是的话,这不是一个安全漏洞?

一个相关的问题:有一个断言,进程描述符的线性地址可以作为一个唯一的进程ID。 但是,由于线性地址使用页表进行翻译,并且对于PAGE_OFFSET下的地址的每个进程,页表都不相同,那么两个进程不能将它们的进程描述符存储在相同的线性地址吗?

在linux中,“进程描述符”是struct task_struct [和其他一些]。 这些存储在内核地址空间[ PAGE_OFFSET之上]而不是在用户空间中。

这与PAGE_OFFSET设置为0xc0000000的32位内核更相关。

在32位内核中,用户进程虚拟地址空间被限制为PAGE_OFFSET

64位内核有些不同,限制并不重要。 PAGE_OFFSET是0xffff880000000000

另外,内核有自己的单个地址空间映射。

每个进程/线程都有自己的虚拟地址空间,即为.so库和线程共享内存禁止共享内存是唯一的。 它不映射到内核地址空间中的任何东西。

即使有[如果有]一个公共的地址空间映射内核页面是读/写保护的用户进程。


一个相关的问题:

这真是两个问题

有一个断言,进程描述符的线性地址可以作为一个唯一的进程ID。

不可以 。这是因为几个原因无法完成的。

只有内核有权访问(即“知道”) task_struct地址。

其次,如果一个进程终止,它是一个僵尸,直到父进程通过wait “收获”它。 内核必须记住哪些进程是僵尸(即它们的pids 不会被重新用于新进程),直到父节点获得它们。

task_struct相当大。 所以,当一个进程进入僵尸时,内核抓取task_struct数据的一部分(例如pidstatus ),并把它们保存在一个“zombie”结构中。 内核可以立即重用task_struct [使用不同的 pid]。

例如,当一个有pid 37的进程在运行的时候在地址(例如)0x1000上有一个task结构,在结束之后但在reap之前,pid 37 没有任务结构地址,并且已经可以分配0x1000的任务结构到23727

但是,由于线性地址使用页表进行翻译,而对于PAGE_OFFSET下的地址,每个进程的页表都不相同,那么两个进程是否不能将它们的进程描述符存储在相同的线性地址?

再次,不。