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.