|
@@ -428,14 +428,20 @@ static inline int sigio_perm(struct task_struct *p,
|
|
|
}
|
|
|
|
|
|
static void send_sigio_to_task(struct task_struct *p,
|
|
|
- struct fown_struct *fown,
|
|
|
+ struct fown_struct *fown,
|
|
|
int fd,
|
|
|
int reason)
|
|
|
{
|
|
|
- if (!sigio_perm(p, fown, fown->signum))
|
|
|
+ /*
|
|
|
+ * F_SETSIG can change ->signum lockless in parallel, make
|
|
|
+ * sure we read it once and use the same value throughout.
|
|
|
+ */
|
|
|
+ int signum = ACCESS_ONCE(fown->signum);
|
|
|
+
|
|
|
+ if (!sigio_perm(p, fown, signum))
|
|
|
return;
|
|
|
|
|
|
- switch (fown->signum) {
|
|
|
+ switch (signum) {
|
|
|
siginfo_t si;
|
|
|
default:
|
|
|
/* Queue a rt signal with the appropriate fd as its
|
|
@@ -444,7 +450,7 @@ static void send_sigio_to_task(struct task_struct *p,
|
|
|
delivered even if we can't queue. Failure to
|
|
|
queue in this case _should_ be reported; we fall
|
|
|
back to SIGIO in that case. --sct */
|
|
|
- si.si_signo = fown->signum;
|
|
|
+ si.si_signo = signum;
|
|
|
si.si_errno = 0;
|
|
|
si.si_code = reason;
|
|
|
/* Make sure we are called with one of the POLL_*
|
|
@@ -456,7 +462,7 @@ static void send_sigio_to_task(struct task_struct *p,
|
|
|
else
|
|
|
si.si_band = band_table[reason - POLL_IN];
|
|
|
si.si_fd = fd;
|
|
|
- if (!group_send_sig_info(fown->signum, &si, p))
|
|
|
+ if (!group_send_sig_info(signum, &si, p))
|
|
|
break;
|
|
|
/* fall-through: fall back on the old plain SIGIO signal */
|
|
|
case 0:
|