I understand that strlcpy
and strlcat
were designed as secure replacements for strncpy
and strncat
. However, some people are still of the opinion that they are insecure, and simply cause a different type of problem.
Can someone give an example of how using strlcpy
or strlcat
(i.e. a function that always null terminates its strings) can lead to security problems?
Ulrich Drepper and James Antill state this is true, but never provide examples or clarify this point.
When people say, "
strcpy()
is dangerous, usestrncpy()
instead" (or similar statements aboutstrcat()
etc., but I am going to usestrcpy()
here as my focus), they mean that there is no bounds checking instrcpy()
. Thus, an overly long string will result in buffer overruns. They are correct. Usingstrncpy()
in this case will prevent buffer overruns.I feel that
strncpy()
really doesn't fix bugs: it solves a problem that can be easily avoided by a good programmer.As a C programmer, you must know the destination size before you are trying to copy strings. That is the assumption in
strncpy()
andstrlcpy()
's last parameters too: you supply that size to them. You can also know the source size before you copy strings. Then, if the destination is not big enough, don't callstrcpy()
. Either reallocate the buffer, or do something else.Why do I not like
strncpy()
?strncpy()
is a bad solution in most cases: your string is going to be truncated without any notice—I would rather write extra code to figure this out myself and then take the course of action that I want to take, rather than let some function decide for me about what to do.strncpy()
is very inefficient. It writes to every byte in the destination buffer. You don't need those thousands of'\0'
at the end of your destination.'\0'
if the destination is not big enough. So, you must do so yourself anyway. The complexity of doing this is not worth the trouble.Now, we come to
strlcpy()
. The changes fromstrncpy()
make it better, but I am not sure if the specific behavior ofstrl*
warrants their existence: they are far too specific. You still have to know the destination size. It is more efficient thanstrncpy()
because it doesn't necessarily write to every byte in the destination. But it solves a problem that can be solved by doing:*((char *)mempcpy(dst, src, n)) = 0;
.I don't think anyone says that
strlcpy()
orstrlcat()
can lead to security issues, what they (and I) are saying that they can result in bugs, for example, when you expect the complete string to be written instead of a part of it.The main issue here is: how many bytes to copy? The programmer must know this and if he doesn't,
strncpy()
orstrlcpy()
won't save him.strlcpy()
andstrlcat()
are not standard, neither ISO C nor POSIX. So, their use in portable programs is impossible. In fact,strlcat()
has two different variants: the Solaris implementation is different from the others for edge cases involving length 0. This makes it even less useful than otherwise.I think Ulrich and others think it'll give a false sense of security. Accidentally truncating strings can have security implications for other parts of the code (for example, if a file system path is truncated, the program might not be performing operations on the intended file).
I don't think
strlcpy
andstrlcat
are consider insecure or it least it isn't the reason why they're not included in glibc - after all, glibc includes strncpy and even strcpy.The criticism they got was that they are allegedly inefficient, not insecure.
According to the Secure Portability paper by Damien Miller:
That is why they are not available in glibc, but it is not true that they are not available on Linux. They are available on Linux in libbsd:
They're packaged in Debian and Ubuntu and other distros. You can also just grab a copy and use in your project - it's short and under a permissive license:
There are two "problems" related to using strl functions:
The c1x standard draft writers and Drepper, argue that programmers won't check the return value. Drepper says we should somehow know the length and use memcpy and avoid string functions altogether, The standards committee argues that the secure strcpy should return nonzero on truncation unless otherwise stated by the
_TRUNCATE
flag. The idea is that people are more likely to use if(strncpy_s(...)).Some people think that string functions should never crash even when fed bogus data. This affects standard functions such as strlen which in normal conditions will segfault. The new standard will include many such functions. The checks of course have a performance penalty.
The upside over the proposed standard functions is that you can know how much data you missed with strl functions.
Ulrich's criticism is based on the idea that a string truncation that is not detected by the program can lead to security issues, through incorrect logic. Therefore, to be secure, you need to check for truncation. To do this for a string concatenation means that you are doing a check along the lines of this:
Now,
strlcat
does effectively do this check, if the programmer remembers to check the result - so you can use it safely:Ulrich's point is that since you have to have
destlen
andsourcelen
around (or recalculate them, which is whatstrlcat
effectively does), you might as well just use the more efficientmemcpy
anyway:(In the above code,
dest_maxlen
is the maximum length of the string that can be stored indest
- one less than the size of thedest
buffer.dest_bufferlen
is the full size of thedest buffer
).Firstly,
strlcpy
has never been intended as a secure version ofstrncpy
(andstrncpy
has never been intended as a secure version ofstrcpy
). These two functions are totally unrelated.strncpy
is a function that has no relation to C-strings (i.e. null-terminated strings) at all. The fact that it has thestr...
prefix in its name is just a historical blunder. The history and purpose ofstrncpy
is well-known and well-documented. This is a function created for working with so called "fixed width" strings (not with C-strings) used in some historical versions of Unix file system. Some programmers today get confused by its name and assume thatstrncpy
is somehow supposed to serve as limited-length C-string copying function (a "secure" sibling ofstrcpy
), which in reality is complete nonsense and leads to bad programming practice. C standard library in its current form has no function for limited-length C-string copying whatsoever. This is wherestrlcpy
fits in.strlcpy
is indeed a true limited-length copying function created for working with C-strings.strlcpy
correctly does everything a limited-length copying function should do. The only criticism one can aim at it is that it is, regretfully, not standard.Secondly,
strncat
on the other hand, is indeed a function that works with C-strings and performs a limited-length concatenation (it is indeed a "secure" sibling ofstrcat
). In order to use this function properly the programmer has to take some special care, since the size parameter this function accepts is not really the size of the buffer that receives the result, but rather the size of its remaining part (also, the terminator character is counted implicitly). This could be confusing, since in order to tie that size to the size of the buffer, programmer has to remember to perform some additional calculations, which is often used to criticize thestrncat
.strlcat
takes care of these issues, changing the interface so that no extra calculations are necessary (at least in the calling code). Again, the only basis I see one can criticise this on is that the function is not standard. Also, functions fromstrcat
group is something you won't see in professional code very often due to the limited usability of the very idea of rescan-based string concatenation.As for how these functions can lead to security problems... They simply can't. They can't lead to security problems in any greater degree than the C language itself can "lead to security problems". You see, for quite a while there was a strong sentiment out there that C++ language has to move in the direction of developing into some weird flavor of Java. This sentiment sometimes spills into the domain of C language as well, resulting in rather clueless and forced criticism of C language features and the features of C standard library. I suspect that we might be dealing with something like that in this case as well, although I surely hope things are not really that bad.