1#include <linux/compat.h> 2#include <linux/uaccess.h> 3 4int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) 5{ 6 int err = 0; 7 bool ia32 = test_thread_flag(TIF_IA32); 8 9 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) 10 return -EFAULT; 11 12 put_user_try { 13 /* If you change siginfo_t structure, please make sure that 14 this code is fixed accordingly. 15 It should never copy any pad contained in the structure 16 to avoid security leaks, but must copy the generic 17 3 ints plus the relevant union member. */ 18 put_user_ex(from->si_signo, &to->si_signo); 19 put_user_ex(from->si_errno, &to->si_errno); 20 put_user_ex((short)from->si_code, &to->si_code); 21 22 if (from->si_code < 0) { 23 put_user_ex(from->si_pid, &to->si_pid); 24 put_user_ex(from->si_uid, &to->si_uid); 25 put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr); 26 } else { 27 /* 28 * First 32bits of unions are always present: 29 * si_pid === si_band === si_tid === si_addr(LS half) 30 */ 31 put_user_ex(from->_sifields._pad[0], 32 &to->_sifields._pad[0]); 33 switch (from->si_code >> 16) { 34 case __SI_FAULT >> 16: 35 break; 36 case __SI_SYS >> 16: 37 put_user_ex(from->si_syscall, &to->si_syscall); 38 put_user_ex(from->si_arch, &to->si_arch); 39 break; 40 case __SI_CHLD >> 16: 41 if (ia32) { 42 put_user_ex(from->si_utime, &to->si_utime); 43 put_user_ex(from->si_stime, &to->si_stime); 44 } else { 45 put_user_ex(from->si_utime, &to->_sifields._sigchld_x32._utime); 46 put_user_ex(from->si_stime, &to->_sifields._sigchld_x32._stime); 47 } 48 put_user_ex(from->si_status, &to->si_status); 49 /* FALL THROUGH */ 50 default: 51 case __SI_KILL >> 16: 52 put_user_ex(from->si_uid, &to->si_uid); 53 break; 54 case __SI_POLL >> 16: 55 put_user_ex(from->si_fd, &to->si_fd); 56 break; 57 case __SI_TIMER >> 16: 58 put_user_ex(from->si_overrun, &to->si_overrun); 59 put_user_ex(ptr_to_compat(from->si_ptr), 60 &to->si_ptr); 61 break; 62 /* This is not generated by the kernel as of now. */ 63 case __SI_RT >> 16: 64 case __SI_MESGQ >> 16: 65 put_user_ex(from->si_uid, &to->si_uid); 66 put_user_ex(from->si_int, &to->si_int); 67 break; 68 } 69 } 70 } put_user_catch(err); 71 72 return err; 73} 74 75int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) 76{ 77 int err = 0; 78 u32 ptr32; 79 80 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t))) 81 return -EFAULT; 82 83 get_user_try { 84 get_user_ex(to->si_signo, &from->si_signo); 85 get_user_ex(to->si_errno, &from->si_errno); 86 get_user_ex(to->si_code, &from->si_code); 87 88 get_user_ex(to->si_pid, &from->si_pid); 89 get_user_ex(to->si_uid, &from->si_uid); 90 get_user_ex(ptr32, &from->si_ptr); 91 to->si_ptr = compat_ptr(ptr32); 92 } get_user_catch(err); 93 94 return err; 95} 96