Prevent relocator of overwriting itself
This commit is contained in:
parent
928506da8b
commit
bd7fbf1020
1 changed files with 26 additions and 8 deletions
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue