X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=fs%2Ffcntl.c;h=a040b764f8e38b6a5067642713d4f9c6e9dc92ba;hb=e3dc5a665d39112e98cfd5bbc7fda2963c00c12c;hp=f9c03ca3b2f409f05b09937201f81d39eb5ed169;hpb=2f38d70fb4e97e7d00e12eaac45790cf6ebd7b22;p=~andy%2Flinux diff --git a/fs/fcntl.c b/fs/fcntl.c index f9c03ca3b2f..a040b764f8e 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -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: