CVE-2015-0235 – GHOST: glibc gethostbyname buffer overflow
openwall.com
openwall.com
https://gist.github.com/koelling/ef9b2b9d0be6d6dbab63
To test your system, simply run this (but obviously only after making sure gistfile1.c is clean ;))
wget https://gist.githubusercontent.com/koelling/ef9b2b9d0be6d6dbab63/raw/de1730049198c64eaf8f8ab015a3c8b23b63fd34/gistfile1.c
gcc gistfile1.c -o CVE-2015-0235
./CVE-2015-0235Reproducers are standard fare and it's not like the code in this case is obfuscated. Are magic code goblins going to come and invoke Ken Thompson's untrustable computing and make your computer install windows and join a botnet or something?
That aside, I actually did type it into my disposable VM. The theory being that if there was something subtle, it would force me either to type it wrong and not be exploited due to cognitive blindness or I'd catch the problem and avoid it.
I've read too many IOCC entries and I probably am a bit paranoid.
> You're piping random executables from the internet
> without even looking at them to see what they do if you
> run that command
... and then in your profile: > Just another Perl hacker.
You audit every CPAN module you install, line by line, right?You can check your libc version with:
ldd --versionLots of info about their discovery. Apparently they developed a PoC exploit. They've also included a pretty short test program to determine if a system is vulnerable or not.
Here's a gist of the test (copied from their advisory): https://gist.github.com/amlweems/6e78d03810548b4867d6
- At most sizeof(char *) bytes can be overwritten (ie, 4 bytes on 32-bit
machines, and 8 bytes on 64-bit machines). Bytes can be overwritten
only with digits ('0'...'9'), dots ('.'), and a terminating null
character ('\0').
- Despite these limitations, arbitrary code execution can be achieved.
As a proof of concept, we developed a full-fledged remote exploit
against the Exim mail server, bypassing all existing protections
(ASLR, PIE, and NX) on both 32-bit and 64-bit machines. We will
publish our exploit as a Metasploit module in the near future.
Wow, that's actually amazing! I never would have thought it possible. As tonyhb says, it will be really interesting 'in the near future' to see how they managed to do it.Also surprising to note that we've been vulnerable since November 2000.
I checked the configs on two of my systems, one default, and one heavily customized, neither had the helo verification turned on.
lsof | grep libc | awk '{print $1}' | sort | uniq
[1] http://ma.ttias.be/critical-glibc-update-cve-2015-0235-getho... ~# netstat -lnp | grep -e "\(tcp.*LISTEN\|udp\)" | cut -d / -f 2- | sort -u
cupsd
dnsmasq
httpd
nmbd
ntpd
qemu-kvm
rpc.portmap
rpc.statd
sendmail: acce
smbd
ssh
sshd[1]https://www.owasp.org/index.php/XML_External_Entity_%28XXE%2...
"UseDNS no" in your sshd_config is a good idea in general.
>lsof +c 64
lsof: +c 64 > what system provides (15)
So
lsof +c 15 is maximum
If would be nice if package managers would let us know when this is necessary, I expect that might be a hard thing to get right though.
sudo lsof | grep lib | grep DEL
You can then either reload those processes manually, or just bounce the box if that's easier.
Deleted comment
I wouldn't normally nitpick about something like this, but if people follow your advice they might incorrectly think they don't need to reboot.
Maybe you have a cut-and-paste error? The before and after look the same to me, no "(deleted)" to be seen.
Upstream patch: https://sourceware.org/git/?p=glibc.git;a=commit;h=d5dd6189d... Full diff: https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=d5dd6...
Red Hat bug: https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2015-0235
Debian bug: https://bugs.debian.org/776391
Great write-up from the discoverer (Qualys): http://www.openwall.com/lists/oss-security/2015/01/27/9 - thanks amlweems! (https://news.ycombinator.com/item?id=8954069)
It looks like when an application calls a function of the gethostbyname()/gethostbyname_r() family but passes a buffer and a buffer length that is too short to store the result, then the function sometimes fails to detect there is not enough space due to a miscalculation of how much space it needs, leading to a heap overflow. This means potentially arbitrary code execution! Edit: Both the reentrant version (gethostbyname_r) and non-reentrant one (gethostbyname) are affected (the non-reentrant one uses a fixed buffer length). The scope of this vulnerability is huge! A lot of server applications attempt to resolve or reverse-resolve network clients's hostnames or IP addresses when a connection is established, so they would all be potentially vulnerable: the malicious client controlling his DNS records simply needs to return specially crafted hostname or address data that is too big to fit in the buffer. And this affects everything, no matter what language the server application is written in: C, Python, PHP, Java...
Edit #2: it looks like the bug was patched 2 years ago, but the fact it was exploitable was not understood until today, hence why a CVE was only assigned now.
Edit #3: Apps written in Golang are not vulnerable: https://news.ycombinator.com/item?id=8954011 - thanks 4ad!
/edit: a second note about Go; even without the native resolver, Go uses getaddrinfo, not gethostbyname*, and it's not vulnerable.
dpkg -s libc6
For my Debian 7 servers it reports "Version: 2.13-38+deb7u7" after upgrading. Everything below that (eg. "*u6") is vulnerable. I don't know about the specific version numbers in Ubuntu though.
Edit: the fixed Ubuntu version is "2.15-0ubuntu10.10"
This overstates things a bit - hostnames that can be returned by the reverse DNS resolver can't trigger the vulnerability (maximum label length of 63). It needs to be a hostname supplied by a non-DNS method (eg. the POC uses the HELO SMTP command).
Assuming the runtime links to glibc, which unfortunately most do.
"A heap-based buffer overflow was found in __nss_hostname_digits_dots(), which is used by the gethostbyname() and gethostbyname2() glibc function call. A remote attacker could use this flaw to execute arbitary code with the permissions of the user running the application."
Note that this is a HEAD link, so if there are changes after I post this they should appear. I don't claim to have spotted the suspicious code (it's not ... super-accessible), just wanted to provide a link to the file in question.
> Avoid arbitrary limits on the length or number of any data structure, including file names, lines, files, and symbols, by allocating all data structures dynamically.
the entire hostname (including the delimiting dots but not a trailing dot) has a maximum of 253 ASCII characters
In general that is a good guideline, but when the standard (RFC1035) says there is an absolute limit, there is little value in going above that as it is likely that other systems won't be able to handle it. The added complexity of dynamic allocation is also an opportunity for bugs, like this one.
Again, this is especially silly if (as it appears to first glance) the bug is in a hostname validation function, and so flexible allocation could only ever be useful in the case of a hostname that must fail validation anyways.
In fact, it looks like if you get to the dynamic allocation section, it will fix the problem. One could argue that the whole problem stems from having a bug in a complex computation of buffer size to handle lots of different bits of data, rather than dynamically allocating the individual bits as needed.
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses */
}
The pointers in the structure point into the buffer. There could be any number of host aliases or IP addresses.(edit) You may be totally right here, by the way.
In that specific case there are no aliases and exactly one IP address, but the buffer could still be too small (e.g. if caller-supplied with gethostbyname_r()).
Deleted comment
Similarly, they usually use busybox ash as a shell and thus weren't vulnerable to shellshock.
Some do use openssl, so might still be affected by heartbleed.
On the other hand, I shall now work hard to stop worrying about undiscovered vulnerabilities in uclibc.
http://www.frsag.org/pipermail/frsag/2015-January/005722.htm... From: Mar 27 Jan 15:28:45 CET 2015
Half an hour after Redhat lifted embargo from the ticket: https://bugzilla.redhat.com/show_activity.cgi?id=1183461 2015-01-27 10:03:14 EST Removed: EMBARGOED CVE-2015-0235
If this is true this lady gets an award for best security disclosure this year ;-)
https://www.mankier.com/3/gethostbyname
"The gethostbyname(), gethostbyaddr(), herror(), and hstrerror() functions are obsolete. Applications should use getaddrinfo(3), getnameinfo(3), and gai_strerror(3) instead."
1/ http://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB...
And not just because of IPv6.
getaddrinfo() is also a much more complicated function than gethostbyname(). If you need the extra features, fine. If you're writing new code, fine. But going back and trying to update existing code is just going to introduce new bugs.
I wanted to know what version of glibc and eglibc my servers were running so that I could check that they were getting updated. Running
dpkg -s glibc
and dpkg -s eglibc
turned up nothing. How could that be since there had to be a C library?!Answer: there are indeed compiled C libraries on my servers. I found that the key packages to update were related to libc6 (http://packages.ubuntu.com/precise/libc6), which were compiled from eglibc.
At any rate, I patched my servers with a typical procedure:
sudo apt-get update
sudo unattended-upgrades
BTW, it helped me to understand that Ubuntu 12.04 uses eglibc and not glibc: http://askubuntu.com/questions/372864/why-ubuntu-uses-eglibc... to make sense of the charts at http://people.canonical.com/~ubuntu-security/cve/2015/CVE-20..., especially the reason for the "DNE" (does not exist?) for Ubuntu 12.04 and glibc.Hope this is clarifying to someone out there. Would love to hear confirmation or refutation of my reasoning here.
$ dpkg -S /lib/x86_64-linux-gnu/libc.so.6
libc6:amd64: /lib/x86_64-linux-gnu/libc.so.6
Hence 'libc6' is the package as you figured out.If you want to see the status of a particular vulnerability in Debian, you can use the Security Tracker: https://security-tracker.debian.org/tracker/CVE-2015-0235 which links to the security advisory and tells you that the bug was fixed in version 2.13-38+deb7u7 of the package.
Note that any programs running before you upgraded the library will need to be restarted in order to use the fixed version. There's a program called checkrestart that will tell you which programs need to be restarted, or you can play it safe and reboot your system after applying library updates.
http://www.openwall.com/lists/oss-security/2015/01/27/9
Also contains a writeup about a remote Exim exploit (which is the default mail server on at least Debian).
101 *buffer_size = size_needed;
102 new_buf = (char *) realloc (*buffer, *buffer_size);
103
104 if (new_buf == NULL)
105 {
...
114 goto done;
115 }
It's a shame they put that "..." there, because this looked like another potential vulnerability to me, or at least something I would take very critically reading this code. (realloc fails, the caller's variable at buffer_size still gets assigned a larger value, next call thinks it has a larger buffer than it does). Line 110 assigns *buffer_size back to 0 so there is no such problem.[1] I wouldn't.
http://www.frsag.org/pipermail/frsag/2015-January/005727.htm...
http://www.frsag.org/pipermail/frsag/2015-January/005726.htm...
"I will keep you posted in next hours. I send the notice to early. Big fail of my own. Stay tuned."
According to this comment: https://news.ycombinator.com/item?id=8954458 , getaddrinfo() uses gethostbyname() internally. So, is a default 'UseDNS yes' ssh setup vulnerable or not?
Thus, an attacker controlling the PTR record for a given IP might provide a GHOST-compliant name in that PTR record; Then, connect to the ssh daemon, wait for it to read the PTR record - and if it gethostbyname() on it, it's game over.
Quite a few log processors would do that. The reason I'm worried specifically about sshd is that it is usually the only port ever listening to the world-and-not-firewalled on my servers (and a non-standard, at that - and only allowing public key authentication) - but despite this generally-regarded-as-secure setting, GHOST may prove it vulnerable.
From man sshd_config:
UseDNS Specifies whether sshd(8) should look up the
remote host name and check that the resolved host name
for the remote IP address maps back to the very same
IP address. The default is “yes”.changelog: * Mon Jan 19 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12-1.149.5 - Fix parsing of numeric hosts in gethostbyname_r (CVE-2015-0235, #1183533).
Qualys GHOST program returns "not vulnerable" after the upgrade.
Obviously there is some dependency that they forgot to add, so I would hold off on updating anything unless you don't really care if the server is offline for a while.
Deleted comment
This was related to iconv() and UTF8.
This is NOT the fix for this CVE.
Here is a list of potential targets that we investigated (they all call
gethostbyname, one way or another), but to the best of our knowledge,
the buffer overflow cannot be triggered in any of them:
apache, cups, dovecot, gnupg, isc-dhcp, lighttpd, mariadb/mysql,
nfs-utils, nginx, nodejs, openldap, openssh, postfix, proftpd,
pure-ftpd, rsyslog, samba, sendmail, sysklogd, syslog-ng, tcp_wrappers,
vsftpd, xinetd.
See "Re: Qualys Security Advisory CVE-2015-0235 - GHOST: glibc gethostbyname buffer overflow" <http://seclists.org/oss-sec/2015/q1/283>.How do I make my hosts secure?
http://chargen.matasano.com/chargen/2015/1/27/vulnerability-...
>> this vulnerability affects many systems from Linux glibc-2.2 version published on 10 November 2000.
>> a fixed was pushed to glibc-2.17 et glibc-2.18
Ran dpkg -l libc6 on 12.04.5 shows it's 2.15. So anything before 2.17?
/lib/x86_64-linux-gnu/libc.so.6 GNU C Library (Ubuntu EGLIBC 2.15-0ubuntu10.7) stable release version 2.15, by Roland McGrath et al.
Edit: Its back again. Booooo.
Having a shorthand to refer to the bug makes it more easy (and therefore more likely) that it will get referenced and discussed.
From http://www.openwall.com/lists/oss-security/2015/01/27/9 :
--[ 3 - Mitigating factors ]--------------------------------------------------
The impact of this bug is reduced significantly by the following reasons:
- A patch already exists (since May 21, 2013), and has been applied and
tested since glibc-2.18, released on August 12, 2013:
- The gethostbyname*() functions are obsolete; with the advent of IPv6,
recent applications use getaddrinfo() instead.
- Many programs, especially SUID binaries reachable locally, use
gethostbyname() if, and only if, a preliminary call to inet_aton()
fails. However, a subsequent call must also succeed (the "inet-aton"
requirement) in order to reach the overflow: this is impossible, and
such programs are therefore safe.
- Most of the other programs, especially servers reachable remotely, use
gethostbyname() to perform forward-confirmed reverse DNS (FCrDNS, also
known as full-circle reverse DNS) checks. These programs are generally
safe, because the hostname passed to gethostbyname() has normally been
pre-validated by DNS software:
. "a string of labels each containing up to 63 8-bit octets, separated
by dots, and with a maximum total of 255 octets." This makes it
impossible to satisfy the "1-KB" requirement.
. Actually, glibc's DNS resolver can produce hostnames of up to
(almost) 1025 characters (in case of bit-string labels, and special
or non-printable characters). But this introduces backslashes ('\\')
and makes it impossible to satisfy the "digits-and-dots"
requirement.
You would effectively have to control the DNS server, or spoof its responses, to get the software to accept a suitable exploit.would you? If you want to exploit something that does unauthenticated gethostbyaddr(), then yes, for that you need to control a DNS server (which, btw, isn't harder than controlling a web server to serve malware with).
On the other hand, if you can make your target call gethostbyname() on an arbitrary string, you don't need to control a DNS server.
There are many sites out there that go and fetch user supplied URLs - for example to fetch picture previews.
First you exploit one of these, install a DNS server on them and then you can also exploit the ones which only do gethostbyaddr() :-)
Fetching a user-supplied URL is not enough to exploit remotely. You have to exploit the target's DNS resolver, because you have to feed it invalid or impossible records. All existing DNS resolvers will reject these because they break RFC.
It would be much easier to exploit a web app and drop your payload and exploit it locally, which is what everyone currently does to pwn servers with rootkits.
Adding a tagline, media friendly name or keywords is unprofessional. Simply, severity is then ranked by how popular the press or security bloggers can market the word, not by the respective severity of the CVE. Its a popularity contest, nothing more.
As someone who deals with every damn sensationalist story at a financial company, having every fucking client phone up about every damn marketoid creation even if it doesn't affect our platform detracts from doing real work.
Let's play their trick:
Its the X Factor of security.
People actually giving a shit about security holes is something we've been wanting for a long time. It beats the hell out of the alternative, something we've been dealing with since the 90s or so!
We do that bit between the CVE being announced and patching ahit, not when the press goes ape shit.
So, that's overrated is it?
Plus, 99% of the time, end users are not directly responsible for patching these issues. So why the focus on mass-media friendly marketing?
Here is what is happening when vulnerabilities get their own brand names, with logos and marketing:
1. Vulnerabilities are implicitly severe if they attract media attention (and only if they attract media attention). I've been featured in the press twice for vulnerabilities. Neither of them were as serious as the least serious, unpublicized vulnerability on this page: https://hackerone.com/internet.
2. It implicitly encourages rating a vulnerability's severity by how much media attention it receives, not by an objective scale.
It's causing a race to the bottom where coordinated disclosure now requires a PR firm, a presskit, a logo, and a brand name. For Heartbleed and Shellshock, sure, they're serious enough for all those hoops. For everything else, the race to the bottom will commoditize these things, making vulnerabilities without them ignored, and confusing vulnerabilities with them as severe.
The final result is that it's just extra, meaningless noise tacked on to vulnerability disclosure that makes it more difficult to achieve, involves more parties and doesn't improve anything.
Between Heartbleed and Shellshock, and now this, a PR firm marketing vulnerabilities like this seems... crass.
In this case, it looks the name is probably not warranted.
It's version 2.13-38+deb7u7
A standard update command should get it, but if not you can find it here:
Feedback welcome:
http://product.reverb.com/2015/01/28/patching-cve-2015-0235-...
I've got some feedback though:
The bug has been fixed (May 21, 2013, between the releases of glibc-2.17 and glibc-2.18).
So your statement "This bug effects all versions of libc6 greater than 2.2+ (which was released Nov, 10, 2000) so you’ll be really lucky if you’re not vulnerable." is wrong.
For example, Ubuntu 14.04 uses glibc-2.19-1 which isn't affected.
--Conclusion: inet_aton() is the only option, and the hostname must have one of the following forms: "a.b.c.d", "a.b.c", "a.b", or "a", where a, b, c, d must be unsigned integers, at most 0xfffffffful, converted successfully (ie, no integer overflow) by strtoul() in decimal or octal (but not hexadecimal, because 'x' and 'X' are forbidden). --
So essentially, any DNS lookups of the form a.b.c.d, a.b.c, a.b, or a where a,b,c,d are all numbers, should be considered suspicious?
https://alas.aws.amazon.com/ALAS-2015-473.html
As usual, the Elastic Beanstalk team (with their forked yum repositories) are lagging behind on a fix.
The Qualys guys were unable to find any issues with sshd and tcp_wrappers. I imagine I'm not the only one that has /etc/hosts.deny setup to reject all but some IPs, but according to Qualys tests this issue cannot be triggered via someone with exploitable RDNS. As far as they know -- of course you should upgrade when you can.
for s in $(lsof | grep libc | awk '{print $1}' | sort | uniq); do if [[ -f "/etc/init.d/$s" && "$(ps aufx | grep -v grep | grep $s)" ]]; then echo $s; service $s restart; fi; done
From: http://blog.wallarm.com/post/109402223343/ghost-a-brief-reca...
size_needed = (sizeof (*host_addr)
- + sizeof (*h_addr_ptrs) + strlen (name) + 1);
+ + sizeof (*h_addr_ptrs)
+ + sizeof (*h_alias_ptr) + strlen (name) + 1);
Doesn't it seem disappointing that some programmers, for whatever reason, just can't seem to count correctly?FFS in this case they even found the bug and fixed it, but didn't notice how it could be a vulnerability. So even with eyes directly on issues, we (human programmers excluding djb) can't seem to get it right.
Heartbleed, Shellshock, Ghost. OpenSSL implemented their own memory allocator, so you would get the same result in another language. Shellshock was a parsing failure, memory safety had nothing to do with it, still arbitrary code execution. Ghost is very hard to exploit, which is why people didn't notice how it could be. It's like trying to exploit an off by one error.
Bugs in production code are not "safe" regardless of what language you use. What we need are better ways to find bugs before the code is put into production.
Heartbleed would not happen just because of a custom allocator. Eg Rust allows you to do so, but would have prevented that code from compiling.
Basically, using C/C++ means that in addition to all the normal security logic errors like command injection, you've got to worry that an errant copy or overflow hands total execution control to an attacker. It's bizarre to not realise this is a huge language failing and that most of the systems level exploits are purely due to poor languages. Even despite all the crazy codegen and memory janking b modern compilers and OSes do, even with some hardware support, it's still happening.
You're kind of answering your own question. Most OS bugs are in C because most OS code is in C.
> Heartbleed would not happen just because of a custom allocator. Eg Rust allows you to do so, but would have prevented that code from compiling.
If you get a large buffer and then "allocate" it by returning pointers to pieces of it (or offsets if you don't have pointers), now the compiler/runtime only knows where the end of the buffer is, not where the end of the allocation is supposed to be. You can write dumb code in any language.
> Basically, using C/C++ means that in addition to all the normal security logic errors like command injection, you've got to worry that an errant copy or overflow hands total execution control to an attacker. It's bizarre to not realise this is a huge language failing and that most of the systems level exploits are purely due to poor languages.
The problem with this reasoning is that it's solving the problem in the wrong place. Yes, if you screw up very badly then it's better for the language to blow up the program than let the attacker control it. But you still have to solve the other problem, which is that the attacker can blow up the program or possibly do other things even with "safe" languages because the program is parsing unvalidated input etc. And solving that problem, which needs to happen regardless, causes the first problem to go away.
While you can write dumb code in any language, programmers somehow end up not writing remote code execution from simple copies in other languages. Yet in C, this keeps happening.
And what I'm saying is that you're solving the problem in the wrong place. I'll take a static analysis tool that will find a buffer overrun at compile time over a runtime that blows up the program in production, every time.
> While you can write dumb code in any language, programmers somehow end up not writing remote code execution from simple copies in other languages. Yet in C, this keeps happening.
Shellshock, eval, SQL injection, people will write dumb code that results in remote code execution using whatever you like.
> I'll take a static analysis tool that will find a buffer
> overrun at compile time over a runtime that blows up the
> program in production, every time.
Then you'll love Rust, where the compiler is essentially one ultra-comprehensive static analyzer. :)If you make it idiot-proof, someone will make a better idiot.
That's 12 just in one of the more popular Java web frameworks.
RCE is possible in any language.
And even if these problems were as widespread, eliminating a huge class of errors is a big step up. Nearly every serious vulnerability in Microsoft's code for the past years is from memory unsafeness.
Hell, why bother with malaria or smallpox vaccines, since people just die from something else anyways.
Of course we should work to eliminate problems, but you have to consider the bigger picture and whether abandoning the language is worth it. So far the pros outweigh the few unique cons.
I'm far more disappointed that so many programmers haven't adopted better systems, systems that avoid the possibility of this kind of error entirely.
Yet there seems to exist this belief in the C world, that they can.
Link fix here: http://killtube.org/showthread.php?2118-GHOST-gethostbyname%...
http://askubuntu.com/questions/578565/ubuntu-12-04-5-lts-won...
It's time to start phasing out C/C++. Languages which don't know how big their arrays are have to go. If it can run efficiently in a garbage-collected environment, it should be in Go or some scripting language. If it can't use GC, Rust is almost there. (As I say occasionally, I really hope the Rust guys don't screw up.) C and C++ should not be used for new work.
It has been 1 days since the last buffer overflow vulnerability report.
Nobody to be taken serious has ever thought or said this -- it says about as much as "You know, I'm not perfect...".
Go itself (as of 1.3) is still itself coded in C, and I have no idea if/how C and Rust are related... C isn't going away, and tooling (Coverity, valgrind, nice compilers like clang) are our friends, as well as work like OpenBSDs string-handling ammendments, malloc() guards, etc.
I really am sympathetic to the complaints against C, but "Burn it!! It's a witch!" doesn't grab me.
Linus Torvalds is nobody to be taken seriously?
That said, Eric S. Raymond didn't say the quoted either. He said that "given enough eyeballs, all bugs are shallow", which is a much less bold claim (imo, at least) than that open source converges towards zero bugs over time.
How many eyes have actually looked at this code?
> We now know that the line "with many eyes, all bugs are shallow" is just wrong.
Remains approximately similar to saying, while watching the tide go out, that sea levels aren't rising. Anyone who ever thought it meant they were fixed instantaneously, and who uses the fact they get fixed and found as counter-proof of the sentiment, was wrong. It doesn't make the idea fundamentally wrong.
Array boundaries checking also has a performance hit but I am coming to think it is a necessary evil.
Dealing with strings as char arrays is just absurd. There isn't a significant performance hit to use some string datatype that reduce the opportunity for bugs.
And with closed source, who knows?!
>C and C++ should not be used for new work.
It's funny how articles on C/C++ seem to shoot to the front page here...
Well, unless you get rid of C/C++ interfaces in all syscalls or Win32 APIs, hell Microsoft tried that with managed code, and utterly failed to deliver.
Now, it is not always practical to use safe languages for everything (specially low level libraries such as say, libc...), and that 'huge category' of problems is not even remotely close to being all the security problems. But using tools that prioritize not shooting yourself in the foot by default is not bad consideration to make, all other things being similar.
Although I do not like the comparison because it's not factually correct, Rust is like the "safe subset of C++". To write actual safe, modern C++ is very close to writing valid Rust. After learning Rust, I became a better C++ programmer.
Either way, I am all for reducing the number of places where random pointer juggling happens inside a program, be it by using a VM or forbidding certain language features outside of small system libraries (e.g. by banning "unsafe fn" from your own Rust code or by using a static checker to force you to use only the "safe subset of C++"). That way we just need to get a couple thousand lines of code right to solve this particular class of nastiness forever, instead of the hundreds of millions of LOCs that live above the system abstractions.
While C was intended to run as close to bare metal as possible, and 99% of current implementations do, that doesn't have to be the case. The C specification describes an abstract machine, and uses abstract concepts, with explicit "as-if" rules saying that implementations may, in many cases, do whatever they want, providing that conforming code runs as if it would on a naive implementation.
So there's no reason at all that, for example, pointers have to be implemented as actual bare addresses in a virtual address space which cannot be bounds checked. It should be perfectly possible to create a new implementation, with a new ABI, which defines pointers as a checked type such that all accesses through a pointer are accurately bounds checked, with a guaranteed "virtual" segfault happening whenever an invalid read or write would have occurred.
Sure, it's not ABI-compatible (by defualt) with current bare-metal C ABIs, and would require shims to work with bare-metal C libraries - but that's no different than Rust and similar other new languages. Sure, it's not quite as fast as bare-metal C implementations due to enforced bounds checking, but it's not going to be slower than Rust and similar which do the same job.
And the advantage would be, we wouldn't need to rewrite all our code. We could just recompile all the existing C code we already have to this new safe ABI, rather than having to rewrite everything from scratch in some new language!
Sure, C isn't the nicest language to use. But we already have plenty of existing code that uses it. Why don't we just write a new compiler back-end and take advantage of all that code in a safe manner?
then type * p = &arr[i]
translates to struct pointer p = { arr, sizeof(arr), i * sizeof(arr[0]) }
Any any use of "(p + j)" or "p[j]" can check that (p->offset + j sizeof(p)) is greater than or equal to 0 and less than p->size. (Excuse my confused use of types in the above.)
"there might be existing C programs that rely on out of bounds access (where they know that the out of bounds access falls into safe memory)"
Those programs are completely non-portable. They could break with your next compiler upgrade, let alone moving to a different compiler (clang?) or a different OS (BSD?).
It could happen. Witness the people who complained about their broken programs when memcopy() was sped up by taking advantage of the standard, or those who were surprised when NULL checks started being discarded after a pointer had already been dereferenced.
Even so, if you did have such programs, and were unlucky enough to rely on them, and were unable to fix them to comply with the C language spec, there's no reason you couldn't still compile them for the existing bare-metal ABI. I'm not proposing to ban* the x86-64 ABI. I'm just saying lets create an additional (x86-64-safe?) ABI that we could use to provide a safe execution environment for a subset of our existing code. That subset could range from none of it to all of it, depending on how much you personally valued speed and anti-bloat over safety, how many non-conforming programs you relied upon, and whatever other factors you wanted to take into account.
Also, you can check your glibc version with this tiny code:
#include <stdio.h>
#include <gnu/libc-version.h>
int main (void) { puts (gnu_get_libc_version ()); return 0; }
(taken from a forum that I've since closed the page on, sorry for lack of attribution)<= 2.17 is unsafe, >= 2.18 is safe.
ldd --version might also do the trick.
> In particular, we discovered that it was fixed on May 21, 2013 (between the releases of glibc-2.17 and glibc-2.18)
Gentoo is listing glibc version 2.19-r1 as the latest stable version [2] and is using that per default.
Mail servers in particular generally make it pretty easy to trigger both forward and reverse lookups.
The test case seems to have it looking up an ip address as if it were a name, but it's using the reentrant version of the function - maybe only those are affected?
The release at http://www.frsag.org/pipermail/frsag/2015-January/005722.htm... says that it affects both gethostbyname() and gethostbyaddr().