1 /* mostly borrowed from kernel/signal.c */
2 #include <linux/config.h>
3 #include <linux/slab.h>
4 #include <linux/module.h>
5 #include <linux/unistd.h>
6 #include <linux/smp_lock.h>
7 #include <linux/init.h>
8 #include <linux/sched.h>
9 #include <linux/types.h>
10 
11 #include <asm/uaccess.h>
12 #include "sys32.h"
13 
14 struct k_sigaction32 {
15 	struct sigaction32 sa;
16 };
17 
18 typedef unsigned int old_sigset_t32;
19 
20 static int
put_old_sigset32(old_sigset_t32 * up,old_sigset_t * set)21 put_old_sigset32(old_sigset_t32 *up, old_sigset_t *set)
22 {
23 	old_sigset_t32 set32 = *set;
24 	return put_user(set32, up);
25 }
26 
27 static int
get_old_segset32(old_sigset_t32 * up,old_sigset_t * set)28 get_old_segset32(old_sigset_t32 *up, old_sigset_t *set)
29 {
30 	old_sigset_t32 set32;
31 	int r;
32 
33 	if ((r = get_user(set32, up)) == 0)
34 		*set = set32;
35 
36 	return r;
37 }
38 
39 long
sys32_sigpending(old_sigset_t32 * set)40 sys32_sigpending(old_sigset_t32 *set)
41 {
42 	extern long sys_sigpending(old_sigset_t *set);
43 	old_sigset_t pending;
44 	int ret;
45 
46 	KERNEL_SYSCALL(ret, sys_sigpending, &pending);
47 
48 	/* can't put_user an old_sigset_t -- it is too big */
49 	if (put_old_sigset32(set, &pending))
50 		return -EFAULT;
51 
52 	return ret;
53 }
54 
sys32_sigprocmask(int how,old_sigset_t32 * set,old_sigset_t32 * oset)55 int sys32_sigprocmask(int how, old_sigset_t32 *set,
56 				 old_sigset_t32 *oset)
57 {
58 	extern int sys_sigprocmask(int how, old_sigset_t *set,
59 				 old_sigset_t *oset);
60 	old_sigset_t s;
61 	int ret;
62 
63 	if (set && get_old_segset32 (set, &s))
64 		return -EFAULT;
65 	KERNEL_SYSCALL(ret, sys_sigprocmask, how, set ? &s : NULL, oset ? &s : NULL);
66 	if (!ret && oset && put_old_sigset32(oset, &s))
67 		return -EFAULT;
68 	return ret;
69 }
70 
71 static inline void
sigset_32to64(sigset_t * s64,sigset_t32 * s32)72 sigset_32to64(sigset_t *s64, sigset_t32 *s32)
73 {
74 	s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32);
75 }
76 
77 static inline void
sigset_64to32(sigset_t32 * s32,sigset_t * s64)78 sigset_64to32(sigset_t32 *s32, sigset_t *s64)
79 {
80 	s32->sig[0] = s64->sig[0] & 0xffffffffUL;
81 	s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL;
82 }
83 
84 static int
put_sigset32(sigset_t32 * up,sigset_t * set,size_t sz)85 put_sigset32(sigset_t32 *up, sigset_t *set, size_t sz)
86 {
87 	sigset_t32 s;
88 
89 	if (sz != sizeof *set) panic("put_sigset32()");
90 	sigset_64to32(&s, set);
91 
92 	return copy_to_user(up, &s, sizeof s);
93 }
94 
95 static int
get_sigset32(sigset_t32 * up,sigset_t * set,size_t sz)96 get_sigset32(sigset_t32 *up, sigset_t *set, size_t sz)
97 {
98 	sigset_t32 s;
99 	int r;
100 
101 	if (sz != sizeof *set) panic("put_sigset32()");
102 
103 	if ((r = copy_from_user(&s, up, sz)) == 0) {
104 		sigset_32to64(set, &s);
105 	}
106 
107 	return r;
108 }
109 
sys32_rt_sigprocmask(int how,sigset_t32 * set,sigset_t32 * oset,unsigned int sigsetsize)110 int sys32_rt_sigprocmask(int how, sigset_t32 *set, sigset_t32 *oset,
111 				    unsigned int sigsetsize)
112 {
113 	extern long sys_rt_sigprocmask(int how,
114 				    sigset_t *set, sigset_t *oset,
115 				   size_t sigsetsize);
116 	sigset_t old_set, new_set;
117 	int ret;
118 
119 	if (set && get_sigset32(set, &new_set, sigsetsize))
120 		return -EFAULT;
121 
122 	KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? &new_set : NULL,
123 				 oset ? &old_set : NULL, sigsetsize);
124 
125 	if (!ret && oset && put_sigset32(oset, &old_set, sigsetsize))
126 		return -EFAULT;
127 
128 	return ret;
129 }
130 
131 
sys32_rt_sigpending(sigset_t32 * uset,unsigned int sigsetsize)132 int sys32_rt_sigpending(sigset_t32 *uset, unsigned int sigsetsize)
133 {
134 	int ret;
135 	sigset_t set;
136 	extern long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
137 
138 	KERNEL_SYSCALL(ret, sys_rt_sigpending, &set, sigsetsize);
139 
140 	if (!ret && put_sigset32(uset, &set, sigsetsize))
141 		return -EFAULT;
142 
143 	return ret;
144 }
145 
146 long
sys32_rt_sigaction(int sig,const struct sigaction32 * act,struct sigaction32 * oact,size_t sigsetsize)147 sys32_rt_sigaction(int sig, const struct sigaction32 *act, struct sigaction32 *oact,
148                  size_t sigsetsize)
149 {
150 	struct k_sigaction32 new_sa32, old_sa32;
151 	struct k_sigaction new_sa, old_sa;
152 	int ret = -EINVAL;
153 
154 	if (act) {
155 		if (copy_from_user(&new_sa32.sa, act, sizeof new_sa32.sa))
156 			return -EFAULT;
157 		new_sa.sa.sa_handler = (__sighandler_t)(unsigned long)new_sa32.sa.sa_handler;
158 		new_sa.sa.sa_flags = new_sa32.sa.sa_flags;
159 		sigset_32to64(&new_sa.sa.sa_mask, &new_sa32.sa.sa_mask);
160 	}
161 
162 	ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
163 
164 	if (!ret && oact) {
165 		sigset_64to32(&old_sa32.sa.sa_mask, &old_sa.sa.sa_mask);
166 		old_sa32.sa.sa_flags = old_sa.sa.sa_flags;
167 		old_sa32.sa.sa_handler = (__sighandler_t32)(unsigned long)old_sa.sa.sa_handler;
168 		if (copy_to_user(oact, &old_sa32.sa, sizeof old_sa32.sa))
169 			return -EFAULT;
170 	}
171 	return ret;
172 }
173 
174 typedef struct {
175 	unsigned int ss_sp;
176 	int ss_flags;
177 	__kernel_size_t32 ss_size;
178 } stack_t32;
179 
180 int
do_sigaltstack32(const stack_t32 * uss32,stack_t32 * uoss32,unsigned long sp)181 do_sigaltstack32 (const stack_t32 *uss32, stack_t32 *uoss32, unsigned long sp)
182 {
183 	stack_t32 ss32, oss32;
184 	stack_t ss, oss;
185 	stack_t *ssp = NULL, *ossp = NULL;
186 	int ret;
187 
188 	if (uss32) {
189 		if (copy_from_user(&ss32, uss32, sizeof ss32))
190 			return -EFAULT;
191 
192 		ss.ss_sp = (void *)ss32.ss_sp;
193 		ss.ss_flags = ss32.ss_flags;
194 		ss.ss_size = ss32.ss_size;
195 
196 		ssp = &ss;
197 	}
198 
199 	if (uoss32)
200 		ossp = &oss;
201 
202 	KERNEL_SYSCALL(ret, do_sigaltstack, ssp, ossp, sp);
203 
204 	if (!ret && uoss32) {
205 		oss32.ss_sp = (unsigned int)(unsigned long)oss.ss_sp;
206 		oss32.ss_flags = oss.ss_flags;
207 		oss32.ss_size = oss.ss_size;
208 		if (copy_to_user(uoss32, &oss32, sizeof *uoss32))
209 			return -EFAULT;
210 	}
211 
212 	return ret;
213 }
214