Prevent relocator of overwriting itself

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2009-11-26 16:52:10 +01:00
parent 928506da8b
commit bd7fbf1020

View file

@ -16,15 +16,17 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define MAX_OVERHEAD ((RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN) \
+ (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN) \
+ (RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN) \
+ (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN))
void * void *
PREFIX (alloc) (grub_size_t size) PREFIX (alloc) (grub_size_t size)
{ {
char *playground; char *playground;
playground = grub_malloc ((RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN) playground = grub_malloc (size + MAX_OVERHEAD);
+ size
+ (RELOCATOR_SIZEOF (backward) +
RELOCATOR_ALIGN));
if (!playground) if (!playground)
return 0; return 0;
@ -40,10 +42,7 @@ PREFIX (realloc) (void *relocator, grub_size_t size)
playground = (char *) relocator - RELOCATOR_SIZEOF (forward); playground = (char *) relocator - RELOCATOR_SIZEOF (forward);
playground = grub_realloc (playground, playground = grub_realloc (playground, size + MAX_OVERHEAD);
(RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN)
+ size
+ (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN));
if (!playground) if (!playground)
return 0; return 0;
@ -73,6 +72,25 @@ PREFIX (boot) (void *relocator, grub_uint32_t dest,
"Relocator: source: %p, destination: 0x%x, size: 0x%x\n", "Relocator: source: %p, destination: 0x%x, size: 0x%x\n",
relocator, dest, size); relocator, dest, size);
/* Very unlikely condition: Relocator may risk overwrite itself.
Just move it a bit up. */
if ((grub_uint8_t *) UINT_TO_PTR (dest) - (grub_uint8_t *) relocator
< RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN
&& (grub_uint8_t *) UINT_TO_PTR (dest) - (grub_uint8_t *) relocator
> -(RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN))
{
void *relocator_new = ((grub_uint8_t *) relocator)
+ (RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN)
+ (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN);
grub_dprintf ("relocator", "Overwrite condition detected moving "
"relocator from %p to %p\n", relocator, relocator_new);
grub_memmove (relocator_new, relocator,
(RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN)
+ size
+ (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN));
relocator = relocator_new;
}
if (UINT_TO_PTR (dest) >= relocator) if (UINT_TO_PTR (dest) >= relocator)
{ {
int overhead; int overhead;