Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sh: use set_current_blocked() and block_sigmask()

As described in e6fa16ab ("signal: sigprocmask() should do
retarget_shared_pending()") the modification of current->blocked is
incorrect as we need to check whether the signal we're about to block is
pending in the shared queue.

Also, use the new helper function introduced in commit 5e6292c0f28f
("signal: add block_sigmask() for adding sigmask to current->blocked")
which centralises the code for updating current->blocked after
successfully delivering a signal and reduces the amount of duplicate code
across architectures. In the past some architectures got this code wrong,
so using this helper function should stop that from happening again.

Acked-by: Oleg Nesterov <oleg@redhat.com>
Cc: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>

authored by

Matt Fleming and committed by
Paul Mundt
5e047fa1 8368b0e0

+20 -49
+10 -22
arch/sh/kernel/signal_32.c
··· 58 58 unsigned long r5, unsigned long r6, unsigned long r7, 59 59 struct pt_regs __regs) 60 60 { 61 - mask &= _BLOCKABLE; 62 - spin_lock_irq(&current->sighand->siglock); 61 + sigset_t blocked; 62 + 63 63 current->saved_sigmask = current->blocked; 64 - siginitset(&current->blocked, mask); 65 - recalc_sigpending(); 66 - spin_unlock_irq(&current->sighand->siglock); 64 + 65 + mask &= _BLOCKABLE; 66 + siginitset(&blocked, mask); 67 + set_current_blocked(&blocked); 67 68 68 69 current->state = TASK_INTERRUPTIBLE; 69 70 schedule(); ··· 241 240 goto badframe; 242 241 243 242 sigdelsetmask(&set, ~_BLOCKABLE); 244 - 245 - spin_lock_irq(&current->sighand->siglock); 246 - current->blocked = set; 247 - recalc_sigpending(); 248 - spin_unlock_irq(&current->sighand->siglock); 243 + set_current_blocked(&set); 249 244 250 245 if (restore_sigcontext(regs, &frame->sc, &r0)) 251 246 goto badframe; ··· 271 274 goto badframe; 272 275 273 276 sigdelsetmask(&set, ~_BLOCKABLE); 274 - spin_lock_irq(&current->sighand->siglock); 275 - current->blocked = set; 276 - recalc_sigpending(); 277 - spin_unlock_irq(&current->sighand->siglock); 277 + set_current_blocked(&set); 278 278 279 279 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) 280 280 goto badframe; ··· 542 548 else 543 549 ret = setup_frame(sig, ka, oldset, regs); 544 550 545 - if (ret == 0) { 546 - spin_lock_irq(&current->sighand->siglock); 547 - sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 548 - if (!(ka->sa.sa_flags & SA_NODEFER)) 549 - sigaddset(&current->blocked,sig); 550 - recalc_sigpending(); 551 - spin_unlock_irq(&current->sighand->siglock); 552 - } 551 + if (ret == 0) 552 + block_sigmask(ka, sig); 553 553 554 554 return ret; 555 555 }
+10 -27
arch/sh/kernel/signal_64.c
··· 159 159 unsigned long r6, unsigned long r7, 160 160 struct pt_regs * regs) 161 161 { 162 - sigset_t saveset; 162 + sigset_t saveset, blocked; 163 + 164 + saveset = current->blocked; 163 165 164 166 mask &= _BLOCKABLE; 165 - spin_lock_irq(&current->sighand->siglock); 166 - saveset = current->blocked; 167 - siginitset(&current->blocked, mask); 168 - recalc_sigpending(); 169 - spin_unlock_irq(&current->sighand->siglock); 167 + siginitset(&blocked, mask); 168 + set_current_blocked(&blocked); 170 169 171 170 REF_REG_RET = -EINTR; 172 171 while (1) { ··· 197 198 if (copy_from_user(&newset, unewset, sizeof(newset))) 198 199 return -EFAULT; 199 200 sigdelsetmask(&newset, ~_BLOCKABLE); 200 - spin_lock_irq(&current->sighand->siglock); 201 201 saveset = current->blocked; 202 - current->blocked = newset; 203 - recalc_sigpending(); 204 - spin_unlock_irq(&current->sighand->siglock); 202 + set_current_blocked(&newset); 205 203 206 204 REF_REG_RET = -EINTR; 207 205 while (1) { ··· 404 408 goto badframe; 405 409 406 410 sigdelsetmask(&set, ~_BLOCKABLE); 407 - 408 - spin_lock_irq(&current->sighand->siglock); 409 - current->blocked = set; 410 - recalc_sigpending(); 411 - spin_unlock_irq(&current->sighand->siglock); 411 + set_current_blocked(&set); 412 412 413 413 if (restore_sigcontext(regs, &frame->sc, &ret)) 414 414 goto badframe; ··· 437 445 goto badframe; 438 446 439 447 sigdelsetmask(&set, ~_BLOCKABLE); 440 - spin_lock_irq(&current->sighand->siglock); 441 - current->blocked = set; 442 - recalc_sigpending(); 443 - spin_unlock_irq(&current->sighand->siglock); 448 + set_current_blocked(&set); 444 449 445 450 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret)) 446 451 goto badframe; ··· 723 734 else 724 735 ret = setup_frame(sig, ka, oldset, regs); 725 736 726 - if (ret == 0) { 727 - spin_lock_irq(&current->sighand->siglock); 728 - sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 729 - if (!(ka->sa.sa_flags & SA_NODEFER)) 730 - sigaddset(&current->blocked,sig); 731 - recalc_sigpending(); 732 - spin_unlock_irq(&current->sighand->siglock); 733 - } 737 + if (ret == 0) 738 + block_sigmask(ka, sig); 734 739 735 740 return ret; 736 741 }