Skip to content

Commit be27425

Browse files
Andi Kleentorvalds
authored andcommitted
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>
1 parent caca951 commit be27425

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

include/linux/personality.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ extern int __set_personality(unsigned int);
2222
* These occupy the top three bytes.
2323
*/
2424
enum {
25+
UNAME26 = 0x0020000,
2526
ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */
2627
FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to descriptors
2728
* (signal handling)

kernel/sys.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,17 @@
3737
#include <linux/fs_struct.h>
3838
#include <linux/gfp.h>
3939
#include <linux/syscore_ops.h>
40+
#include <linux/version.h>
41+
#include <linux/ctype.h>
4042

4143
#include <linux/compat.h>
4244
#include <linux/syscalls.h>
4345
#include <linux/kprobes.h>
4446
#include <linux/user_namespace.h>
4547

4648
#include <linux/kmsg_dump.h>
49+
/* Move somewhere else to avoid recompiling? */
50+
#include <generated/utsrelease.h>
4751

4852
#include <asm/uaccess.h>
4953
#include <asm/io.h>
@@ -1161,6 +1165,34 @@ DECLARE_RWSEM(uts_sem);
11611165
#define override_architecture(name) 0
11621166
#endif
11631167

1168+
/*
1169+
* Work around broken programs that cannot handle "Linux 3.0".
1170+
* Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40
1171+
*/
1172+
static int override_release(char __user *release, int len)
1173+
{
1174+
int ret = 0;
1175+
char buf[len];
1176+
1177+
if (current->personality & UNAME26) {
1178+
char *rest = UTS_RELEASE;
1179+
int ndots = 0;
1180+
unsigned v;
1181+
1182+
while (*rest) {
1183+
if (*rest == '.' && ++ndots >= 3)
1184+
break;
1185+
if (!isdigit(*rest) && *rest != '.')
1186+
break;
1187+
rest++;
1188+
}
1189+
v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40;
1190+
snprintf(buf, len, "2.6.%u%s", v, rest);
1191+
ret = copy_to_user(release, buf, len);
1192+
}
1193+
return ret;
1194+
}
1195+
11641196
SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
11651197
{
11661198
int errno = 0;
@@ -1170,6 +1202,8 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
11701202
errno = -EFAULT;
11711203
up_read(&uts_sem);
11721204

1205+
if (!errno && override_release(name->release, sizeof(name->release)))
1206+
errno = -EFAULT;
11731207
if (!errno && override_architecture(name))
11741208
errno = -EFAULT;
11751209
return errno;
@@ -1191,6 +1225,8 @@ SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
11911225
error = -EFAULT;
11921226
up_read(&uts_sem);
11931227

1228+
if (!error && override_release(name->release, sizeof(name->release)))
1229+
error = -EFAULT;
11941230
if (!error && override_architecture(name))
11951231
error = -EFAULT;
11961232
return error;
@@ -1225,6 +1261,8 @@ SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
12251261

12261262
if (!error && override_architecture(name))
12271263
error = -EFAULT;
1264+
if (!error && override_release(name->release, sizeof(name->release)))
1265+
error = -EFAULT;
12281266
return error ? -EFAULT : 0;
12291267
}
12301268
#endif

0 commit comments

Comments
 (0)