Live data from Hacker News

Glibc getaddrinfo stack-based buffer overflow

googleonlinesecurity.blogspot.com

471–480 of 480 posts

Re: Glibc getaddrinfo stack-based buffer overflow

#471
post #405

Earlier quoted context omitted.

As long as the function is doing one thing conceptually, I don't see the benefit of breaking it up into multiple routines just because it's too long (for some arbitrary length). Not only do you have the cognitive overhead of trying to come up with a name [1], but passing in all the required parameters to the function. And for this function, I personally don't see any good "breaking points". At work, I have to deal wi…

It's true that a function in an expressive language can be 10 lines, which in C is 70 lines just because of verbosity (repeated assigns instead of constructors and so on). So while the threshold is certainly higher in C, this is still too large. It does 3-4 things conceptually but 2 (lookups) are already broken out. I can see at least one opportunity more for extracting a function. It's important not least because of…

I'd like to know what you would extract out to its own function, because I certainly don't seen anything worth making its own function.

Re: Glibc getaddrinfo stack-based buffer overflow

#472
post #471

Earlier quoted context omitted.

It's true that a function in an expressive language can be 10 lines, which in C is 70 lines just because of verbosity (repeated assigns instead of constructors and so on). So while the threshold is certainly higher in C, this is still too large. It does 3-4 things conceptually but 2 (lookups) are already broken out. I can see at least one opportunity more for extracting a function. It's important not least because of…

I'd like to know what you would extract out to its own function, because I certainly don't seen anything worth making its own function.

Maybe it's just my aversion to C (and procedural) in general but I think assigning 3 fields of the same struct in succession as a sign that you are making an inline constructor that should be explicit. The chunk I meant looked like a possibility though was the hint bit.

The point of smaller code is testability. It's worth even making it somewhat harder to read. If a test makes three things in succession that in their own functions would have required 3 tests each, the aggregated do-everything function requires much more than the 9 test cases. So dividing the method in two, even if arbitrary and bad for readability can have a positive impact since the total code volume is reduced a lot.

All of this ^ only applies if the code actually has tests. If not - then don't divide arbitrarily if it reduces readability at all. But then again without tests you have bigger problems than readability...

Re: Glibc getaddrinfo stack-based buffer overflow

#474
post #471

Earlier quoted context omitted.

I'd like to know what you would extract out to its own function, because I certainly don't seen anything worth making its own function.

Maybe it's just my aversion to C (and procedural) in general but I think assigning 3 fields of the same struct in succession as a sign that you are making an inline constructor that should be explicit. The chunk I meant looked like a possibility though was the hint bit. The point of smaller code is testability. It's worth even making it somewhat harder to read. If a test makes three things in succession that in their…

It's your aversion to C, because the hint thing does not do what you think it does. It doesn't assign three fields of a structure, it pulls three fields out of a structure (and in my opinion, making a function just to do that is silly---it's not an opaque object (as it's documented in man pages as to the fields it has), hides the intent and further more, clutters up the code.

If you make this "accessor" function static [1], then you have to include the test code in the same C file (cluttering that file with code only used for testing [2]) or you clutter the C global function namespace with a function that's quite possibly only used on one location (and thus, can't be inlined at all due to C semantics---just some of the realities of attempting TDD in C).

[1] Functions and variable marked as "static" are only visible in the file.

[2] And you end up with pretty much dead code in a release version. You could exclude such code from a release build, but then you can't actually test the release build of each function.

Re: Glibc getaddrinfo stack-based buffer overflow

#475
post #474

Earlier quoted context omitted.

Maybe it's just my aversion to C (and procedural) in general but I think assigning 3 fields of the same struct in succession as a sign that you are making an inline constructor that should be explicit. The chunk I meant looked like a possibility though was the hint bit. The point of smaller code is testability. It's worth even making it somewhat harder to read. If a test makes three things in succession that in their…

It's your aversion to C, because the hint thing does not do what you think it does. It doesn't assign three fields of a structure, it pulls three fields out of a structure (and in my opinion, making a function just to do that is silly---it's not an opaque object (as it's documented in man pages as to the fields it has), hides the intent and further more, clutters up the code. If you make this "accessor" function stat…

I used to think C was bad without even considering the lacking modules/namespaces etc and what it means for testing. It does encourage few and large hard-to-test public functions. Am I right in suspecting that the test suites of libs like these are pretty small?

Re: Glibc getaddrinfo stack-based buffer overflow

#476
post #212

Earlier quoted context omitted.

Or perhaps he made a more subtle point: you can't replace all C with Rust. Even if you rewrite the libc (you'll need some assembly), even if you rewrite the kernel (you'll need a lot of assembly and "unsafe"), there will still be lots of closed-source C running on undocumented components of your computer as firmware. C is just representative of computers as they really are today, for a bunch of reasons (mostly pragma…

Agree. "C" to OS, Kernel, Computer Language, applications is like oxygen is to life on earth. Yes, O2 causes fire from time to time, but you can't live without it.

Do you know of a language called "C", as opposed to C?

Re: Glibc getaddrinfo stack-based buffer overflow

#477
post #464
post #160

Earlier quoted context omitted.

Is djbdns vulnerable? It does not use these routines. I've never needed ENDS0, but maybe the need will arise someday. Meanwhile... Short term, I'd prefer to expunge all "C networking code" originating from BIND authors, e.g., libresolv.

The fact that djbdns doesn't use BIND code is not really relevant. The problem at hand is in the BIND DNS client library that is compiled and linked into applications. It's triggered by sending responses larger than 2048 bytes to those applications. The only way that djbdns factors into it is whether an attacker, running a content DNS server out on Internet, can manage to get such a DNS response through a DNS proxy s…

"The fact that djbdns doesn't use BIND code is not really relevant."

It is to me.

It's true that in this case it's not what mitigates this vulnerability. Although it has certainly mitigated many others over the years and, sadly, probably will do so a few more times in the future. There's just no getting rid of the BIND legacy.

Correct me if I am wrong, but using a local dnscache and the fact that dnscache does not implement ENDS0 should be enough to mitigate this one.

I have been running a local tinydns root.zone and dnscache for many years. Really like the software.

Re: Glibc getaddrinfo stack-based buffer overflow

#478
post #461
post #386

Earlier quoted context omitted.

You've hamstring the type system at the interface , internally you still get all the benefits. In any case, a typical use-case for a shared library like this is embedded into other applications, which may not be written in Rust at all, and hence things like generics don't work anyway. In fact, this is reflected in a common way to expose an interface in this manner: have a main Rust interface (i.e. with normal generic…

Personally, I've always thought that type safety provides the most benefit at boundaries between codebases: you have people composing pieces that they don't understand, and the types serve to guide how those pieces can be composed to result in a correct program. Within a library, it's not uncommon that the core data structure or processing is only correct because a human looked hard at it--I would be surprised if Rus…

> Personally, I've always thought that type safety provides the most benefit at boundaries between codebases: you have people composing pieces that they don't understand, and the types serve to guide how those pieces can be composed to result in a correct program.

Yeah, type safety is definitely a big benefit when joining pieces together, but writing normal Rust code does this too, it's only the cross-language boundary that suffers (this is of course the most critical one, so having tools that avoid mistakes here is important, like autogenerating a C header). Joining random codebases together is especially common with cargo making it so easy to pull in dependencies.

Please don't misinterpret me: I definitely don't disagree with you that having in-language type safety and generics are important, but those are fundamentally not things you can guarantee when you're doing things across languages.

> Within a library, it's not uncommon that the core data structure or processing is only correct because a human looked hard at it--I would be surprised if Rust implementations of, say, font rendering, used types internally to guarantee the correctness of their rendering relative to a formal specification. Instead they're using types to make sure they process all input, or make sure they handle memory safely.

I would hope/expect libraries to use types internally. That's the easiest way to have the computer stop you screwing up. E.g. the standard library does, the Vec type contains a RawVec to manage memory ( https://github.com/rust-lang/rust/blob/a212264011289885bdb8b... ) and similarly with HashMap ( https://github.com/rust-lang/rust/blob/a212264011289885bdb8b... ).

> an assumption-free one compiled considering generics to be opaque blobs and using dynamic dispatch for trait methods so that the same code can be used for all instantiations of the generic function.

> For example, a function parameterized over an unconstrained type T can't do anything useful with values of that type, except dropping them. Thus code would be generated in which the call to the drop impl would be dynamic.

This sounds nice on the face of it... but it also sounds outlandishly complicated to implement. On the latter quote, a function can also move data around, and moving (unknown-size) data around seems difficult, e.g. what's an always-works impl of the following?

    fn push(x: &mut Vec, y: T) { let z = y; x.push(z) }
Note, no bounds.

Calling object safe methods (like a destructor) is the easiest part of implementing this.

> I think this can be made to work w/r/t non-object-safe trait bounds as well, but I'm not sure how to justify that.

I'd be... surprised; non-object safe traits suffer from all the problems of the `push` example, and more.

Re: Glibc getaddrinfo stack-based buffer overflow

#479
post #474

Earlier quoted context omitted.

It's your aversion to C, because the hint thing does not do what you think it does. It doesn't assign three fields of a structure, it pulls three fields out of a structure (and in my opinion, making a function just to do that is silly---it's not an opaque object (as it's documented in man pages as to the fields it has), hides the intent and further more, clutters up the code. If you make this "accessor" function stat…

I used to think C was bad without even considering the lacking modules/namespaces etc and what it means for testing. It does encourage few and large hard-to-test public functions. Am I right in suspecting that the test suites of libs like these are pretty small?

I think it really depends upon the codebase. Libraries are easier to test than applications in general, since you have a published API to throw at testing. One approach (and it seems to work for LuaJIT, a mid-sized C based project) is to just collect test cases as bugs arise (create the smallest input possible to trigger the bug in question) and as changes are made, rerun all those cases as a type of ever-growing regression test.

Or, you know, run a fuzzer.

Re: Glibc getaddrinfo stack-based buffer overflow

#480
post #110

Earlier quoted context omitted.

An intermediate step is to run everything under AddressSanitizer, since it's fast enough for many cases. See, for example: https://blog.hboeck.de/archives/879-Safer-use-of-C-code-runn...

It likely won't help. I excluded glibc from using ASAN to let this work. It is theoretically possible to use ASAN on glibc as well, but it's complicated and certainly not ready for any kind of production use. Also although this is my work, it's far from clear to me whether using ASAN in production really is a useful thing. Practically I'd rather suggest looking at the safestack and CFI features of clang for productio…

BTW at least Clang's ASan is capable of detecting CVE-2015-7547 (in https://groups.google.com/forum/#!topic/address-sanitizer/tt...).
Post reply on HN