aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c73
1 files changed, 47 insertions, 26 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 1814e68e4de3..dbd7fe073c55 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -159,6 +159,10 @@ void recalc_sigpending(void)
159 159
160/* Given the mask, find the first available signal that should be serviced. */ 160/* Given the mask, find the first available signal that should be serviced. */
161 161
162#define SYNCHRONOUS_MASK \
163 (sigmask(SIGSEGV) | sigmask(SIGBUS) | sigmask(SIGILL) | \
164 sigmask(SIGTRAP) | sigmask(SIGFPE))
165
162int next_signal(struct sigpending *pending, sigset_t *mask) 166int next_signal(struct sigpending *pending, sigset_t *mask)
163{ 167{
164 unsigned long i, *s, *m, x; 168 unsigned long i, *s, *m, x;
@@ -166,26 +170,39 @@ int next_signal(struct sigpending *pending, sigset_t *mask)
166 170
167 s = pending->signal.sig; 171 s = pending->signal.sig;
168 m = mask->sig; 172 m = mask->sig;
173
174 /*
175 * Handle the first word specially: it contains the
176 * synchronous signals that need to be dequeued first.
177 */
178 x = *s &~ *m;
179 if (x) {
180 if (x & SYNCHRONOUS_MASK)
181 x &= SYNCHRONOUS_MASK;
182 sig = ffz(~x) + 1;
183 return sig;
184 }
185
169 switch (_NSIG_WORDS) { 186 switch (_NSIG_WORDS) {
170 default: 187 default:
171 for (i = 0; i < _NSIG_WORDS; ++i, ++s, ++m) 188 for (i = 1; i < _NSIG_WORDS; ++i) {
172 if ((x = *s &~ *m) != 0) { 189 x = *++s &~ *++m;
173 sig = ffz(~x) + i*_NSIG_BPW + 1; 190 if (!x)
174 break; 191 continue;
175 } 192 sig = ffz(~x) + i*_NSIG_BPW + 1;
193 break;
194 }
176 break; 195 break;
177 196
178 case 2: if ((x = s[0] &~ m[0]) != 0) 197 case 2:
179 sig = 1; 198 x = s[1] &~ m[1];
180 else if ((x = s[1] &~ m[1]) != 0) 199 if (!x)
181 sig = _NSIG_BPW + 1;
182 else
183 break; 200 break;
184 sig += ffz(~x); 201 sig = ffz(~x) + _NSIG_BPW + 1;
185 break; 202 break;
186 203
187 case 1: if ((x = *s &~ *m) != 0) 204 case 1:
188 sig = ffz(~x) + 1; 205 /* Nothing to do */
189 break; 206 break;
190 } 207 }
191 208
@@ -218,17 +235,17 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimi
218 struct user_struct *user; 235 struct user_struct *user;
219 236
220 /* 237 /*
221 * We won't get problems with the target's UID changing under us 238 * Protect access to @t credentials. This can go away when all
222 * because changing it requires RCU be used, and if t != current, the 239 * callers hold rcu read lock.
223 * caller must be holding the RCU readlock (by way of a spinlock) and
224 * we use RCU protection here
225 */ 240 */
241 rcu_read_lock();
226 user = get_uid(__task_cred(t)->user); 242 user = get_uid(__task_cred(t)->user);
227 atomic_inc(&user->sigpending); 243 atomic_inc(&user->sigpending);
244 rcu_read_unlock();
228 245
229 if (override_rlimit || 246 if (override_rlimit ||
230 atomic_read(&user->sigpending) <= 247 atomic_read(&user->sigpending) <=
231 t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur) { 248 task_rlimit(t, RLIMIT_SIGPENDING)) {
232 q = kmem_cache_alloc(sigqueue_cachep, flags); 249 q = kmem_cache_alloc(sigqueue_cachep, flags);
233 } else { 250 } else {
234 print_dropped_signal(sig); 251 print_dropped_signal(sig);
@@ -979,7 +996,8 @@ static void print_fatal_signal(struct pt_regs *regs, int signr)
979 for (i = 0; i < 16; i++) { 996 for (i = 0; i < 16; i++) {
980 unsigned char insn; 997 unsigned char insn;
981 998
982 __get_user(insn, (unsigned char *)(regs->ip + i)); 999 if (get_user(insn, (unsigned char *)(regs->ip + i)))
1000 break;
983 printk("%02x ", insn); 1001 printk("%02x ", insn);
984 } 1002 }
985 } 1003 }
@@ -1179,11 +1197,12 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
1179 int ret = -EINVAL; 1197 int ret = -EINVAL;
1180 struct task_struct *p; 1198 struct task_struct *p;
1181 const struct cred *pcred; 1199 const struct cred *pcred;
1200 unsigned long flags;
1182 1201
1183 if (!valid_signal(sig)) 1202 if (!valid_signal(sig))
1184 return ret; 1203 return ret;
1185 1204
1186 read_lock(&tasklist_lock); 1205 rcu_read_lock();
1187 p = pid_task(pid, PIDTYPE_PID); 1206 p = pid_task(pid, PIDTYPE_PID);
1188 if (!p) { 1207 if (!p) {
1189 ret = -ESRCH; 1208 ret = -ESRCH;
@@ -1199,14 +1218,16 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
1199 ret = security_task_kill(p, info, sig, secid); 1218 ret = security_task_kill(p, info, sig, secid);
1200 if (ret) 1219 if (ret)
1201 goto out_unlock; 1220 goto out_unlock;
1202 if (sig && p->sighand) { 1221
1203 unsigned long flags; 1222 if (sig) {
1204 spin_lock_irqsave(&p->sighand->siglock, flags); 1223 if (lock_task_sighand(p, &flags)) {
1205 ret = __send_signal(sig, info, p, 1, 0); 1224 ret = __send_signal(sig, info, p, 1, 0);
1206 spin_unlock_irqrestore(&p->sighand->siglock, flags); 1225 unlock_task_sighand(p, &flags);
1226 } else
1227 ret = -ESRCH;
1207 } 1228 }
1208out_unlock: 1229out_unlock:
1209 read_unlock(&tasklist_lock); 1230 rcu_read_unlock();
1210 return ret; 1231 return ret;
1211} 1232}
1212EXPORT_SYMBOL_GPL(kill_pid_info_as_uid); 1233EXPORT_SYMBOL_GPL(kill_pid_info_as_uid);