Commit 3b35cbe5 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Fix 32bit siginfo problems on x86-64

From: Andi Kleen <ak@muc.de>

32bit siginfo would sometimes get passed incorrectly on x86-64. This
change fixes the conversion function to be a bit dumber, but more
correct.
parent 53b3aa6c
...@@ -46,25 +46,25 @@ void signal_fault(struct pt_regs *regs, void *frame, char *where); ...@@ -46,25 +46,25 @@ void signal_fault(struct pt_regs *regs, void *frame, char *where);
static int ia32_copy_siginfo_to_user(siginfo_t32 *to, siginfo_t *from) static int ia32_copy_siginfo_to_user(siginfo_t32 *to, siginfo_t *from)
{ {
int err;
if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t))) if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
return -EFAULT; return -EFAULT;
if (from->si_code < 0) {
/* the only field that's different is the alignment
of the pointer in sigval_t. Move that 4 bytes down including
padding. */
memmove(&((siginfo_t32 *)&from)->si_int,
&from->si_int,
sizeof(siginfo_t) - offsetof(siginfo_t, si_int));
/* last 4 bytes stay the same */
return __copy_to_user(to, from, sizeof(siginfo_t32));
} else {
int err;
/* If you change siginfo_t structure, please be sure /* If you change siginfo_t structure, please make sure that
this code is fixed accordingly. this code is fixed accordingly.
It should never copy any pad contained in the structure It should never copy any pad contained in the structure
to avoid security leaks, but must copy the generic to avoid security leaks, but must copy the generic
3 ints plus the relevant union member. */ 3 ints plus the relevant union member. */
if (from->si_code < 0) {
err = __put_user(from->si_signo, &to->si_signo);
err |= __put_user(from->si_errno, &to->si_errno);
err |= __put_user(from->si_code, &to->si_code);
err |= __put_user(from->_sifields._rt._pid, &to->_sifields._rt._pid);
err |= __put_user(from->_sifields._rt._uid, &to->_sifields._rt._uid);
err |= __put_user((u32)(u64)from->_sifields._rt._sigval.sival_ptr,
&to->_sifields._rt._sigval.sival_ptr);
} else {
err = __put_user(from->si_signo, &to->si_signo); err = __put_user(from->si_signo, &to->si_signo);
err |= __put_user(from->si_errno, &to->si_errno); err |= __put_user(from->si_errno, &to->si_errno);
err |= __put_user(from->si_code, &to->si_code); err |= __put_user(from->si_code, &to->si_code);
...@@ -86,8 +86,8 @@ static int ia32_copy_siginfo_to_user(siginfo_t32 *to, siginfo_t *from) ...@@ -86,8 +86,8 @@ static int ia32_copy_siginfo_to_user(siginfo_t32 *to, siginfo_t *from)
break; break;
/* case __SI_RT: This is not generated by the kernel as of now. */ /* case __SI_RT: This is not generated by the kernel as of now. */
} }
return err;
} }
return err;
} }
asmlinkage long asmlinkage long
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment