On 4.12.2020 1.15, David Laight wrote:
From: Mike Rapoport
Sent: 03 December 2020 06:58
On Wed, Dec 02, 2020 at 08:49:06PM +0200, Topi Miettinen wrote:
On 1.12.2020 23.45, Topi Miettinen wrote:
Memory mappings inside kernel allocated with vmalloc() are in
predictable order and packed tightly toward the low addresses. With
new kernel boot parameter 'randomize_vmalloc=1', the entire area is
used randomly to make the allocations less predictable and harder to
guess for attackers.
Isn't that going to horribly fragment the available address space
and make even moderate sized allocation requests fail (or sleep).
For 32 bit architecture this is a real issue, but I don't think for 64
bits it will be a problem. You can't fragment the virtual memory space
for small allocations because the resulting page tables will not fit in
RAM for existing or near future systems.
For large allocations (directly mapping entire contents of TB sized NVME
drives or a special application which needs 1GB huge pages) this could
be a risk. Maybe this could be solved by reserving some space for them,
or perhaps in those cases you shouldn't use randomize_vmalloc=1.
The method for reserving the large areas could something like below.
First, consider a simple arrangement of reserving high addresses for
large allocations and low addresses for smaller allocations. The
allocator would start searching downwards from high addresses for a free
large block and upwards from low addresses for small blocks. Also the
address space would be semi-rigidly divided to priority areas: area 0
with priority for small allocations, area 1 with equal priority for both
small and large, and area 2 where small allocations would be placed only
as a last resort (which probably would never be the case).
The linear way of dividing the allocations would of course be very much
non-random, so this could be improved with a pseudo-random scrambling
function to distribute the addresses in memory. A simple example would
be to randomly choose a value for one bit in the address for large
allocations (not necessarily the most significant available but also
large enough to align 1GB/TB sized allocations if needed), or a bit
pattern across several address bits for non-even distribution.
The addresses would be also fully randomized inside each priority area.
The division would mean some loss of randomization. A simple rigid
division of 50%/50% for small vs. large allocations would mean a loss of
one bit but the above methods could help this. Dividing the address
space less evenly would improve one side at the expense of the other.
Cracking the scrambling function would reveal the bit(s) used for the
division.
It would be nice to remove the current rigid division of the kernel
address space (Documentation/x86/x86_64/mm.rst) and let the allocations
be placed more randomly in the entire 47 bit address space. Would the
above priority scheme (perhaps with a rigid priority for certain users)
be good enough to allow this?
Even better would be to remove the use of highest bit for selecting
kernel/user addresses but I suppose it would be a lot of work for
gaining just one extra bit of randomness. There could be other effects
though (good or bad).
-Topi
I'm not even sure that you need to use 'best fit' rather than
'first fit'.
'best fit' is certainly a lot better for a simple linked list
user space malloc.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)