1
2
3
4
5
6
7
8
9
10
11#include <linux/compiler.h>
12#include <linux/errno.h>
13#include <linux/kernel.h>
14#include <linux/signal.h>
15#include <linux/syscalls.h>
16
17#include <asm/compat.h>
18#include <asm/compat-signal.h>
19#include <asm/uaccess.h>
20#include <asm/unistd.h>
21
22#include "signal-common.h"
23
24
25
26typedef unsigned int __sighandler32_t;
27typedef void (*vfptr_t)(void);
28
29
30
31
32
33asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset)
34{
35 return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t));
36}
37
38SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *, act,
39 struct compat_sigaction __user *, oact)
40{
41 struct k_sigaction new_ka, old_ka;
42 int ret;
43 int err = 0;
44
45 if (act) {
46 old_sigset_t mask;
47 s32 handler;
48
49 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
50 return -EFAULT;
51 err |= __get_user(handler, &act->sa_handler);
52 new_ka.sa.sa_handler = (void __user *)(s64)handler;
53 err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
54 err |= __get_user(mask, &act->sa_mask.sig[0]);
55 if (err)
56 return -EFAULT;
57
58 siginitset(&new_ka.sa.sa_mask, mask);
59 }
60
61 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
62
63 if (!ret && oact) {
64 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
65 return -EFAULT;
66 err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
67 err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
68 &oact->sa_handler);
69 err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
70 err |= __put_user(0, &oact->sa_mask.sig[1]);
71 err |= __put_user(0, &oact->sa_mask.sig[2]);
72 err |= __put_user(0, &oact->sa_mask.sig[3]);
73 if (err)
74 return -EFAULT;
75 }
76
77 return ret;
78}
79
80int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
81{
82 int err;
83
84 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
85 return -EFAULT;
86
87
88
89
90
91
92
93
94 err = __put_user(from->si_signo, &to->si_signo);
95 err |= __put_user(from->si_errno, &to->si_errno);
96 err |= __put_user((short)from->si_code, &to->si_code);
97 if (from->si_code < 0)
98 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
99 else {
100 switch (from->si_code >> 16) {
101 case __SI_TIMER >> 16:
102 err |= __put_user(from->si_tid, &to->si_tid);
103 err |= __put_user(from->si_overrun, &to->si_overrun);
104 err |= __put_user(from->si_int, &to->si_int);
105 break;
106 case __SI_CHLD >> 16:
107 err |= __put_user(from->si_utime, &to->si_utime);
108 err |= __put_user(from->si_stime, &to->si_stime);
109 err |= __put_user(from->si_status, &to->si_status);
110 default:
111 err |= __put_user(from->si_pid, &to->si_pid);
112 err |= __put_user(from->si_uid, &to->si_uid);
113 break;
114 case __SI_FAULT >> 16:
115 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
116 break;
117 case __SI_POLL >> 16:
118 err |= __put_user(from->si_band, &to->si_band);
119 err |= __put_user(from->si_fd, &to->si_fd);
120 break;
121 case __SI_RT >> 16:
122 case __SI_MESGQ >> 16:
123 err |= __put_user(from->si_pid, &to->si_pid);
124 err |= __put_user(from->si_uid, &to->si_uid);
125 err |= __put_user(from->si_int, &to->si_int);
126 break;
127 case __SI_SYS >> 16:
128 err |= __copy_to_user(&to->si_call_addr, &from->si_call_addr,
129 sizeof(compat_uptr_t));
130 err |= __put_user(from->si_syscall, &to->si_syscall);
131 err |= __put_user(from->si_arch, &to->si_arch);
132 break;
133 }
134 }
135 return err;
136}
137
138int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
139{
140 if (copy_from_user(to, from, 3*sizeof(int)) ||
141 copy_from_user(to->_sifields._pad,
142 from->_sifields._pad, SI_PAD_SIZE32))
143 return -EFAULT;
144
145 return 0;
146}
147