• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <linux/compat.h>
2 #include <linux/uaccess.h>
3 
copy_siginfo_to_user32(compat_siginfo_t __user * to,const siginfo_t * from)4 int 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 
copy_siginfo_from_user32(siginfo_t * to,compat_siginfo_t __user * from)75 int 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