diff options
author | Dan Rosenberg <drosenberg@vsecurity.com> | 2011-06-15 18:09:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-15 23:04:02 -0400 |
commit | 21c5977a836e399fc710ff2c5367845ed5c2527f (patch) | |
tree | 7258368ce3cfb107ed83d05ac4f7f8b547d47e23 /arch/alpha/kernel | |
parent | ec8f9ceacef719a844ca269d654502af6a00a273 (diff) |
alpha: fix several security issues
Fix several security issues in Alpha-specific syscalls. Untested, but
mostly trivial.
1. Signedness issue in osf_getdomainname allows copying out-of-bounds
kernel memory to userland.
2. Signedness issue in osf_sysinfo allows copying large amounts of
kernel memory to userland.
3. Typo (?) in osf_getsysinfo bounds minimum instead of maximum copy
size, allowing copying large amounts of kernel memory to userland.
4. Usage of user pointer in osf_wait4 while under KERNEL_DS allows
privilege escalation via writing return value of sys_wait4 to kernel
memory.
Signed-off-by: Dan Rosenberg <drosenberg@vsecurity.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/alpha/kernel')
-rw-r--r-- | arch/alpha/kernel/osf_sys.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 376f22130791..326f0a2d56e5 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c | |||
@@ -409,7 +409,7 @@ SYSCALL_DEFINE2(osf_getdomainname, char __user *, name, int, namelen) | |||
409 | return -EFAULT; | 409 | return -EFAULT; |
410 | 410 | ||
411 | len = namelen; | 411 | len = namelen; |
412 | if (namelen > 32) | 412 | if (len > 32) |
413 | len = 32; | 413 | len = 32; |
414 | 414 | ||
415 | down_read(&uts_sem); | 415 | down_read(&uts_sem); |
@@ -594,7 +594,7 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count) | |||
594 | down_read(&uts_sem); | 594 | down_read(&uts_sem); |
595 | res = sysinfo_table[offset]; | 595 | res = sysinfo_table[offset]; |
596 | len = strlen(res)+1; | 596 | len = strlen(res)+1; |
597 | if (len > count) | 597 | if ((unsigned long)len > (unsigned long)count) |
598 | len = count; | 598 | len = count; |
599 | if (copy_to_user(buf, res, len)) | 599 | if (copy_to_user(buf, res, len)) |
600 | err = -EFAULT; | 600 | err = -EFAULT; |
@@ -649,7 +649,7 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer, | |||
649 | return 1; | 649 | return 1; |
650 | 650 | ||
651 | case GSI_GET_HWRPB: | 651 | case GSI_GET_HWRPB: |
652 | if (nbytes < sizeof(*hwrpb)) | 652 | if (nbytes > sizeof(*hwrpb)) |
653 | return -EINVAL; | 653 | return -EINVAL; |
654 | if (copy_to_user(buffer, hwrpb, nbytes) != 0) | 654 | if (copy_to_user(buffer, hwrpb, nbytes) != 0) |
655 | return -EFAULT; | 655 | return -EFAULT; |
@@ -1008,6 +1008,7 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options, | |||
1008 | { | 1008 | { |
1009 | struct rusage r; | 1009 | struct rusage r; |
1010 | long ret, err; | 1010 | long ret, err; |
1011 | unsigned int status = 0; | ||
1011 | mm_segment_t old_fs; | 1012 | mm_segment_t old_fs; |
1012 | 1013 | ||
1013 | if (!ur) | 1014 | if (!ur) |
@@ -1016,13 +1017,15 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options, | |||
1016 | old_fs = get_fs(); | 1017 | old_fs = get_fs(); |
1017 | 1018 | ||
1018 | set_fs (KERNEL_DS); | 1019 | set_fs (KERNEL_DS); |
1019 | ret = sys_wait4(pid, ustatus, options, (struct rusage __user *) &r); | 1020 | ret = sys_wait4(pid, (unsigned int __user *) &status, options, |
1021 | (struct rusage __user *) &r); | ||
1020 | set_fs (old_fs); | 1022 | set_fs (old_fs); |
1021 | 1023 | ||
1022 | if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur))) | 1024 | if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur))) |
1023 | return -EFAULT; | 1025 | return -EFAULT; |
1024 | 1026 | ||
1025 | err = 0; | 1027 | err = 0; |
1028 | err |= put_user(status, ustatus); | ||
1026 | err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec); | 1029 | err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec); |
1027 | err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec); | 1030 | err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec); |
1028 | err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec); | 1031 | err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec); |