do_sigaltstack: avoid copying 'stack_t' as a structure to user space

Ulrich Drepper correctly points out that there is generally padding in
the structure on 64-bit hosts, and that copying the structure from
kernel to user space can leak information from the kernel stack in those
padding bytes.

Avoid the whole issue by just copying the three members one by one
instead, which also means that the function also can avoid the need for
a stack frame. This also happens to match how we copy the new structure
from user space, so it all even makes sense.

[ The obvious solution of adding a memset() generates horrid code, gcc
does really stupid things. ]

Reported-by: Ulrich Drepper <drepper@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+8 -7
+8 -7
kernel/signal.c
··· 2454 2454 stack_t oss; 2455 2455 int error; 2456 2456 2457 - if (uoss) { 2458 - oss.ss_sp = (void __user *) current->sas_ss_sp; 2459 - oss.ss_size = current->sas_ss_size; 2460 - oss.ss_flags = sas_ss_flags(sp); 2461 - } 2457 + oss.ss_sp = (void __user *) current->sas_ss_sp; 2458 + oss.ss_size = current->sas_ss_size; 2459 + oss.ss_flags = sas_ss_flags(sp); 2462 2460 2463 2461 if (uss) { 2464 2462 void __user *ss_sp; ··· 2499 2501 current->sas_ss_size = ss_size; 2500 2502 } 2501 2503 2504 + error = 0; 2502 2505 if (uoss) { 2503 2506 error = -EFAULT; 2504 - if (copy_to_user(uoss, &oss, sizeof(oss))) 2507 + if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))) 2505 2508 goto out; 2509 + error = __put_user(oss.ss_sp, &uoss->ss_sp) | 2510 + __put_user(oss.ss_size, &uoss->ss_size) | 2511 + __put_user(oss.ss_flags, &uoss->ss_flags); 2506 2512 } 2507 2513 2508 - error = 0; 2509 2514 out: 2510 2515 return error; 2511 2516 }