Does a canary make these types of attacks impossible?
No, it doesn't. It makes it more difficult to perform return-to-libc or ROP but it is definitely no silver bullet against such attacks.
First of all, stack canaries only protect against return address smashing through buffer overflows. But there are other ways to corrupt memory: indirect pointer overwrite or format string vulnerabilities to name two.
Second, stack canaries may be bypassed by overwriting them with the original value. I'm not saying this is easy on modern implementations but it certainly isn't impossible.
Third, although the attacks are called return-to-libc and Return Oriented Programming, who says we need return instructions to carry out those attacks? These attacks can be initiated by corrupting any memory location from which the processor will load and address to jump to. The most common example is a function pointer. But we could also overwrite the GOT or longjmp
buffers. (As a side note, it has been shown that ROP can be performed without using any return instructions!)
The fourth reason is not a weakness of stack canaries in se but one of most implementations. Stack canaries are normally only placed in functions that have a stack based character buffer with a size of at least 8. Those implementation will therefore not detect overflows in other buffers. This exploit used an overflow in an integer array so it could not be detected by stack canaries.