Does a buffer overflow vulnerability always mean a code execution vulnerability?

No, a buffer overflow might:

  • Be against a buffer on the heap not the stack. This might still lead to code execution but will be much more complicated to exploit.
  • Be limited in size, so not able to overwrite return pointers. (e.g. be able to only write 1 byte beyond the buffer)
  • Be restricted in which bytes can be written, preventing suitable pointers to be written.
  • Overwrite stack cookies, which are detected before the return address is used. Unless the cookie is leaked, the exploit would crash the process the vast majority of the time, rather than leading to code execution.
  • Be on a stack growing upwards, so not be able to overwrite return addresses. An exploit might still be able to overwrite other local variables, or the buffer might be passed to another function, but wouldn't lead to code execution as reliably as downwards stacks.

Some of these might still lead to code execution, but other instances might be impossible to exploit.

However once you've found where a buffer overflow is happening it's usually much easier to fix it, than to prove it can't be exploited.

Douglas gives a correct answer. Not all buffer overflows give code execution. However, I felt it was missing a very important caution.

Even if a buffer overflow does not allow arbitrary code execution, that does not mean that it is safe.

A write buffer overflow lets you write to data that you are not supposed to. That data being a function address is just a special case. For example, suppose I have a user struct that has fields for name and privilege. It is easy to imagine how setting my name to "JosiahhasaverylongnameAdmin" could exploit a serious vulnerability, without any arbitrary code execution.

For another real world example, if you remember Heartbleed, that is a buffer overflow. It is just a read overflow rather than a write overflow. No chance of a code execution there, but a devastating breach of confidentiality even so.