• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/compat.h>
3 #include <linux/uaccess.h>
4 #include <linux/ptrace.h>
5 
6 /*
7  * The compat_siginfo_t structure and handing code is very easy
8  * to break in several ways.  It must always be updated when new
9  * updates are made to the main siginfo_t, and
10  * copy_siginfo_to_user32() must be updated when the
11  * (arch-independent) copy_siginfo_to_user() is updated.
12  *
13  * It is also easy to put a new member in the compat_siginfo_t
14  * which has implicit alignment which can move internal structure
15  * alignment around breaking the ABI.  This can happen if you,
16  * for instance, put a plain 64-bit value in there.
17  */
signal_compat_build_tests(void)18 static inline void signal_compat_build_tests(void)
19 {
20 	int _sifields_offset = offsetof(compat_siginfo_t, _sifields);
21 
22 	/*
23 	 * If adding a new si_code, there is probably new data in
24 	 * the siginfo.  Make sure folks bumping the si_code
25 	 * limits also have to look at this code.  Make sure any
26 	 * new fields are handled in copy_siginfo_to_user32()!
27 	 */
28 	BUILD_BUG_ON(NSIGILL  != 8);
29 	BUILD_BUG_ON(NSIGFPE  != 8);
30 	BUILD_BUG_ON(NSIGSEGV != 4);
31 	BUILD_BUG_ON(NSIGBUS  != 5);
32 	BUILD_BUG_ON(NSIGTRAP != 4);
33 	BUILD_BUG_ON(NSIGCHLD != 6);
34 	BUILD_BUG_ON(NSIGSYS  != 1);
35 
36 	/* This is part of the ABI and can never change in size: */
37 	BUILD_BUG_ON(sizeof(compat_siginfo_t) != 128);
38 	/*
39 	 * The offsets of all the (unioned) si_fields are fixed
40 	 * in the ABI, of course.  Make sure none of them ever
41 	 * move and are always at the beginning:
42 	 */
43 	BUILD_BUG_ON(offsetof(compat_siginfo_t, _sifields) != 3 * sizeof(int));
44 #define CHECK_CSI_OFFSET(name)	  BUILD_BUG_ON(_sifields_offset != offsetof(compat_siginfo_t, _sifields.name))
45 
46 	 /*
47 	 * Ensure that the size of each si_field never changes.
48 	 * If it does, it is a sign that the
49 	 * copy_siginfo_to_user32() code below needs to updated
50 	 * along with the size in the CHECK_SI_SIZE().
51 	 *
52 	 * We repeat this check for both the generic and compat
53 	 * siginfos.
54 	 *
55 	 * Note: it is OK for these to grow as long as the whole
56 	 * structure stays within the padding size (checked
57 	 * above).
58 	 */
59 #define CHECK_CSI_SIZE(name, size) BUILD_BUG_ON(size != sizeof(((compat_siginfo_t *)0)->_sifields.name))
60 #define CHECK_SI_SIZE(name, size) BUILD_BUG_ON(size != sizeof(((siginfo_t *)0)->_sifields.name))
61 
62 	CHECK_CSI_OFFSET(_kill);
63 	CHECK_CSI_SIZE  (_kill, 2*sizeof(int));
64 	CHECK_SI_SIZE   (_kill, 2*sizeof(int));
65 
66 	CHECK_CSI_OFFSET(_timer);
67 	CHECK_CSI_SIZE  (_timer, 5*sizeof(int));
68 	CHECK_SI_SIZE   (_timer, 6*sizeof(int));
69 
70 	CHECK_CSI_OFFSET(_rt);
71 	CHECK_CSI_SIZE  (_rt, 3*sizeof(int));
72 	CHECK_SI_SIZE   (_rt, 4*sizeof(int));
73 
74 	CHECK_CSI_OFFSET(_sigchld);
75 	CHECK_CSI_SIZE  (_sigchld, 5*sizeof(int));
76 	CHECK_SI_SIZE   (_sigchld, 8*sizeof(int));
77 
78 	CHECK_CSI_OFFSET(_sigchld_x32);
79 	CHECK_CSI_SIZE  (_sigchld_x32, 7*sizeof(int));
80 	/* no _sigchld_x32 in the generic siginfo_t */
81 
82 	CHECK_CSI_OFFSET(_sigfault);
83 	CHECK_CSI_SIZE  (_sigfault, 4*sizeof(int));
84 	CHECK_SI_SIZE   (_sigfault, 8*sizeof(int));
85 
86 	CHECK_CSI_OFFSET(_sigpoll);
87 	CHECK_CSI_SIZE  (_sigpoll, 2*sizeof(int));
88 	CHECK_SI_SIZE   (_sigpoll, 4*sizeof(int));
89 
90 	CHECK_CSI_OFFSET(_sigsys);
91 	CHECK_CSI_SIZE  (_sigsys, 3*sizeof(int));
92 	CHECK_SI_SIZE   (_sigsys, 4*sizeof(int));
93 
94 	/* any new si_fields should be added here */
95 }
96 
sigaction_compat_abi(struct k_sigaction * act,struct k_sigaction * oact)97 void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact)
98 {
99 	/* Don't leak in-kernel non-uapi flags to user-space */
100 	if (oact)
101 		oact->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
102 
103 	if (!act)
104 		return;
105 
106 	/* Don't let flags to be set from userspace */
107 	act->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
108 
109 	if (in_ia32_syscall())
110 		act->sa.sa_flags |= SA_IA32_ABI;
111 	if (in_x32_syscall())
112 		act->sa.sa_flags |= SA_X32_ABI;
113 }
114 
__copy_siginfo_to_user32(compat_siginfo_t __user * to,const siginfo_t * from,bool x32_ABI)115 int __copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from,
116 		bool x32_ABI)
117 {
118 	int err = 0;
119 
120 	signal_compat_build_tests();
121 
122 	if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
123 		return -EFAULT;
124 
125 	put_user_try {
126 		/* If you change siginfo_t structure, please make sure that
127 		   this code is fixed accordingly.
128 		   It should never copy any pad contained in the structure
129 		   to avoid security leaks, but must copy the generic
130 		   3 ints plus the relevant union member.  */
131 		put_user_ex(from->si_signo, &to->si_signo);
132 		put_user_ex(from->si_errno, &to->si_errno);
133 		put_user_ex(from->si_code, &to->si_code);
134 
135 		if (from->si_code < 0) {
136 			put_user_ex(from->si_pid, &to->si_pid);
137 			put_user_ex(from->si_uid, &to->si_uid);
138 			put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
139 		} else {
140 			/*
141 			 * First 32bits of unions are always present:
142 			 * si_pid === si_band === si_tid === si_addr(LS half)
143 			 */
144 			put_user_ex(from->_sifields._pad[0],
145 					  &to->_sifields._pad[0]);
146 			switch (siginfo_layout(from->si_signo, from->si_code)) {
147 			case SIL_FAULT:
148 				if (from->si_signo == SIGBUS &&
149 				    (from->si_code == BUS_MCEERR_AR ||
150 				     from->si_code == BUS_MCEERR_AO))
151 					put_user_ex(from->si_addr_lsb, &to->si_addr_lsb);
152 
153 				if (from->si_signo == SIGSEGV) {
154 					if (from->si_code == SEGV_BNDERR) {
155 						compat_uptr_t lower = (unsigned long)from->si_lower;
156 						compat_uptr_t upper = (unsigned long)from->si_upper;
157 						put_user_ex(lower, &to->si_lower);
158 						put_user_ex(upper, &to->si_upper);
159 					}
160 					if (from->si_code == SEGV_PKUERR)
161 						put_user_ex(from->si_pkey, &to->si_pkey);
162 				}
163 				break;
164 			case SIL_SYS:
165 				put_user_ex(from->si_syscall, &to->si_syscall);
166 				put_user_ex(from->si_arch, &to->si_arch);
167 				break;
168 			case SIL_CHLD:
169 				if (!x32_ABI) {
170 					put_user_ex(from->si_utime, &to->si_utime);
171 					put_user_ex(from->si_stime, &to->si_stime);
172 				} else {
173 					put_user_ex(from->si_utime, &to->_sifields._sigchld_x32._utime);
174 					put_user_ex(from->si_stime, &to->_sifields._sigchld_x32._stime);
175 				}
176 				put_user_ex(from->si_status, &to->si_status);
177 				/* FALL THROUGH */
178 			case SIL_KILL:
179 				put_user_ex(from->si_uid, &to->si_uid);
180 				break;
181 			case SIL_POLL:
182 				put_user_ex(from->si_fd, &to->si_fd);
183 				break;
184 			case SIL_TIMER:
185 				put_user_ex(from->si_overrun, &to->si_overrun);
186 				put_user_ex(ptr_to_compat(from->si_ptr),
187 					    &to->si_ptr);
188 				break;
189 			case SIL_RT:
190 				put_user_ex(from->si_uid, &to->si_uid);
191 				put_user_ex(from->si_int, &to->si_int);
192 				break;
193 			}
194 		}
195 	} put_user_catch(err);
196 
197 	return err;
198 }
199 
200 /* from syscall's path, where we know the ABI */
copy_siginfo_to_user32(compat_siginfo_t __user * to,const siginfo_t * from)201 int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
202 {
203 	return __copy_siginfo_to_user32(to, from, in_x32_syscall());
204 }
205 
copy_siginfo_from_user32(siginfo_t * to,compat_siginfo_t __user * from)206 int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
207 {
208 	int err = 0;
209 	u32 ptr32;
210 
211 	if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
212 		return -EFAULT;
213 
214 	get_user_try {
215 		get_user_ex(to->si_signo, &from->si_signo);
216 		get_user_ex(to->si_errno, &from->si_errno);
217 		get_user_ex(to->si_code, &from->si_code);
218 
219 		get_user_ex(to->si_pid, &from->si_pid);
220 		get_user_ex(to->si_uid, &from->si_uid);
221 		get_user_ex(ptr32, &from->si_ptr);
222 		to->si_ptr = compat_ptr(ptr32);
223 	} get_user_catch(err);
224 
225 	return err;
226 }
227