By Michael Kerrisk
July 18, 2012
Adding the
strlcpy() function
(and the related
strlcat() function)
has been a perennial request
(1,
2,
3)
to the
GNU C library (glibc)
maintainers,
commonly supported by a statement that
strlcpy()
is superior to the existing alternatives.
Perhaps the earliest request to add these
BSD-derived functions to glibc took the form of
a patch submitted in 2000
by a fresh-faced Christoph Hellwig.
Christoph's request was rejected, and subsequent requests have similarly been rejected (or ignored).
It's instructive to consider the reasons why
strlcpy()
has so far been rejected,
and why it may well not make its way into glibc in the future.
A little prehistory
In the days before programmers considered that someone else might want to
deliberately subvert their code, the C library provided just:
char *strcpy(char *dst, const char *src);
with the simple purpose of copying the bytes from the
string pointed to by
src
(up to and including the terminating null byte)
to the buffer pointed to by
dst.
Naturally, when calling
strcpy(),
the programmer must take care that the bytes being
copied don't overrun the
space available in the buffer pointed by
dst.
The effect of such buffer overruns
is to overwrite other parts of a process's memory, such as
neighboring variables,
with the most common result being to corrupt data
or to crash the program.
If the programmer can with 100% certainty predict
at compile time the size of the
src
string,
then it's possible (if unwise) to preallocate a suitably sized
dst
buffer and omit any argument checks before calling
strcpy().
In all other cases, the call should be guarded with a suitable
if
statement to check the size of its argument.
However, strings (in the form of input text)
are one of the ways that humans interact with computers,
and thus quite commonly the size of the
src
string is controlled by the user of a program, not the program's creator.
At that point, of course, it becomes essential for every call to
strcpy()
to be guarded by a suitable
if
statement:
char dst [DST_SIZE];
...
if (strlen(src) < DST_SIZE)
strcpy(dst, src);
(The use of
<
rather than
<=
ensures that there's at least one byte extra byte available for the null terminator.)
But it was easy for programmers to omit such checks
if they were forgetful, inattentive, or cowboys.
And later, other more attentive programmers realized that by
carefully controlling what was written into the overflowed buffer,
and overrunning into more exotic places such as
function
call return addresses stored on the stack,
they could do
much
more interesting things
with buffer overruns than simply crashing the program.
(And because code tends to live a long time,
and the individual programmers creating it can be slow to
to learn about the sharp edges of the tools they use,
even today buffer overruns remain one of the
most
commonly reported vulnerabilities
in applications.)
Improving on strcpy()
Prechecking the arguments of each call to
strcpy()
is burdensome.
A seemingly obvious way to relieve the programmer
of that task was to add an API
that allowed the caller to inform the library
function of the size of the target buffer:
char *strncpy(char *dst, const char *src, size_t n);
The
strncpy()
function is like
strcpy(),
but copies at most
n
bytes from
src
to
dst.
As long as
n
does not exceed the space allocated in
dst,
a buffer overrun can never occur.
Although choosing a suitable value for
n
ensures that
strncpy()
will never overrun
dst,
it turns out that
strncpy()
has problems of its own.
Most notably,
if there is no null terminator in the first
n
bytes of
src,
then
strncpy()
does not place a null terminator after the bytes copied to
dst.
If the programmer does not check for this event,
and subsequent operations expect a null terminator to be present,
then the program is once more vulnerable to attack.
The vulnerability may be more difficult to exploit than a buffer overflow,
but the security implications can be just as severe.
One iteration of API design didn't solve the problems, but perhaps a further one can…
Enter,
strlcpy():
size_t strlcpy(char *dst, const char *src, size_t size);
strlcpy()
is similar to
strncpy()
but copies at most
size-1
bytes from
src
to
dst,
and always adds a null terminator following the bytes copied to
dst.
Problems solved?
strlcpy()
avoids buffer overruns and ensures that the output string is null terminated.
So why have the glibc maintainers obstinately refused to accept it?
The essence of the argument against
strlcpy()
is that it fixes one problem—sometimes failing to terminate
dst
in the case of
strncpy(),
buffer overruns in the case of
strcpy()—while leaving another:
the loss of data that occurs when the string copied from
src
to
dst
is truncated because it exceeds
size.
(In addition, there is still
an unusual corner case
where the unwary programmer can find that
strlcat(),
the analogous function for string concatenation,
leaves
dst
without a null terminator.)
At the very least,
(silent) data loss is undesirable to the user of the program.
At the worst, truncated data can lead to security issues that
may be as problematic as buffer overruns,
albeit probably harder to exploit.
(One of the nicer features of
strlcpy()
and
strlcat()
is that their return values do at least facilitate the detection of
truncation—if the programmer checks the return values.)
All of which brings us full circle:
to avoid unhappy users and security exploits,
in the general case even a call to
strlcpy()
(or
strlcat())
must be guarded by an
if
statement checking the arguments,
if the state of the arguments
can't be predicted with certainty in advance of the call.
Where are we now?
Today,
strlcpy()
and
strlcat()
are present on many versions of UNIX
(at least Solaris, the BSDs, Mac OS X, and Irix),
but not all of them (e.g., HP-UX and AIX).
There are even implementations of these functions
in the Linux kernel
for internal use by the kernel code.
Meanwhile, these functions are not present in glibc,
and were rejected for inclusion in
the POSIX.1-2008 standard,
apparently for similar reasons to their rejection from glibc.
Reactions among core glibc contributors on the topic of including
strlcpy()
and
strlcat()
have been varied
over the years.
Christoph Hellwig's early patch was rejected
in the then-primary maintainer's inimitable style
(1 and
2).
But reactions from other glibc developers have been more nuanced,
indicating,
for example,
some willingness to accept the functions.
Perhaps most insightfully,
Paul Eggert notes
that even when these functions are provided
(as an add-on packaged with the application),
projects such as OpenSSH,
where security is of paramount concern,
still manage to either misuse the functions (silently truncating data)
or use them unnecessarily (i.e., the traditional
strcpy()
and
strcat()
could equally have been used without harm);
such a state of affairs does not constitute a
strong argument for including the functions in glibc.
The appearance of an
embryonic
entry on this topic in the glibc FAQ,
with a brief rationale for why these functions are currently excluded,
and a note that "gcc -D_FORTIFY_SOURCE"
can catch many of the errors that
strlcpy()
and
strlcat()
were designed to catch,
would appear to be something of a final word on the topic.
Those that still feel that these functions should be in glibc
will have to make do with the
implementations provided in
libbsd
for now.
Finally,
in case it isn't obvious by now,
it should of course be noted that the root of this problem lies
in the C language itself.
C's native strings are not
managed strings
of the style natively provided in more modern languages such as Java, Go, and D.
In other words, C's strings have no notion of bounds checking
(or dynamically adjusting a string's boundary) built into the type itself.
Thus, when using C's native string type,
the programmer can never entirely avoid the task of
checking string sizes when strings are manipulated,
and no replacements for
strcpy()
and
strcat()
will ever remove that need.
One might even wonder if the original C library implementers were clever
enough to realize from the start that
strcpy()
and
strcat()
were sufficient—if it weren't for the fact that they also gave us
gets().
Comments (95 posted)
Brief items
But it’s worse than that. Much worse. You’re not going to be sent to jail for refusal to give up encryption keys. You’re going to be sent to jail for an inability to unlock something that the police think is encrypted. Yes, this is where the hairs rise on our arms: if you have a recorded file with radio noise from the local telescope that you use for generation of random numbers, and the police asks you to produce the decryption key to show them the three documents inside the encrypted container that your radio noise looks like, you will be sent to jail for up to five years for your inability to produce the imagined documents.
--
Rick
Falkvinge
The practice of upstream filtering raises a number of questions, including jurisdictional issues and the lack of recourse available to users in Oman. The application of filters in India restricts Internet users in Oman from accessing content, potentially even content produced in Oman itself, as a result of actions taken for domestic purposes within India. Users in Oman did not consent to this blocking, are left with little recourse for challenging these actions, and have limited means of accessing this content, which may or may not be in violation of Omani regulations. Combined with the significant filtering implemented by Omantel itself, this practice places Internet users in Oman behind multiple layers of national-level filtering.
--
Citizen
Lab on upstream filtering in India affecting internet users in Oman
Comments (17 posted)
Lennart Poettering has
informed
the world that the systemd init daemon now has initial support for the
seccomp filter mechanism found in the 3.5
kernel. The end result is that processes can be easily configured to be
run in a sandboxed environment. "
It's actually really cool, and dead
simple to use. A Cheers! for security!"
Comments (24 posted)
The Android project has published an
Android Security
Overview that provides information about Android security at the system
and kernel level as well as application security and more. "
This document outlines the goals of the Android security program, describes the fundamentals of the Android security architecture, and answers the most pertinent questions for system architects and security analysts. This document focuses on the security features of Android's core platform and does not discuss security issues that are unique to specific applications, such as those related to the browser or SMS application. Recommended best practices for building Android devices, deploying Android devices, or developing applications for Android are not the goal of this document and are provided elsewhere."
Comments (3 posted)
New vulnerabilities
automake: code execution
| Package(s): | automake |
CVE #(s): | CVE-2012-3386
|
| Created: | July 12, 2012 |
Updated: | April 5, 2013 |
| Description: |
From the Mandriva advisory:
A vulnerability has been discovered and corrected in automake:
A race condition in automake (lib/am/distdir.am) could allow a local
attacker to run arbitrary code with the privileges of the user running
make distcheck (CVE-2012-3386).
|
| Alerts: |
|
Comments (none posted)
exif: information leak
| Package(s): | exif |
CVE #(s): | CVE-2012-2845
|
| Created: | July 13, 2012 |
Updated: | April 5, 2013 |
| Description: |
From the Mandriva advisory:
An integer overflow in the function jpeg_data_load_data in the exif
program could cause a data read beyond the end of a buffer, causing
an application crash or leakage of potentially sensitive information
when parsing a crafted JPEG file. |
| Alerts: |
|
Comments (none posted)
extplorer: cross-site request forgery
| Package(s): | extplorer |
CVE #(s): | CVE-2012-3362
|
| Created: | July 13, 2012 |
Updated: | July 18, 2012 |
| Description: |
From the Debian advisory:
John Leitch has discovered a vulnerability in eXtplorer, a very feature
rich web server file manager, which can be exploited by malicious people
to conduct cross-site request forgery attacks.
The vulnerability allows users to perform certain actions via HTTP requests without performing any validity checks to verify the request. This can be exploited for example, to create an administrative user account by tricking an logged administrator to visiting an attacker-defined web link. |
| Alerts: |
|
Comments (none posted)
glibc: multiple vulnerabilities
| Package(s): | glibc |
CVE #(s): | CVE-2012-3404
CVE-2012-3405
CVE-2012-3406
|
| Created: | July 18, 2012 |
Updated: | August 16, 2012 |
| Description: |
From the Red Hat advisory:
Multiple errors in glibc's formatted printing functionality could allow an
attacker to bypass FORTIFY_SOURCE protections and execute arbitrary code
using a format string flaw in an application, even though these protections
are expected to limit the impact of such flaws to an application abort. |
| Alerts: |
|
Comments (none posted)
gypsy: multiple vulnerabilities
| Package(s): | gypsy |
CVE #(s): | CVE-2011-0523
CVE-2011-0524
|
| Created: | July 17, 2012 |
Updated: | August 13, 2012 |
| Description: |
From the openSUSE advisory:
Add gypsy-CVE-2011-0523.patch: add config file to
restrict the files that can be read.
Add gypsy-CVE-2011-0524.patch: use snprintf() to avoid
buffer overflows.
Add gnome-common BuildRequires and call to
gnome-autogen.sh for gypsy-CVE-2011-0523.patch, since it
touches the build system. |
| Alerts: |
|
Comments (none posted)
libexif: multiple vulnerabilities
| Package(s): | libexif |
CVE #(s): | CVE-2012-2812
CVE-2012-2813
CVE-2012-2814
CVE-2012-2836
CVE-2012-2837
CVE-2012-2840
CVE-2012-2841
|
| Created: | July 13, 2012 |
Updated: | April 5, 2013 |
| Description: |
From the Mandriva advisory:
A heap-based out-of-bounds array read in the exif_entry_get_value
function in libexif/exif-entry.c in libexif 0.6.20 and earlier allows
remote attackers to cause a denial of service or possibly obtain
potentially sensitive information from process memory via an image
with crafted EXIF tags (CVE-2012-2812).
A heap-based out-of-bounds array read in the exif_convert_utf16_to_utf8
function in libexif/exif-entry.c in libexif 0.6.20 and earlier allows
remote attackers to cause a denial of service or possibly obtain
potentially sensitive information from process memory via an image
with crafted EXIF tags (CVE-2012-2813).
A buffer overflow in the exif_entry_format_value function in
libexif/exif-entry.c in libexif 0.6.20 allows remote attackers to
cause a denial of service or possibly execute arbitrary code via an
image with crafted EXIF tags (CVE-2012-2814).
A heap-based out-of-bounds array read in the exif_data_load_data
function in libexif 0.6.20 and earlier allows remote attackers to
cause a denial of service or possibly obtain potentially sensitive
information from process memory via an image with crafted EXIF tags
(CVE-2012-2836).
A divide-by-zero error in the mnote_olympus_entry_get_value function
while formatting EXIF maker note tags in libexif 0.6.20 and earlier
allows remote attackers to cause a denial of service via an image
with crafted EXIF tags (CVE-2012-2837).
An off-by-one error in the exif_convert_utf16_to_utf8 function in
libexif/exif-entry.c in libexif 0.6.20 and earlier allows remote
attackers to cause a denial of service or possibly execute arbitrary
code via an image with crafted EXIF tags (CVE-2012-2840).
An integer underflow in the exif_entry_get_value function can cause a
heap overflow and potentially arbitrary code execution while formatting
an EXIF tag, if the function is called with a buffer size parameter
equal to zero or one (CVE-2012-2841). |
| Alerts: |
|
Comments (none posted)
libxslt: denial of service
| Package(s): | libxslt,libxslt-python |
CVE #(s): | CVE-2012-2825
|
| Created: | July 17, 2012 |
Updated: | October 4, 2012 |
| Description: |
From the CVE entry:
The XSL implementation in Google Chrome before 20.0.1132.43 allows remote attackers to cause a denial of service (incorrect read operation) via unspecified vectors. |
| Alerts: |
|
Comments (none posted)
libytnef: buffer overflow
| Package(s): | libytnef |
CVE #(s): | |
| Created: | July 16, 2012 |
Updated: | April 10, 2013 |
| Description: |
Fedora has added a patch to libytnef 1.5 that fixes a possible buffer overflow. See this bug in the Red Hat bugzilla. |
| Alerts: |
|
Comments (none posted)
mono: cross-site scripting
| Package(s): | mono |
CVE #(s): | CVE-2012-3382
|
| Created: | July 13, 2012 |
Updated: | August 23, 2012 |
| Description: |
From the Debian advisory:
Marcus Meissner discovered that the web server included in Mono performed
insufficient sanitising of requests, resulting in cross-site scripting.
|
| Alerts: |
|
Comments (none posted)
mozilla: multiple vulnerabilities
| Package(s): | firefox, thunderbird, seamonkey |
CVE #(s): | CVE-2012-1948
CVE-2012-1950
CVE-2012-1951
CVE-2012-1952
CVE-2012-1953
CVE-2012-1954
CVE-2012-1955
CVE-2012-1957
CVE-2012-1958
CVE-2012-1959
CVE-2012-1961
CVE-2012-1962
CVE-2012-1963
CVE-2012-1964
CVE-2012-1965
CVE-2012-1966
CVE-2012-1967
CVE-2012-1949
|
| Created: | July 18, 2012 |
Updated: | August 15, 2012 |
| Description: |
From the Red Hat advisory:
A web page containing malicious content could cause Firefox to crash or,
potentially, execute arbitrary code with the privileges of the user running
Firefox. (CVE-2012-1948, CVE-2012-1951, CVE-2012-1952, CVE-2012-1953,
CVE-2012-1954, CVE-2012-1958, CVE-2012-1962, CVE-2012-1967)
A malicious web page could bypass same-compartment security wrappers (SCSW)
and execute arbitrary code with chrome privileges. (CVE-2012-1959)
A flaw in the context menu functionality in Firefox could allow a malicious
website to bypass intended restrictions and allow a cross-site scripting
attack. (CVE-2012-1966)
A page different to that in the address bar could be displayed when
dragging and dropping to the address bar, possibly making it easier for a
malicious site or user to perform a phishing attack. (CVE-2012-1950)
A flaw in the way Firefox called history.forward and history.back could
allow an attacker to conceal a malicious URL, possibly tricking a user
into believing they are viewing a trusted site. (CVE-2012-1955)
A flaw in a parser utility class used by Firefox to parse feeds (such as
RSS) could allow an attacker to execute arbitrary JavaScript with the
privileges of the user running Firefox. This issue could have affected
other browser components or add-ons that assume the class returns
sanitized input. (CVE-2012-1957)
A flaw in the way Firefox handled X-Frame-Options headers could allow a
malicious website to perform a clickjacking attack. (CVE-2012-1961)
A flaw in the way Content Security Policy (CSP) reports were generated by
Firefox could allow a malicious web page to steal a victim's OAuth 2.0
access tokens and OpenID credentials. (CVE-2012-1963)
A flaw in the way Firefox handled certificate warnings could allow a
man-in-the-middle attacker to create a crafted warning, possibly tricking
a user into accepting an arbitrary certificate as trusted. (CVE-2012-1964)
A flaw in the way Firefox handled feed:javascript URLs could allow output
filtering to be bypassed, possibly leading to a cross-site scripting
attack. (CVE-2012-1965) |
| Alerts: |
|
Comments (none posted)
mozilla: denial of service
| Package(s): | firefox, thunderbird |
CVE #(s): | CVE-2012-1960
|
| Created: | July 18, 2012 |
Updated: | August 1, 2012 |
| Description: |
From the Ubuntu advisory:
Tony Payne discovered an out-of-bounds memory read in Mozilla's color
management library (QCMS). If the user were tricked into opening a specially
crafted color profile, an attacker could possibly exploit this to cause a
denial of service via application crash. |
| Alerts: |
|
Comments (none posted)
nova: denial of service
| Package(s): | nova |
CVE #(s): | CVE-2012-3371
|
| Created: | July 12, 2012 |
Updated: | July 18, 2012 |
| Description: |
From the Ubuntu advisory:
Dan Prince discovered that the Nova scheduler, when using
DifferentHostFilter or SameHostFilter, would make repeated database
instance lookup calls based on passed scheduler hints. An authenticated
attacker could use this to cause a denial of service. |
| Alerts: |
|
Comments (none posted)
openldap: weaker than expected encryption
| Package(s): | openldap |
CVE #(s): | CVE-2012-2668
|
| Created: | July 17, 2012 |
Updated: | August 9, 2012 |
| Description: |
From the CVE entry:
libraries/libldap/tls_m.c in OpenLDAP, possibly 2.4.31 and earlier, when using the Mozilla NSS backend, always uses the default cipher suite even when TLSCipherSuite is set, which might cause OpenLDAP to use weaker ciphers than intended and make it easier for remote attackers to obtain sensitive information. |
| Alerts: |
|
Comments (none posted)
puppet: multiple vulnerabilities
| Package(s): | puppet |
CVE #(s): | CVE-2012-3864
CVE-2012-3865
CVE-2012-3866
CVE-2012-3867
|
| Created: | July 13, 2012 |
Updated: | August 13, 2012 |
| Description: |
From the Debian advisory:
CVE-2012-3864: Authenticated clients could read arbitrary files on the puppet master.
CVE-2012-3865: Authenticated clients could delete arbitrary files on the puppet master.
CVE-2012-3866: The report of the most recent Puppet run was stored with world-readable permissions, resulting in information disclosure.
CVE-2012-3867: Agent hostnames were insufficiently validated. |
| Alerts: |
|
Comments (none posted)
rhythmbox: code execution
| Package(s): | rhythmbox |
CVE #(s): | CVE-2012-3355
|
| Created: | July 12, 2012 |
Updated: | August 6, 2012 |
| Description: |
From the Ubuntu advisory:
Hans Spaans discovered that the Context plugin in Rhythmbox created a
temporary directory in an insecure manner. A local attacker could exploit
this to execute arbitrary code as the user invoking the program. The
Context plugin is disabled by default in Ubuntu. |
| Alerts: |
|
Comments (none posted)
Page editor: Jake Edge
Next page: Kernel development>>