68 lines
4 KiB
Text
68 lines
4 KiB
Text
Development notes regarding ProcFS. Original document by David van Moolenbroek.
|
|
|
|
|
|
SECURITY MODEL
|
|
|
|
Right now, procfs is not able to deal with security-sensitive information,
|
|
because there would be too many opportunities for rogue processes to obtain
|
|
values they shouldn't be able to get to. This is mainly due to the fact that
|
|
while procfs is running, the environment around it may change arbitrarily: for
|
|
example, a /proc/<pid>/mem file could offer access to a process's core memory,
|
|
but if a rogue process opened that file right before the victim process invokes
|
|
an exec() on a setuid binary, the rogue process could read from the victim
|
|
process's memory while a victim user provides this process with their password.
|
|
This is only one example out of many; such time-to-check/time-to-use race
|
|
conditions are inherent to the inherently race-prone situation that procfs
|
|
finds itself in, trying to provide information about an asynchronously running
|
|
system.
|
|
|
|
A little more specifically, this problem mainly comes up when system calls are
|
|
made to obtain information (long) after a certain PID directory has been
|
|
updated, which typically happens right after pulling in a new copy of the
|
|
process tables of the kernel, PM, and VFS. Returning stale information from
|
|
those tables is usually not a problem: at worst, the caller gets outdated
|
|
information about the system as it once was, after passing a security check for
|
|
that point in time. Hence, it can not obtain information it never had access
|
|
to. Using information from those tables to perform calls later, however, is
|
|
a different case. In the "mem" example above, procfs would have the old user ID
|
|
in its copy of the process tables, and yet perform on-demand sys_datacopy calls
|
|
(or something similar) to retrieve memory from the process, bypassing a check
|
|
on the then-current user ID. A similar situation already exists right now for
|
|
the /proc/<pid>/map file for example, which pulls in information on demand -
|
|
but it provides only public information anyway, just like the other files that
|
|
procfs currently exposes.
|
|
|
|
A proper solution to this problem has simply not been implemented yet. It is
|
|
possible to change the system in such a way that procfs check whether the
|
|
target process is still in the same security state before returning information
|
|
to the caller process. This can be done either while or after obtaining the
|
|
information, depending on what is most convenient for the design of the system.
|
|
Any such solution obviously has an impact on system design and procfs'
|
|
performance, and was found not worth implementing for the first version of
|
|
procfs, since all offered information was public anyway. However, such a change
|
|
*must* be made before procfs can expose anything that provides a potential for
|
|
security breaches.
|
|
|
|
Finally, it must be kept in mind that even updating the process tables from
|
|
various other sources is not an atomic operation. There might be mismatches
|
|
between the tables. Procfs must be able to handle such occurrences with care,
|
|
from both a security perspective and a general functionality perspective.
|
|
|
|
|
|
FUTURE EXPANSIONS
|
|
|
|
It would be trivial to add a /proc/self symlink pointing to the caller's PID
|
|
directory, if the VFS-FS protocol's REQ_RDLINK request were augmented to
|
|
include the caller's PID or endpoint. However, this would be a procfs-specific
|
|
protocol change, and there does not seem to be a need for this just yet.
|
|
|
|
Even more custom protocol changes or procfs-specific backcalls would have to be
|
|
added to expose processes' current working directory, root directory,
|
|
executable path, or open files. A number of VFS parts would have to be changed
|
|
significantly to fully support all of these, possibly including an entire DNLC.
|
|
|
|
All the necessary infrastructure is there to add static (sub)directories - for
|
|
example, a /proc/net/ directory. It would be more tricky to add subdirectories
|
|
for dynamic (process) directories, for example /proc/<pid>/fd/. This would
|
|
require some changes to the VTreeFS side of the tree management. Some of the
|
|
current assumptions are documented in type.h.
|