When in doubt, twiddle bytes in libc.so.5
Back in the fall of 2000, there was a nasty little security advisory in the klogd/syslogd pair which ran on every one of my machines. It seemed that data supplied by a user could work its way directly into the second argument of a *printf call and thus take over its format string. From there, any number of bad things could happen.
Within a day or two, there was a patched Slackware package:
---------------------------- Mon Sep 18 11:13:56 PDT 2000 a1/sysklogd.tgz: Upgraded to sysklogd-1.4. This fixes the "klogd format bug" announced this morning on BugTraq. (* Security fix *) ----------------------------
This patch was great, but it opened up a new problem for me. Slackware itself had recently switched to being based around glibc 2.1, and I still had a number of systems which were entirely or partially based on the older libc5 versions. I was able to install the glibc packages and then upgraded sysklogd, but then other things broke on me.
Somewhere along the way, /dev/log had changed from a SOCK_STREAM style to SOCK_DGRAM. This was probably done to avoid a denial of service attack. That was also a good thing, but it meant that all of my older programs which were still linked against libc5 had a syslog() call which no longer functioned. This was unacceptable.
I figured it would be possible to write something which would create a stream listening socket and would then translate things to datagrams and sling them at syslogd. It didn't take too much work, and now I had something which would do the conversion. It was the usual thing: set up a listener, run select(), keep track of client connections and disconnections, read() on activity, and write it to upstream.
Still, there was a big problem: the old programs still opened /dev/log, and the new programs did it too! I couldn't have it both ways on the same socket. Ultimately, I wound up doing something really evil to fix this problem. I opened up libc.so.5 and changed /dev/log to /dev/LOG with a quick call to sed. Then I made my program listen on /dev/LOG and write to /dev/log, and restarted everything which needed to use this interface.
It worked. Granted, it just moved the denial-of-service possibility to my converter, but that was an acceptable situation during the transition. Later, once everything had been upgraded and/or recompiled around glibc, I shut it down and removed the lingering cruft.
This was just one of a bunch of crazy things I had to write over the years to keep my fleet of mismatched machines running properly.