I recently had the sudden urge to try Red Hat 8 on real hardware (as one has, apparently), and this 1 GHz Athlon thin client with Windows 98 was the perfect candidate for this project.
Please note: It's not a very good idea to run outdated software on networked computers. This is purely an archaeological exercise, and the machine I'm using it on doesn't have any important data and is not networked.
The Story So Far
How I got a working kernel and booted it from Windows 98 using loadlin
and
used a Busybox-based initrd to then create and format an ext2
partition and
copy in a current Debian sid
chroot (created using debootstrap
and copied
as tarball via a USB disk to the Windows partition), then use the Debian chroot
userland and its ssh
and tar
(the rsync
versions of RedHat 8 and
current-day Debian sid were too far apart) is a story for another post.
Suffice to say, I now have Linux kernel 5.7.0-rc3 running on this machine, and the RedHat 8 installation copied into a directory I can chroot into.
Kernel
RedHat 8 shipped with the Linux kernel 2.4.18 in September 2002, the 5.7-rc3 kernel I tested here was released in April 2020. So far, the ABI of the Linux kernel seems super stable.
XFree86 on fbdev
Interestingly, by using the XFree86 (yes, 2002) fbdev
driver and the sisfb
driver in the kernel (vesafb
also worked, but the machine in question has an
onboard SiS graphics card, and maybe I'll try something with that in the
future) and starting the X font server xfs
inside the chroot
, it was
possible to start up a KDE session.
MP3 and GIF Patents
Most of the command-line and GUI programs worked fine, but some features
that we take for granted today were patched out: xmms
had
MP3 support patched out, because the
MP3 patents
in the US expired between 2007 and 2017. Note that just downloading the
xmms 1.2.7 and building/installing it restores MP3 playback functionality.
Also, with The GIMP you could not save GIF files, because the GIF patents hadn't expired yet in 2002. Did you know that PNG was more or less created because of the GIF patent situation?
Pet Tools
Building recent versions of Vim (8.2) and Python (3.8.2) with the old toolchain of RedHat 8 (it ships with glibc 2.2.93 and GCC 3.2, which obviously predates many language improvements; LLVM was only released in 2003 and clang in 2007) wasn't that difficult, I had to patch out some low level functions that just haven't been added to libc back then, but both actually compiled and started fine.
To put things into perspective, RH8 ships with Python 2.2.1 and Vim 6.1.
ps
But then I ran into a weird situation: ps
crashed. Just typing ps
made it
segfault. Of course, ps
needs to query stuff from the kernel, and this is
mostly done via text files in procfs
(the /proc
filesystem). Likely Linux
changed something there in the last 18 years.
Some more digging later, I identified the
procps package (RH8 ships with version 2.0.7)
as the source for the ps
binary and libproc.so.2.0.7
. Building the source
and running ps
under GDB (RH8 ships with version 5.2.1) shows that it fails
to parse some text file content. The first bug was in the meminfo()
function,
which parses /proc/meminfo
and returns a matrix of some values. How much
space do we need to store the field numbers?
char fieldbuf[12]; /* bigger than any field name or size in kb */
Yeah, sure. That worked probably just fine on 2002-era kernels, but these days,
there's fields such as ShmemHugePages
which is clearly longer than this. A
simple bump of the size to 64 (hello from 2020, this is surely bigger than any
field name or size in kb, right?) fixed this particular issue for me.
The rest of the bugs were non-crasher bugs, but they caused a super useful
"Internal error!" message to be printed (and of course, there's multiple
places in the source with the same message, because having a more specific
error message might be too helpful). Some printf debugging later it turns
out that reading /proc/*/status
these days contains text data longer than
512 bytes, so trying to parse the files fails somewhere when the internal
buffer is truncated and some fields left unread.
In the end, I'm sure there are other bugs, but at least for basic usage, this
patch fixes ps
on RedHat 8 on recent kernels. Of course, one could try to
just build a newer procps
version or replace some utilities with Busybox,
but this way it's more period-correct, and at least makes the ps
utility
provide period-correct
bug-for-bug compatibility
in case some tools or scripts depend on it.
The Patch
Download it here: procps-2.0.7-patched-kernel5.7.0-rc3.patch
diff -ru procps-2.0.7/proc/readproc.c procps-2.0.7-patched/proc/readproc.c
--- procps-2.0.7/proc/readproc.c 2000-07-10 21:55:39.000000000 +0200
+++ procps-2.0.7-patched/proc/readproc.c 2020-05-04 20:17:42.000000000 +0200
@@ -128,6 +128,13 @@
P->vm_lib = 0;
}
+ /* FIXME Kernel 5.7.0-rc3 has the fields separated in lines:
+ * SigPnd: 0000000000000000
+ * ShdPnd: 0000000000000000
+ * SigBlk: 0000000080000000
+ * SigIgn: 0000000000000000
+ * SigCgt: 0000000000000000
+ **/
tmp = strstr (S,"SigPnd:");
if(tmp) sscanf (tmp,
#ifdef SIGNAL_STRING
@@ -303,7 +310,7 @@
proc_t* readproc(PROCTAB* PT, proc_t* rbuf) {
static struct direct *ent; /* dirent handle */
static struct stat sb; /* stat buffer */
- static char path[32], sbuf[512]; /* bufs for stat,statm */
+ static char path[32], sbuf[4096]; /* bufs for stat,statm */
int allocated = 0, matched = 0; /* flags */
proc_t *p = NULL;
@@ -403,7 +410,7 @@
proc_t* ps_readproc(PROCTAB* PT, proc_t* rbuf) {
static struct direct *ent; /* dirent handle */
static struct stat sb; /* stat buffer */
- static char path[32], sbuf[512]; /* bufs for stat,statm */
+ static char path[32], sbuf[4096]; /* bufs for stat,statm */
int allocated = 0 /* , matched = 0 */ ; /* flags */
proc_t *p = NULL;
@@ -473,7 +480,7 @@
void look_up_our_self(proc_t *p) {
- static char path[32], sbuf[512]; /* bufs for stat,statm */
+ static char path[32], sbuf[4096]; /* bufs for stat,statm */
sprintf(path, "/proc/%d", getpid());
if (file2str(path, "stat", sbuf, sizeof sbuf) >= 0)
stat2proc(sbuf, p); /* parse /proc/#/stat */
diff -ru procps-2.0.7/proc/sysinfo.c procps-2.0.7-patched/proc/sysinfo.c
--- procps-2.0.7/proc/sysinfo.c 2000-07-10 21:36:13.000000000 +0200
+++ procps-2.0.7-patched/proc/sysinfo.c 2020-05-04 20:12:30.000000000 +0200
@@ -33,7 +33,7 @@
#define MEMINFO_FILE "/proc/meminfo"
static int meminfo_fd = -1;
-static char buf[1024];
+static char buf[1024*64];
/* This macro opens filename only if necessary and seeks to 0 so
* that successive calls to the functions are more efficient.
@@ -202,7 +202,7 @@
static unsigned long long *row[MAX_ROW + 1]; /* row pointers */
static unsigned long long num[MAX_ROW * MAX_COL]; /* number storage */
char *p;
- char fieldbuf[12]; /* bigger than any field name or size in kb */
+ char fieldbuf[64]; /* bigger than any field name or size in kb */
int i, j, k, l;
FILE_TO_BUF(MEMINFO_FILE,meminfo_fd);
@@ -226,7 +226,7 @@
}
else {
while(*p) {
- sscanf(p,"%11s%n",fieldbuf,&k);
+ sscanf(p,"%63s%n",fieldbuf,&k);
if(!strcmp(fieldbuf,"MemTotal:")) {
p+=k;
sscanf(p," %Ld",&(row[meminfo_main][meminfo_total]));