path: root/arch/alpha/lib
diff options
authorMathieu Desnoyers <>2013-09-11 14:23:18 -0700
committerLinus Torvalds <>2013-09-11 15:58:18 -0700
commit3ddc5b46a8e90f3c9251338b60191d0a804b0d92 (patch)
tree5c76cd730cb94e75f30953d6cd1aed9386fcee37 /arch/alpha/lib
parent20d0e57017b69e7e4ae7166c43f3a3f023ab9702 (diff)
kernel-wide: fix missing validations on __get/__put/__copy_to/__copy_from_user()
I found the following pattern that leads in to interesting findings: grep -r "ret.*|=.*__put_user" * grep -r "ret.*|=.*__get_user" * grep -r "ret.*|=.*__copy" * The __put_user() calls in compat_ioctl.c, ptrace compat, signal compat, since those appear in compat code, we could probably expect the kernel addresses not to be reachable in the lower 32-bit range, so I think they might not be exploitable. For the "__get_user" cases, I don't think those are exploitable: the worse that can happen is that the kernel will copy kernel memory into in-kernel buffers, and will fail immediately afterward. The alpha csum_partial_copy_from_user() seems to be missing the access_ok() check entirely. The fix is inspired from x86. This could lead to information leak on alpha. I also noticed that many architectures map csum_partial_copy_from_user() to csum_partial_copy_generic(), but I wonder if the latter is performing the access checks on every architectures. Signed-off-by: Mathieu Desnoyers <> Cc: Richard Henderson <> Cc: Ivan Kokshaysky <> Cc: Matt Turner <> Cc: Jens Axboe <> Cc: Oleg Nesterov <> Cc: David Miller <> Signed-off-by: Andrew Morton <> Signed-off-by: Linus Torvalds <>
Diffstat (limited to 'arch/alpha/lib')
1 files changed, 5 insertions, 0 deletions
diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c
index 40736da9bea8..ffb19b7da999 100644
--- a/arch/alpha/lib/csum_partial_copy.c
+++ b/arch/alpha/lib/csum_partial_copy.c
@@ -338,6 +338,11 @@ csum_partial_copy_from_user(const void __user *src, void *dst, int len,
unsigned long doff = 7 & (unsigned long) dst;
if (len) {
+ if (!access_ok(VERIFY_READ, src, len)) {
+ *errp = -EFAULT;
+ memset(dst, 0, len);
+ return sum;
+ }
if (!doff) {
if (!soff)
checksum = csum_partial_cfu_aligned(