Balloon parallelism wraps flexible thread-array sizing on 32-bit
Closed, ResolvedPublic

Assigned To
Authored By
werner
Tue, Aug 4, 4:43 PM

Description

Balloon parallelism wraps flexible thread-array sizing on 32-bit

Balloon KDF does not bound its public parallelism parameter before sizing a flexible trailing array. On a 32-bit build, the context-size product and the later block-count conversion can both wrap to one small allocation, while the initialization loop still uses the original lane count and immediately writes past the heap object.

Vulnerable code

cipher/kdf.c, ballon_context_size and balloon_open:

c
static size_t
ballon_context_size (unsigned int parallelism)
{
  size_t n;

  n = offsetof (struct balloon_context, thread_data)
    + parallelism * sizeof (struct balloon_thread_data);
  return n;
}
c
  n = ballon_context_size (parallelism);
  b = xtrymalloc (n);
c
  block = xtrycalloc (parallelism * b->n_blocks, b->blklen);
  if (!block)
    {
      ec = gpg_err_code_from_errno (errno);
      xfree (b);
      return ec;
    }
  b->block = block;

  for (i = 0; i < parallelism; i++)
    {
      struct balloon_thread_data *t = &b->thread_data[i];

      t->b = b;
      t->ec = 0;
      t->idx = i;
      t->block = block;

Why it matters

On 32-bit systems with SHA-256, s_cost = 1 and parallelism = 0x10000001 wrap the flexible-array size to one thread entry. The 64-bit block product is then narrowed to 32-bit size_t at xtrycalloc, also producing a small allocation. Writing thread_data[1] is already out of bounds. A 64-bit process generally fails the huge allocation safely, so the impact is confined to 32-bit POSIX and Windows builds whose applications accept external Balloon parameters.

Proposed fix

Reject zero and excessive parallelism, then check parallelism <= (SIZE_MAX - offsetof(...)) / sizeof(thread_data[0]) before allocating. Independently prove that parallelism * n_blocks and its byte count fit size_t; use the validated value as the loop bound. Add a 32-bit ASan regression for the values above and boundary tests around each checked multiplication.

Revisions and Commits

Event Timeline

werner created this task.
werner created this object with visibility "Public (No Login Required)".
werner created this object with edit policy "Contributor (Project)".
werner renamed this task from balloon parallelism underallocates thread array on 32 bit to Balloon parallelism wraps flexible thread-array sizing on 32-bit.Tue, Aug 4, 5:11 PM
gniibe added a subscriber: gniibe.

I'm going to fix this with T8383.

gniibe mentioned this in Unknown Object (Maniphest Task).Mon, Aug 10, 3:55 AM
gniibe changed the task status from Open to Testing.Tue, Aug 11, 4:16 AM
gniibe lowered the priority of this task from High to Normal.
gniibe mentioned this in Unknown Object (Maniphest Task).Mon, Aug 24, 8:26 AM
werner shifted this object from the Restricted Space space to the S1 Public space.