Decrease stack usage in signature verification.

We have only 92K of stack and using over 4K per frame is wasteful

	* grub-core/commands/verify.c (grub_load_public_key): Allocate on heap
	rather than stack.
	(grub_verify_signature_real): Likewise.
This commit is contained in:
Vladimir Serbinenko 2013-11-16 16:34:51 +01:00
parent ab4366fd49
commit 4f84ae0ec8
2 changed files with 35 additions and 20 deletions

View file

@ -1,3 +1,13 @@
2013-11-16 Vladimir Serbinenko <phcoder@gmail.com>
Decrease stack usage in signature verification.
We have only 92K of stack and using over 4K per frame is wasteful
* grub-core/commands/verify.c (grub_load_public_key): Allocate on heap
rather than stack.
(grub_verify_signature_real): Likewise.
2013-11-16 Vladimir Serbinenko <phcoder@gmail.com> 2013-11-16 Vladimir Serbinenko <phcoder@gmail.com>
Decrease stack usage in mdraid 0.9x. Decrease stack usage in mdraid 0.9x.

View file

@ -198,17 +198,16 @@ free_pk (struct grub_public_key *pk)
grub_free (pk); grub_free (pk);
} }
#define READBUF_SIZE 4096
struct grub_public_key * struct grub_public_key *
grub_load_public_key (grub_file_t f) grub_load_public_key (grub_file_t f)
{ {
grub_err_t err; grub_err_t err;
struct grub_public_key *ret; struct grub_public_key *ret;
struct grub_public_subkey **last = 0; struct grub_public_subkey **last = 0;
void *fingerprint_context; void *fingerprint_context = NULL;
grub_uint8_t *buffer = NULL;
fingerprint_context = grub_zalloc (GRUB_MD_SHA1->contextsize);
if (!fingerprint_context)
return NULL;
ret = grub_zalloc (sizeof (*ret)); ret = grub_zalloc (sizeof (*ret));
if (!ret) if (!ret)
@ -217,6 +216,12 @@ grub_load_public_key (grub_file_t f)
return NULL; return NULL;
} }
buffer = grub_zalloc (READBUF_SIZE);
fingerprint_context = grub_zalloc (GRUB_MD_SHA1->contextsize);
if (!buffer || !fingerprint_context)
goto fail;
last = &ret->subkeys; last = &ret->subkeys;
while (1) while (1)
@ -304,7 +309,6 @@ grub_load_public_key (grub_file_t f)
{ {
grub_uint16_t l; grub_uint16_t l;
grub_size_t lb; grub_size_t lb;
grub_uint8_t buffer[4096];
if (grub_file_read (f, &l, sizeof (l)) != sizeof (l)) if (grub_file_read (f, &l, sizeof (l)) != sizeof (l))
{ {
grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
@ -312,7 +316,7 @@ grub_load_public_key (grub_file_t f)
} }
lb = (grub_be_to_cpu16 (l) + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT; lb = (grub_be_to_cpu16 (l) + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT;
if (lb > sizeof (buffer) - sizeof (grub_uint16_t)) if (lb > READBUF_SIZE - sizeof (grub_uint16_t))
{ {
grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
goto fail; goto fail;
@ -348,6 +352,7 @@ grub_load_public_key (grub_file_t f)
fail: fail:
free_pk (ret); free_pk (ret);
grub_free (fingerprint_context); grub_free (fingerprint_context);
grub_free (buffer);
return NULL; return NULL;
} }
@ -486,10 +491,12 @@ grub_verify_signature_real (char *buf, grub_size_t size,
gcry_mpi_t hmpi; gcry_mpi_t hmpi;
grub_uint64_t keyid = 0; grub_uint64_t keyid = 0;
struct grub_public_subkey *sk; struct grub_public_subkey *sk;
grub_uint8_t *readbuf = NULL;
context = grub_zalloc (hash->contextsize); context = grub_zalloc (hash->contextsize);
if (!context) readbuf = grub_zalloc (READBUF_SIZE);
return grub_errno; if (!context || !readbuf)
goto fail;
hash->init (context); hash->init (context);
if (buf) if (buf)
@ -497,8 +504,7 @@ grub_verify_signature_real (char *buf, grub_size_t size,
else else
while (1) while (1)
{ {
grub_uint8_t readbuf[4096]; r = grub_file_read (f, readbuf, READBUF_SIZE);
r = grub_file_read (f, readbuf, sizeof (readbuf));
if (r < 0) if (r < 0)
goto fail; goto fail;
if (r == 0) if (r == 0)
@ -510,8 +516,8 @@ grub_verify_signature_real (char *buf, grub_size_t size,
hash->write (context, &v4, sizeof (v4)); hash->write (context, &v4, sizeof (v4));
while (rem) while (rem)
{ {
grub_uint8_t readbuf[4096]; r = grub_file_read (sig, readbuf,
r = grub_file_read (sig, readbuf, rem < (grub_ssize_t) sizeof (readbuf) ? rem : (grub_ssize_t) sizeof (readbuf)); rem < READBUF_SIZE ? rem : READBUF_SIZE);
if (r < 0) if (r < 0)
goto fail; goto fail;
if (r == 0) if (r == 0)
@ -527,11 +533,10 @@ grub_verify_signature_real (char *buf, grub_size_t size,
if (r != sizeof (unhashed_sub)) if (r != sizeof (unhashed_sub))
goto fail; goto fail;
{ {
grub_uint8_t readbuf[4096];
grub_uint8_t *ptr; grub_uint8_t *ptr;
grub_uint32_t l; grub_uint32_t l;
rem = grub_be_to_cpu16 (unhashed_sub); rem = grub_be_to_cpu16 (unhashed_sub);
if (rem > (int) sizeof (readbuf)) if (rem > READBUF_SIZE)
goto fail; goto fail;
r = grub_file_read (sig, readbuf, rem); r = grub_file_read (sig, readbuf, rem);
if (r != rem) if (r != rem)
@ -576,24 +581,23 @@ grub_verify_signature_real (char *buf, grub_size_t size,
{ {
grub_uint16_t l; grub_uint16_t l;
grub_size_t lb; grub_size_t lb;
grub_uint8_t buffer[4096];
grub_dprintf ("crypt", "alive\n"); grub_dprintf ("crypt", "alive\n");
if (grub_file_read (sig, &l, sizeof (l)) != sizeof (l)) if (grub_file_read (sig, &l, sizeof (l)) != sizeof (l))
goto fail; goto fail;
grub_dprintf ("crypt", "alive\n"); grub_dprintf ("crypt", "alive\n");
lb = (grub_be_to_cpu16 (l) + 7) / 8; lb = (grub_be_to_cpu16 (l) + 7) / 8;
grub_dprintf ("crypt", "l = 0x%04x\n", grub_be_to_cpu16 (l)); grub_dprintf ("crypt", "l = 0x%04x\n", grub_be_to_cpu16 (l));
if (lb > sizeof (buffer) - sizeof (grub_uint16_t)) if (lb > READBUF_SIZE - sizeof (grub_uint16_t))
goto fail; goto fail;
grub_dprintf ("crypt", "alive\n"); grub_dprintf ("crypt", "alive\n");
if (grub_file_read (sig, buffer + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb) if (grub_file_read (sig, readbuf + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb)
goto fail; goto fail;
grub_dprintf ("crypt", "alive\n"); grub_dprintf ("crypt", "alive\n");
grub_memcpy (buffer, &l, sizeof (l)); grub_memcpy (readbuf, &l, sizeof (l));
grub_dprintf ("crypt", "alive\n"); grub_dprintf ("crypt", "alive\n");
if (gcry_mpi_scan (&mpis[i], GCRYMPI_FMT_PGP, if (gcry_mpi_scan (&mpis[i], GCRYMPI_FMT_PGP,
buffer, lb + sizeof (grub_uint16_t), 0)) readbuf, lb + sizeof (grub_uint16_t), 0))
goto fail; goto fail;
grub_dprintf ("crypt", "alive\n"); grub_dprintf ("crypt", "alive\n");
} }
@ -631,6 +635,7 @@ grub_verify_signature_real (char *buf, grub_size_t size,
fail: fail:
grub_free (context); grub_free (context);
grub_free (readbuf);
if (!grub_errno) if (!grub_errno)
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
return grub_errno; return grub_errno;