--- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -595,7 +595,7 @@ /* Check if it's a CAS reboot. If so, set the script to be executed. */ int -grub_ieee1275_cas_reboot (char *script) +grub_ieee1275_cas_reboot (char **script) { grub_uint32_t ibm_ca_support_reboot; grub_uint32_t ibm_fw_nbr_reboots; @@ -628,16 +628,37 @@ if (ibm_ca_support_reboot || ibm_fw_nbr_reboots) { - if (! grub_ieee1275_get_property_length (options, "boot-last-label", &actual)) - { - if (actual > 1024) - script = grub_realloc (script, actual + 1); - grub_ieee1275_get_property (options, "boot-last-label", script, actual, - &actual); - return 0; - } + grub_ssize_t len; + char *buf; + + if (grub_ieee1275_get_property_length (options, "boot-last-label", &len) + || len <= 0) + { + grub_dprintf ("ieee1275", "boot-last-label missing or invalid\n"); + goto out; + } + /* The returned property string length may not include terminating null byte, and in + a bid to avoid out of bound access we allocate one more byte to add it back */ + buf = grub_malloc ((grub_size_t)len + 1); + if (!buf) + { + grub_print_error (); + goto out; + } + if (grub_ieee1275_get_property (options, "boot-last-label", buf, (grub_size_t)len + 1, &actual) + || actual < 0) + { + grub_dprintf ("ieee1275", "error while get boot-last-label property\n"); + grub_free (buf); + goto out; + } + /* Add terminating null byte */ + buf[len] = '\0'; + *script = buf; + return 0; } +out: grub_ieee1275_set_boot_last_label (""); return -1; @@ -651,8 +672,9 @@ grub_dprintf("ieee1275", "set boot_last_label (size: %" PRIxGRUB_SIZE ")\n", grub_strlen(text)); if (! grub_ieee1275_finddevice ("/options", &options) && options != (grub_ieee1275_ihandle_t) -1) + /* To be on the safe side, set the property string with terminating null byte */ grub_ieee1275_set_property (options, "boot-last-label", text, - grub_strlen (text), &actual); + grub_strlen (text) + 1, &actual); return 0; } --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -282,10 +282,9 @@ #ifdef GRUB_MACHINE_IEEE1275 int boot; boot = 0; - char *script; + char *script = NULL; char *dummy[1] = { NULL }; - script = grub_malloc (1024); - if (! grub_ieee1275_cas_reboot (script)) + if (! grub_ieee1275_cas_reboot (&script) && script) { if (! grub_script_execute_new_scope (script, 0, dummy)) boot = 1; --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -256,7 +256,7 @@ void EXPORT_FUNC(grub_ieee1275_children_peer) (struct grub_ieee1275_devalias *alias); void EXPORT_FUNC(grub_ieee1275_children_first) (const char *devpath, struct grub_ieee1275_devalias *alias); -int EXPORT_FUNC(grub_ieee1275_cas_reboot) (char *script); +int EXPORT_FUNC(grub_ieee1275_cas_reboot) (char **script); int EXPORT_FUNC(grub_ieee1275_set_boot_last_label) (const char *text); char *EXPORT_FUNC(grub_ieee1275_get_boot_dev) (void);