This blogger is terribly ignorant, and the title of this submission is a gross misinterpretation of reality. Nothing has changed. There is one universal truth that has always and will always be true:

The version of a shared library found at runtime may be equal to or greater than the version used at link time, but never older.

The error that the article demonstrates is what you get from linking against version X and then trying to run the resulting binary against version Y, where Y < X. That has always been unsupported. If you were getting away with it previously, you were simply lucky, and now you've been bitten. No aspect of this has changed recently, it has been true since the very beginning of symbol versioning many years ago.

The details of this particular function is that memcpy() has always been documented as not supporting overlapping source and destinations -- you must use memmove() if that is the case. But by historical accident, the implementation of memcpy() in glibc until recently was okay with overlapping regions, which resulted in people writing broken code without realizing it. Recently when glibc wanted to implement a more optimized version, it found that some popular software broke -- one famous example was Adobe Flash, hallmark of shitty code. Since this was a binary-only plugin, it could not be simply recompiled and there was much noise made over the kerfuffle.

The solution that glibc employed was symbol versioning. This is the perfect example of exactly why symbol versioning was invented in the first place: it allows binaries linked against an older version of the library to continue using the old version of memcpy(), while proving a new version of the function for programs linked against the new version. Everyone wins.

Except you have people that want to link programs on one machine and run them on another machine. And they get error messages about symbol versions, because they are ignorant of how these things work. If you want to do that, then your development machine where the linking occurs must have the oldest version of glibc that you intend to support. This is the correct solution, not mucking about with __asm__ directives and whatnot. It's very simple: you can always move forward, but never backward. What you link against sets a line in the sand, so if you want your binaries usable on old systems, you need to link it on such an old system.

I can accept that I break the rules by deploying my app an an older system. But it has worked for many years of Ubuntu upgrades which makes it annoying that it should stop working because of memcpy. Why make a backwards incompatible change in such an old function?

It's not a backwards incompatible change. Binaries linked against the old version of the library continue to work -- maintaining backwards compatibility is the whole reason that symbol versioning was invented in the first place. The glibc maintainers are actually going to great pains to make sure old binaries continue to function with newer versions of the library without needing to be rebuilt, and it would be far easier to not go to all that trouble. But the situation then would be far more grim, and there would be constant breakage and instability.

It only seemed to work in the past because you got lucky. You were lucky to not have used any functions that were newly added, or whose arguments or semantics needed to be changed. But that doesn't mean you have a right to expect any kind of consideration now -- unsupported is unsupported, whether or not it results in a broken program. "I've shoplifted from this store before several times without being caught, why are you detaining me now?" Making it easier to do what you're trying to do should not be a goal, in fact that would be a disaster. Making wrong things seem to work is not something you want to strive for.