1
2
3
4
5
6
7#include <linux/sched.h>
8#include <linux/kernel.h>
9#include <linux/signal.h>
10#include <linux/errno.h>
11#include <linux/wait.h>
12#include <linux/ptrace.h>
13#include <linux/unistd.h>
14#include <linux/mm.h>
15#include <linux/smp.h>
16#include <linux/smp_lock.h>
17
18#include <asm/uaccess.h>
19
20#define _S(nr) (1<<((nr)-1))
21
22#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
23
24#ifndef __alpha__
25
26
27
28
29
30
31
32
33
34
35
36
37
38asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset)
39{
40 sigset_t old_set = current->blocked;
41
42 if (set) {
43 sigset_t new_set;
44
45 if(get_user(new_set, set))
46 return -EFAULT;
47
48 new_set &= _BLOCKABLE;
49 switch (how) {
50 default:
51 return -EINVAL;
52 case SIG_BLOCK:
53 new_set |= old_set;
54 break;
55 case SIG_UNBLOCK:
56 new_set = old_set & ~new_set;
57 break;
58 case SIG_SETMASK:
59 break;
60 }
61 current->blocked = new_set;
62 }
63 if (oset) {
64 if(put_user(old_set, oset))
65 return -EFAULT;
66 }
67 return 0;
68}
69
70
71
72
73asmlinkage int sys_sgetmask(void)
74{
75
76 return current->blocked;
77}
78
79asmlinkage int sys_ssetmask(int newmask)
80{
81 int old;
82
83 spin_lock_irq(¤t->sigmask_lock);
84 old = current->blocked;
85 current->blocked = newmask & _BLOCKABLE;
86 spin_unlock_irq(¤t->sigmask_lock);
87
88 return old;
89}
90
91#endif
92
93asmlinkage int sys_sigpending(sigset_t *set)
94{
95 int ret;
96
97
98 spin_lock_irq(¤t->sigmask_lock);
99 ret = put_user(current->blocked & current->signal, set);
100 spin_unlock_irq(¤t->sigmask_lock);
101 return ret;
102}
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121inline void check_pending(int signum)
122{
123 struct sigaction *p;
124
125 p = signum - 1 + current->sig->action;
126 spin_lock(¤t->sigmask_lock);
127 if (p->sa_handler == SIG_IGN) {
128 current->signal &= ~_S(signum);
129 } else if (p->sa_handler == SIG_DFL) {
130 if (signum == SIGCONT ||
131 signum == SIGCHLD ||
132 signum != SIGWINCH)
133 current->signal &= ~_S(signum);
134 }
135 spin_unlock(¤t->sigmask_lock);
136}
137
138#ifndef __alpha__
139
140
141
142asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler)
143{
144 struct sigaction tmp;
145
146 if (signum<1 || signum>32)
147 return -EINVAL;
148 if (signum==SIGKILL || signum==SIGSTOP)
149 return -EINVAL;
150 if (handler != SIG_DFL && handler != SIG_IGN) {
151 if(verify_area(VERIFY_READ, handler, 1))
152 return -EFAULT;
153 }
154
155 memset(&tmp, 0, sizeof(tmp));
156 tmp.sa_handler = handler;
157 tmp.sa_flags = SA_ONESHOT | SA_NOMASK;
158
159 spin_lock_irq(¤t->sig->siglock);
160 handler = current->sig->action[signum-1].sa_handler;
161 current->sig->action[signum-1] = tmp;
162 check_pending(signum);
163 spin_unlock_irq(¤t->sig->siglock);
164
165 return (unsigned long) handler;
166}
167#endif
168
169#ifndef __sparc__
170asmlinkage int sys_sigaction(int signum, const struct sigaction * action,
171 struct sigaction * oldaction)
172{
173 struct sigaction new_sa, *p;
174
175 if (signum < 1 || signum > 32)
176 return -EINVAL;
177
178 p = signum - 1 + current->sig->action;
179
180 if (action) {
181 if (copy_from_user(&new_sa, action, sizeof(struct sigaction)))
182 return -EFAULT;
183 if (signum==SIGKILL || signum==SIGSTOP)
184 return -EINVAL;
185 }
186
187 if (oldaction) {
188
189
190
191
192
193 if (copy_to_user(oldaction, p, sizeof(struct sigaction)))
194 return -EFAULT;
195 }
196
197 if (action) {
198 spin_lock_irq(¤t->sig->siglock);
199 *p = new_sa;
200 check_pending(signum);
201 spin_unlock_irq(¤t->sig->siglock);
202 }
203 return 0;
204}
205#endif
206