aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index dd948a1fca4c..18ee1d2f6474 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -37,6 +37,8 @@
37#include <linux/fs_struct.h> 37#include <linux/fs_struct.h>
38#include <linux/gfp.h> 38#include <linux/gfp.h>
39#include <linux/syscore_ops.h> 39#include <linux/syscore_ops.h>
40#include <linux/version.h>
41#include <linux/ctype.h>
40 42
41#include <linux/compat.h> 43#include <linux/compat.h>
42#include <linux/syscalls.h> 44#include <linux/syscalls.h>
@@ -44,6 +46,8 @@
44#include <linux/user_namespace.h> 46#include <linux/user_namespace.h>
45 47
46#include <linux/kmsg_dump.h> 48#include <linux/kmsg_dump.h>
49/* Move somewhere else to avoid recompiling? */
50#include <generated/utsrelease.h>
47 51
48#include <asm/uaccess.h> 52#include <asm/uaccess.h>
49#include <asm/io.h> 53#include <asm/io.h>
@@ -1161,6 +1165,34 @@ DECLARE_RWSEM(uts_sem);
1161#define override_architecture(name) 0 1165#define override_architecture(name) 0
1162#endif 1166#endif
1163 1167
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 */
1172static 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
1164SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) 1196SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
1165{ 1197{
1166 int errno = 0; 1198 int errno = 0;
@@ -1170,6 +1202,8 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
1170 errno = -EFAULT; 1202 errno = -EFAULT;
1171 up_read(&uts_sem); 1203 up_read(&uts_sem);
1172 1204
1205 if (!errno && override_release(name->release, sizeof(name->release)))
1206 errno = -EFAULT;
1173 if (!errno && override_architecture(name)) 1207 if (!errno && override_architecture(name))
1174 errno = -EFAULT; 1208 errno = -EFAULT;
1175 return errno; 1209 return errno;
@@ -1191,6 +1225,8 @@ SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
1191 error = -EFAULT; 1225 error = -EFAULT;
1192 up_read(&uts_sem); 1226 up_read(&uts_sem);
1193 1227
1228 if (!error && override_release(name->release, sizeof(name->release)))
1229 error = -EFAULT;
1194 if (!error && override_architecture(name)) 1230 if (!error && override_architecture(name))
1195 error = -EFAULT; 1231 error = -EFAULT;
1196 return error; 1232 return error;
@@ -1225,6 +1261,8 @@ SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
1225 1261
1226 if (!error && override_architecture(name)) 1262 if (!error && override_architecture(name))
1227 error = -EFAULT; 1263 error = -EFAULT;
1264 if (!error && override_release(name->release, sizeof(name->release)))
1265 error = -EFAULT;
1228 return error ? -EFAULT : 0; 1266 return error ? -EFAULT : 0;
1229} 1267}
1230#endif 1268#endif