Suhosin: canary mismatch on efree() – heap overflow detected

Users of Suhosin-Patch will sooner or later see messages like “canary mismatch on efree() – heap overflow detected” in their error log. When this happens they are often confused and don’t understand what it means.

The first questions they often ask themself are:

  • Did they trigger a bug in Suhosin?
  • Is something wrong with Suhosin?

In reality this means that when PHP internally tried to free some allocated memory the memory manager security features of Suhosin detected that the memory to be freed is somehow corrupted. This corruption occured somewhen between the allocation of the memory area and the attempt to free it. Suhosin detects this by writing canary values infront and after allocated memory areas. These canary values are random numbers that are stored in one of Suhosin’s internal variables. The check consists of comparing the internally stored random number with the values found infront and after the memory area. Those values are outside of anything PHP is supposed to write to and therefore a failed canary comparision can only mean two things.

  1. some memory corruption destroyed/overwrote the internally stored random values
  2. some memory corruption destroyed/overwrote the canaries next to the allocated memory

This means everytime Suhosin gives out an error there was a memory corruption. There are no false positives as some of the PHP developers claim again and again. This means that everytime you see this error there has been a memory corruption in PHP or one of the loaded extensions. This means there is a bug and some code in one of the loaded components that behaves wrongly.

Unfortunately the PHP developers refuse to support PHP users that decided to go with the more secure version of PHP, because the patch could influence how PHP works and be the cause of the bug. They require their users to reproduce the problem with a vanilla PHP with valgrind running.

The obvious problems with this are

  1. Running PHP in valgrind has a much greater influence on how PHP works than Suhosin-Patch has
  2. Using valgrind wrongly means the memory corruption bugs cannot be found
  3. Using valgrind correctly does not necessary reveal the bug, because it might be hidden by memory alignment or just because valgrind cannot detect that class of memory corruptions
  4. A memory corruption that Suhosin might detect everytime might only crash a vanilla (valgrind) PHP once every thousand invocations or might not result in a crash at all but in wrong computation results
  5. Some memory corruptions occur in memory areas that are unused due to alignment, they will not result in misbehaviour of vanilla PHP – However any memory corruption is a bug in PHP (or extensions) that should be fixed and a little harmless memory corruption today could turn into a remote exploit in the future when the code is changed (or when PHP is executed on another (new) architecture).
  6. A normal user will not be able to recompile PHP and reproduce with valgrind correctly
  7. A not reproduced memory corruption still exists but will not be fixed

That said the only option for users of the more secure PHP is at the moment to try to get support for their problem at their distribution’s PHP maintainers because the people at PHP.net will not be interested in helping them. However due to the reasons above the distribution maintainers might not be able to help you, because they cannot reproduce the bug (although Suhosin proved its existance).

If you know what you are doing then just use valgrind on the Suhosin patched PHP and simply claim that you reproduced the bug without Suhosin installed. This will also give you a higher probability of reproducing the problem.

Because of this I will think up some debugging functionality for Suhosin that will make it easier for users to tell the PHP developers where their bug is located. More information about how this will be implemented will be released during the next month.