69 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			69 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 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.
 | 
