This is the mail archive of the
mailing list for the glibc project.
Re: Implement C11 annex K?
- From: "David A. Wheeler" <dwheeler at dwheeler dot com>
- To: "libc-alpha" <libc-alpha at sourceware dot org>
- Date: Mon, 08 Sep 2014 19:21:20 -0400 (EDT)
- Subject: Re: Implement C11 annex K?
- Authentication-results: sourceware.org; auth=none
- Reply-to: dwheeler at dwheeler dot com
Paul Eggert <firstname.lastname@example.org> wrote:
> ... There's no evidence that using strlcpy
> reduces risk significantly, compared to spending an equivalent amount of
> effort using standard alternatives. If anything, the little evidence
> we've seen indicates the contrary.
We may have to agree to disagree, since we don't agree on what the examples *mean*.
With the same data I conclude "strlcpy is obviously much better".
Yes, you CAN write secure code without strlcpy/strlcat,
as you showed in your examples, but I think that proves nothing.
> Most of your email was about *style*, not about *risk*.
I disagree. Strlcpy/strlcat (and the annex K functions) *always* limit
buffer overwrites to the stated length (as well as guaranteeing \0 termination
when there is a length). That is not a style; that is a fact. In contrast,
any function that doesn't limit writing length (and doesn't allocate)
can produce a buffer overflow. That is not a style; that is a fact.
Therefore, using strlcpy/strlcat provides built-in protections against the risk of
programming error that can produce a buffer overflow, as compared to using
functions like strcpy. We can argue about whether or not
the reduction is *worth* it (fair enough!), but that's a different argument.
You've shown how to rewrite code that uses strlcpy/strlcat into something else
that doesn't have buffer overflows. But that is not the point.
If developers never make mistakes, there are no problems.
However, there is no evidence that mistakes have disappeared recently :-).
If someone makes a mistake with strlcpy/strlcat, typically the worst that
happens is silent truncation, which is not good but is typically much harder to exploit than
the buffer overflow vulnerabilities that occur when incorrectly using functions like strcpy and sprintf.
You pointed out that some strlcpy calls allow truncation, but that's the point: That is
the *worst* that happens with mistakes. Having functions that decrease the risk of vulnerabilities
due to programmer error is not just a "style"; it is a key point.
Strlcpy/strlcat and annex K produce code that is less likely to be vulnerable
to buffer overflows *even if* the code around it makes a mistake.
> >>> addrmatch.c:321:
> > The spec says snprintf can return <0, which this code fails to handle.
> In general snprintf can return <0, but this call won't. And even if it
> did, it wouldn't be a problem in practice, as Rich Felker mentioned.
As you note, snprintf *may* return a negative value. Indeed, POSIX specifically requires it
if the # of characters exceeds INT_MAX. Also, a cast to unsigned doesn't always work,
it depends on the system architecture and C implementation. The non-spec assumptions
you have to make turn out to be painfully long when trying to use casts.
Perhaps focusing on my intended goal would help.
My goal is to have a set of functions that reduce the risk that a
programming mistake will lead to a security vulnerability (especially buffer overflow),
better than the current functions in GNU libc. Ideally it would be a set of functions
portably available across C library implementations.
I accept that asprintf/vasprintf are very helpful for the dynamically-allocated case.
I'm still looking for easy-to-use functions that are designed to prevent
buffer overflows when the destination has a pre-allocated size.
Yes, snprintf helps, but is that really the best that can be done?
It's clunky and hides common cases (e.g., string copy and concatenation).
If annex K is unacceptable, would a change to it be acceptable?
For example, perhaps some _nhs variants that guaranteed to never invoke a handler?
Or something else?
--- David A. Wheeler