| 1 |
From: Linus Torvalds <torvalds@linux-foundation.org>
|
| 2 |
Date: Sat, 1 Aug 2009 17:34:56 +0000 (-0700)
|
| 3 |
Subject: do_sigaltstack: avoid copying 'stack_t' as a structure to user space
|
| 4 |
X-Git-Tag: v2.6.31-rc6~89
|
| 5 |
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=0083fc2c50e6c5127c2802ad323adf8143ab7856
|
| 6 |
|
| 7 |
do_sigaltstack: avoid copying 'stack_t' as a structure to user space
|
| 8 |
|
| 9 |
Ulrich Drepper correctly points out that there is generally padding in
|
| 10 |
the structure on 64-bit hosts, and that copying the structure from
|
| 11 |
kernel to user space can leak information from the kernel stack in those
|
| 12 |
padding bytes.
|
| 13 |
|
| 14 |
Avoid the whole issue by just copying the three members one by one
|
| 15 |
instead, which also means that the function also can avoid the need for
|
| 16 |
a stack frame. This also happens to match how we copy the new structure
|
| 17 |
from user space, so it all even makes sense.
|
| 18 |
|
| 19 |
[ The obvious solution of adding a memset() generates horrid code, gcc
|
| 20 |
does really stupid things. ]
|
| 21 |
|
| 22 |
Reported-by: Ulrich Drepper <drepper@redhat.com>
|
| 23 |
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
| 24 |
---
|
| 25 |
|
| 26 |
diff --git a/kernel/signal.c b/kernel/signal.c
|
| 27 |
index ccf1cee..f268372 100644
|
| 28 |
--- a/kernel/signal.c
|
| 29 |
+++ b/kernel/signal.c
|
| 30 |
@@ -2454,11 +2454,9 @@ do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long s
|
| 31 |
stack_t oss;
|
| 32 |
int error;
|
| 33 |
|
| 34 |
- if (uoss) {
|
| 35 |
- oss.ss_sp = (void __user *) current->sas_ss_sp;
|
| 36 |
- oss.ss_size = current->sas_ss_size;
|
| 37 |
- oss.ss_flags = sas_ss_flags(sp);
|
| 38 |
- }
|
| 39 |
+ oss.ss_sp = (void __user *) current->sas_ss_sp;
|
| 40 |
+ oss.ss_size = current->sas_ss_size;
|
| 41 |
+ oss.ss_flags = sas_ss_flags(sp);
|
| 42 |
|
| 43 |
if (uss) {
|
| 44 |
void __user *ss_sp;
|
| 45 |
@@ -2501,13 +2499,16 @@ do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long s
|
| 46 |
current->sas_ss_size = ss_size;
|
| 47 |
}
|
| 48 |
|
| 49 |
+ error = 0;
|
| 50 |
if (uoss) {
|
| 51 |
error = -EFAULT;
|
| 52 |
- if (copy_to_user(uoss, &oss, sizeof(oss)))
|
| 53 |
+ if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
|
| 54 |
goto out;
|
| 55 |
+ error = __put_user(oss.ss_sp, &uoss->ss_sp) |
|
| 56 |
+ __put_user(oss.ss_size, &uoss->ss_size) |
|
| 57 |
+ __put_user(oss.ss_flags, &uoss->ss_flags);
|
| 58 |
}
|
| 59 |
|
| 60 |
- error = 0;
|
| 61 |
out:
|
| 62 |
return error;
|
| 63 |
}
|