Suponiendo que el sistema operativo asigna páginas de forma completamente aleatoria, mi mejor cálculo dice que hay un 11% de probabilidad de que cualquier dirección de víctima tenga al menos 12 páginas coincidentes en su búfer de 4MB. Eso no es muy probable, y ciertamente no está de acuerdo con la tasa de éxito del 70% que viste.
Sin embargo, existen buenas razones para que un sistema operativo evite la asignación aleatoria de páginas y, en su lugar, haga todo lo posible para asignar páginas contiguas. Una razón para esto es que el sistema operativo a veces necesita asignar grandes búferes contiguos (para admitir páginas grandes o grandes búferes de DMA, por ejemplo), y la asignación aleatoria de páginas físicas dificultaría mucho encontrar una región lo suficientemente grande. Esto se conoce como fragmentación de la memoria.
Pero en el contexto de esta discusión, un beneficio más interesante de la asignación contigua es (irónicamente) el rendimiento del caché de nivel 3. Si está ejecutando un algoritmo que utiliza un búfer de memoria grande, la forma de obtener el mejor rendimiento es asignar memoria física contigua, para que las páginas individuales no se expulsen entre sí de la memoria caché. Si el SO logra maximizar el rendimiento de esta manera, también logrará maximizar la efectividad del ataque: su búfer de 4MB cubrirá todo el caché, y tendrá un 100% de probabilidad de desalojar una página víctima. Por lo tanto, su tasa de éxito observada del 70% es menos una medida de probabilidad y más una medida aproximada de la efectividad del sistema operativo en la asignación de páginas para un buen rendimiento de caché.
Si desea ver un ejemplo de un sistema operativo funcionando de esta manera en la práctica, lea sobre Linux repartidor de amigos . Comienza por romper la memoria en un conjunto de grandes bloques libres. Luego, si quiere asignar una página, toma uno de esos bloques grandes y lo divide por la mitad. Luego toma una de las mitades y la divide de nuevo en dos, y continúa hasta que tiene un par de bloques de 1 página, en cuyo punto también tiene un bloque de 2 páginas, uno de 4 tamaños, uno De tamaño 8, etc. Las primeras dos asignaciones serán esos dos bloques de 1 página, que están uno al lado del otro porque son el resultado de romper un bloque de 2 páginas por la mitad. La tercera asignación romperá el otro bloque de 2 páginas a la mitad, que nuevamente estará al lado de los otros dos por las mismas razones.
Entonces, cada vez que necesita una nueva página, el asignador toma el bloque más pequeño que puede encontrar y lo descompone hasta que tenga una sola página. Finalmente, cuando se libera una página, el asignador verifica si hay una página libre justo al lado, para que pueda volver a formar esas dos páginas en un bloque más grande. El efecto neto es mantener las asignaciones aproximadamente contiguas cuando sea posible.