minix/servers/procfs/NOTES
2010-09-14 21:25:25 +00:00

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.