Hi Russ, On Thu, Dec 20, 2012 at 3:49 PM, Russ Allbery <rra@xxxxxxxxxxxx> wrote: > Jeffrey Walton <noloader@xxxxxxxxx> writes: > >> If a project does not observe proper preprocessor macros for a >> configuration, a project could fall victim to runtime assertions and >> actually DoS itself after the assert calls abort(). The ISC's DNS server >> comes to mind (confer: there are CVE's assigned for the errant behavior, >> and its happened more than once! >> http://www.google.com/#q=isc+dns+assert+dos). > > It's very rare for it to be sane to continue after an assert(). That > would normally mean a serious coding error on the part of the person who > wrote the assert(). The whole point of assert() is to establish > invariants which, if violated, would result in undefined behavior. > Continuing after an assert() could well lead to an even worse security > problem, such as a remote system compromise. So, I somewhat disagree with you here. I think the differences are philosophical because I could never find guidance from standard bodies (such as Posix or IEEE) on rationales or goals behind NDEBUG and the intention of the abort() behind an assert(). First, an observation: if all the use cases are accounted (positive and negative), code *lacking* NDEBUG will never fire an asserts. The default case of 'fail' is enough to ensure this. You would be surprised (or maybe not) how many functions don't have the default 'fail' case. Any code that lacks NDEBUG because it depends upon assert() the abort() is defective by design. That includes the ISC's DNS server and their assertion/abort scheme (critical infrastructure, no less). Under no circumstance is a program allowed to abort(). It processes as expected or it fails gracefully. If it fails gracefully, it can exit() if it likes. But it does not crash, and it does not abort(). Here's the philosophical difference (that will surely draw criticism): asserts are a debug/diagnostic tool to aide in development. They have no place in release code. I'll take it a step further: Posix asserts are useless during development under a debugger because the eventually lead to SIGTERM. A much better approach in practice is to SIGTRAP. Code under my purview must (1) validate all parameters and (2) check all return values. Not only must there be logic to fail the function if anything goes wrong, *everything* must be asserted to alert of the point of first failure. In this respect, asserts create self-debugging code. I found developers did not like assert in debug configurations. They did not like asserts because of SIGTERM, which meant the developers did not fully assert. That caused the code to be non-compliant. The root cause was they did not like eating the dogfood of their own bugs. So I had to rewrite the asserts to use SIGTRAP, which made them very happy (they could make a mental note and continue on debugging). Code improved dramatically after that - we were always aware of the first point of failure, with out the need for breakpoints and detailed inspection unless needed. > The purpose of the -DNDEBUG compile-time option is not to achieve > additional security by preventing a DoS, but rather to gain additional > *performance* by removing all the checks done via assert(). If your goal > is to favor security over performance, you never want to use -DNDEBUG. Probably another philosophical difference: (1) code must be correct. (2) code should be secure. (3) code can be efficient. NDEBUG just removes the debugging/diagnostic aides, so it does help with (3). (1) is achieved because there is a separate if/then/else that handles the proper failure of a function in a release configuration. I know many will disagree, but I will put my money where my mouth is: I have code in the field (secure containers and secure channels) that has never taken a bug report or taken less than a handful (fewer than 3). They were developed with the discipline described above, and they include a complete suite of negative, multi-threaded self tests that ensure graceful failures. I don't care too much about the positive test cases since I can hire a kid from a third world country for $10 or $15 US a day to copy/paste code that works under the 'good' cases. Can anyone else say claim have a non-trivial code base that does not suffer defects (with a reasonable but broad definition of defect)? Anyway, sorry about the philosophicals. I know it does not lend much to the thread. Jeff _______________________________________________ Autoconf mailing list Autoconf@xxxxxxx https://lists.gnu.org/mailman/listinfo/autoconf