MAP_FIXED_SAFE
Any mmap() call allows the calling process to specify an address for the mapping. In normal operation, though, this address is simply a hint that the kernel is free to ignore. MAP_FIXED exists for cases where the mapping really has to be placed at the requested address or the application will fail to work. The kernel takes this flag seriously, to the point that, if there is already another mapping in the given address range, the existing mapping will be destroyed to make room for the new one. This seems like a strange semantic; if an application wants a mapping at a given area, it should probably be able to take responsibility for making room for that mapping. But mmap() is specified to work that way, so that is what happens.
Needless to say, that can be problematic if the application wasn't aware of the conflicting mapping — something that could occur as the result of a bug, address-space layout randomization, disagreements between libraries, or deliberate manipulation by an attacker. The data contained within that mapping (or the overlapping part of it, at least) will be silently dropped on the floor and the new mapping will show up in its place. The chances of things working correctly after that are likely to be fairly small. In some cases, security vulnerabilities can result; see, for example, CVE-2017-1000253. In that case, the kernel's internal use of MAP_FIXED to load programs into memory was exploited to corrupt the stack.
A solution can be found in Michal Hocko's MAP_FIXED_SAFE patch set. It adds a new mmap() flag called, surprisingly, MAP_FIXED_SAFE with semantics similar to MAP_FIXED with one exception: the operation will fail if the targeted address range is not free. The kernel's ELF loader is modified to use this new flag when mapping programs into memory; that will cause program loading to fail if two mappings collide, but that is better than the alternative. It is expected that new code would use this new flag in almost all cases, and that older programs would eventually be switched as well.
Some had suggested adding a separate flag to modify the behavior of MAP_FIXED, so that applications would pass something like MAP_FIXED|MAP_SAFE to mmap(). The problem with that approach is that mmap() is one of those system calls that never checked for unknown flags. A program using that construction would, as a result, silently fall back to MAP_FIXED on older kernels that lacked support for the new MAP_SAFE flag. Using a new flag means that, while the application will not get the desired failure status on an older kernel if the address range is not available, it also will not clobber any existing mappings (because the specified address will be treated as a hint by the kernel).
This change is pretty much ready to go, and Hocko has requested that it be merged. There is, however, the vital issue which has caused the most discussion about this patch series: the naming of MAP_FIXED_SAFE. For various reasons, various developers wanted a different name. Suggestions included MAP_FIXED_UNIQUE, MAP_FIXED_NOREPLACE, MAP_FIXED_NO_CLOBBER, MAP_TANTRUM, MAP_EXACT, MAP_NOFORCE, and quite a few others. It was just the sort of discussion that results when the technical issues are resolved, but everybody wants to put their stamp on the final result.
After enduring a fair amount of that discussion, Hocko made his own decision on the naming:
He also stated that anybody who was truly unhappy with the name was welcome to block the patch and somehow build a consensus around a better one, but that he was done with it. So, naturally, somebody objected, and Hocko wished him luck carrying the patch set forward.
Given the personalities involved, one might think that a useful patch will
end up simply blocked at this point. Your editor would wager, though, that
the MAP_FIXED_SAFE patches will be merged in something close to
their current form. They address a real problem; holding them up while
waiting for the perfect name does not seem like an approach that will do
anybody any good.
| Index entries for this article | |
|---|---|
| Kernel | Memory management |
| Security | Linux kernel |
