32bit siginfo would sometimes get passed incorrectly on x86-64. This change fixes the conversion function to be a bit dumber, but more correct. arch/x86_64/ia32/ia32_signal.c | 26 +++++++++++++------------- 1 files changed, 13 insertions(+), 13 deletions(-) diff -puN arch/x86_64/ia32/ia32_signal.c~x86_64-09 arch/x86_64/ia32/ia32_signal.c --- 25/arch/x86_64/ia32/ia32_signal.c~x86_64-09 2003-12-23 23:57:20.000000000 -0800 +++ 25-akpm/arch/x86_64/ia32/ia32_signal.c 2003-12-23 23:57:20.000000000 -0800 @@ -46,25 +46,25 @@ void signal_fault(struct pt_regs *regs, static int ia32_copy_siginfo_to_user(siginfo_t32 *to, siginfo_t *from) { + int err; if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t))) 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. It should never copy any pad contained in the structure to avoid security leaks, but must copy the generic 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_errno, &to->si_errno); err |= __put_user(from->si_code, &to->si_code); @@ -86,8 +86,8 @@ static int ia32_copy_siginfo_to_user(sig break; /* case __SI_RT: This is not generated by the kernel as of now. */ } - return err; } + return err; } asmlinkage long _