Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Add a personality to report 2.6.x version numbers

I ran into a couple of programs which broke with the new Linux 3.0
version. Some of those were binary only. I tried to use LD_PRELOAD to
work around it, but it was quite difficult and in one case impossible
because of a mix of 32bit and 64bit executables.

For example, all kind of management software from HP doesnt work, unless
we pretend to run a 2.6 kernel.

$ uname -a
Linux svivoipvnx001 3.0.0-08107-g97cd98f #1062 SMP Fri Aug 12 18:11:45 CEST 2011 i686 i686 i386 GNU/Linux

$ hpacucli ctrl all show

Error: No controllers detected.

$ rpm -qf /usr/sbin/hpacucli
hpacucli-8.75-12.0

Another notable case is that Python now reports "linux3" from
sys.platform(); which in turn can break things that were checking
sys.platform() == "linux2":

https://bugzilla.mozilla.org/show_bug.cgi?id=664564

It seems pretty clear to me though it's a bug in the apps that are using
'==' instead of .startswith(), but this allows us to unbreak broken
programs.

This patch adds a UNAME26 personality that makes the kernel report a
2.6.40+x version number instead. The x is the x in 3.x.

I know this is somewhat ugly, but I didn't find a better workaround, and
compatibility to existing programs is important.

Some programs also read /proc/sys/kernel/osrelease. This can be worked
around in user space with mount --bind (and a mount namespace)

To use:

wget ftp://ftp.kernel.org/pub/linux/kernel/people/ak/uname26/uname26.c
gcc -o uname26 uname26.c
./uname26 program

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Andi Kleen and committed by
Linus Torvalds
be27425d caca9510

+39
+1
include/linux/personality.h
··· 22 22 * These occupy the top three bytes. 23 23 */ 24 24 enum { 25 + UNAME26 = 0x0020000, 25 26 ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */ 26 27 FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to descriptors 27 28 * (signal handling)
+38
kernel/sys.c
··· 37 37 #include <linux/fs_struct.h> 38 38 #include <linux/gfp.h> 39 39 #include <linux/syscore_ops.h> 40 + #include <linux/version.h> 41 + #include <linux/ctype.h> 40 42 41 43 #include <linux/compat.h> 42 44 #include <linux/syscalls.h> ··· 46 44 #include <linux/user_namespace.h> 47 45 48 46 #include <linux/kmsg_dump.h> 47 + /* Move somewhere else to avoid recompiling? */ 48 + #include <generated/utsrelease.h> 49 49 50 50 #include <asm/uaccess.h> 51 51 #include <asm/io.h> ··· 1165 1161 #define override_architecture(name) 0 1166 1162 #endif 1167 1163 1164 + /* 1165 + * Work around broken programs that cannot handle "Linux 3.0". 1166 + * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40 1167 + */ 1168 + static int override_release(char __user *release, int len) 1169 + { 1170 + int ret = 0; 1171 + char buf[len]; 1172 + 1173 + if (current->personality & UNAME26) { 1174 + char *rest = UTS_RELEASE; 1175 + int ndots = 0; 1176 + unsigned v; 1177 + 1178 + while (*rest) { 1179 + if (*rest == '.' && ++ndots >= 3) 1180 + break; 1181 + if (!isdigit(*rest) && *rest != '.') 1182 + break; 1183 + rest++; 1184 + } 1185 + v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40; 1186 + snprintf(buf, len, "2.6.%u%s", v, rest); 1187 + ret = copy_to_user(release, buf, len); 1188 + } 1189 + return ret; 1190 + } 1191 + 1168 1192 SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) 1169 1193 { 1170 1194 int errno = 0; ··· 1202 1170 errno = -EFAULT; 1203 1171 up_read(&uts_sem); 1204 1172 1173 + if (!errno && override_release(name->release, sizeof(name->release))) 1174 + errno = -EFAULT; 1205 1175 if (!errno && override_architecture(name)) 1206 1176 errno = -EFAULT; 1207 1177 return errno; ··· 1225 1191 error = -EFAULT; 1226 1192 up_read(&uts_sem); 1227 1193 1194 + if (!error && override_release(name->release, sizeof(name->release))) 1195 + error = -EFAULT; 1228 1196 if (!error && override_architecture(name)) 1229 1197 error = -EFAULT; 1230 1198 return error; ··· 1260 1224 up_read(&uts_sem); 1261 1225 1262 1226 if (!error && override_architecture(name)) 1227 + error = -EFAULT; 1228 + if (!error && override_release(name->release, sizeof(name->release))) 1263 1229 error = -EFAULT; 1264 1230 return error ? -EFAULT : 0; 1265 1231 }