* BUG? "Call fasync() functions without the BKL" is racy @ 2008-11-28 19:25 Oleg Nesterov 2008-12-01 11:34 ` Andi Kleen 0 siblings, 1 reply; 12+ messages in thread From: Oleg Nesterov @ 2008-11-28 19:25 UTC (permalink / raw) To: Andi Kleen, Jonathan Corbet; +Cc: Al Viro, Vitaly Mayatskikh, linux-kernel Hi. Let's suppose we have the tasks T1, T2, T3 which share the same file, all do sys_fcntl(file, F_SETFL) in parallel. file->f_flags == 0. setfl(arg) does: if ((arg ^ filp->f_flags) & FASYNC) // --- WINDOW_1 --- filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0) // --- WINDOW_2 --- filp->f_flags = arg; T1 calls setfl(FASYNC), preempted in WINDOW_1. T2 calls setfl(FASYNC), does all job and returns. T3 calls setfl(0), sees ->f_flags & FASYNC, does ->fasync(on => 0), preempted in WINDOW_2. T1 resumes, does ->fasync(on => 1) again, update ->f_flags (it already has FASYNC) and returns. T3 resumes, and clears FASYNC from ->f_flags. Now, this file was added into some "struct fasync_struct", but ->f_flags doesn't have FASYNC. This means __fput() will skip ->fasync(on => 0) and the next kill_fasync() can crash because fa_file points to the freed/reused memory. I think a238b790d5f99c7832f9b73ac8847025815b85f7 should be reverted. Or do you see the better fix? Unless I missed something of course. Oleg. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: BUG? "Call fasync() functions without the BKL" is racy 2008-11-28 19:25 BUG? "Call fasync() functions without the BKL" is racy Oleg Nesterov @ 2008-12-01 11:34 ` Andi Kleen 2008-12-01 19:15 ` Oleg Nesterov 0 siblings, 1 reply; 12+ messages in thread From: Andi Kleen @ 2008-12-01 11:34 UTC (permalink / raw) To: Oleg Nesterov; +Cc: Jonathan Corbet, Al Viro, Vitaly Mayatskikh, linux-kernel Oleg Nesterov wrote: > Hi. > > Let's suppose we have the tasks T1, T2, T3 which share the same file, > all do sys_fcntl(file, F_SETFL) in parallel. file->f_flags == 0. > > setfl(arg) does: > > if ((arg ^ filp->f_flags) & FASYNC) > // --- WINDOW_1 --- > filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0) > // --- WINDOW_2 --- > filp->f_flags = arg; > > T1 calls setfl(FASYNC), preempted in WINDOW_1. > > T2 calls setfl(FASYNC), does all job and returns. > > T3 calls setfl(0), sees ->f_flags & FASYNC, does ->fasync(on => 0), > preempted in WINDOW_2. > > T1 resumes, does ->fasync(on => 1) again, update ->f_flags (it > already has FASYNC) and returns. > > T3 resumes, and clears FASYNC from ->f_flags. > > > > Now, this file was added into some "struct fasync_struct", but > ->f_flags doesn't have FASYNC. This means __fput() will skip > ->fasync(on => 0) and the next kill_fasync() can crash because > fa_file points to the freed/reused memory. Nasty. Thanks for catching. > > I think a238b790d5f99c7832f9b73ac8847025815b85f7 should be reverted. > Or do you see the better fix? Hmm, about checking for this case and retrying? Or put a fasync mutex into files_struct. -Andi ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: BUG? "Call fasync() functions without the BKL" is racy 2008-12-01 11:34 ` Andi Kleen @ 2008-12-01 19:15 ` Oleg Nesterov 2008-12-01 19:34 ` Jonathan Corbet 2008-12-02 0:15 ` BUG? "Call fasync() functions without the BKL" is racy Andi Kleen 0 siblings, 2 replies; 12+ messages in thread From: Oleg Nesterov @ 2008-12-01 19:15 UTC (permalink / raw) To: Andi Kleen; +Cc: Jonathan Corbet, Al Viro, Vitaly Mayatskikh, linux-kernel On 12/01, Andi Kleen wrote: > > Oleg Nesterov wrote: >> >> Let's suppose we have the tasks T1, T2, T3 which share the same file, >> all do sys_fcntl(file, F_SETFL) in parallel. file->f_flags == 0. >> >> setfl(arg) does: >> >> if ((arg ^ filp->f_flags) & FASYNC) >> // --- WINDOW_1 --- >> filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0) >> // --- WINDOW_2 --- >> filp->f_flags = arg; >> >> T1 calls setfl(FASYNC), preempted in WINDOW_1. >> >> T2 calls setfl(FASYNC), does all job and returns. >> >> T3 calls setfl(0), sees ->f_flags & FASYNC, does ->fasync(on => 0), >> preempted in WINDOW_2. >> >> T1 resumes, does ->fasync(on => 1) again, update ->f_flags (it >> already has FASYNC) and returns. >> >> T3 resumes, and clears FASYNC from ->f_flags. >> >> >> >> Now, this file was added into some "struct fasync_struct", but >> ->f_flags doesn't have FASYNC. This means __fput() will skip >> ->fasync(on => 0) and the next kill_fasync() can crash because >> fa_file points to the freed/reused memory. > > Nasty. Thanks for catching. Actually, this is more simple. Somehow I missed that setf() _always_ updates ->f_flags, so we have a trivial race with 2 threads. >> >> I think a238b790d5f99c7832f9b73ac8847025815b85f7 should be reverted. >> Or do you see the better fix? > > Hmm, about checking for this case and retrying? > > Or put a fasync mutex into files_struct. Perhaps, we can add O_LOCK_FLAGS, then something like --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -175,6 +175,15 @@ static int setfl(int fd, struct file * f if (error) return error; + spin_lock(¤t->files->file_lock); + if (!(filp->f_flags & O_LOCK_FLAGS)) + filp->f_flags |= O_LOCK_FLAGS; + else + error = -EAGAIN; + spin_unlock(¤t->files->file_lock); + if (error) /* pretend ->f_flags was changed after us */ + return 0; + if ((arg ^ filp->f_flags) & FASYNC) { if (filp->f_op && filp->f_op->fasync) { error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0); @@ -183,7 +192,8 @@ static int setfl(int fd, struct file * f } } - filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK); + filp->f_flags = (arg & SETFL_MASK) | + (filp->f_flags & ~(SETFL_MASK | O_LOCK_FLAGS)); out: return error; } What do you think? (btw, ioctl_fioasync() calls lock_kernel() but it doesn't protect ->f_flags) Oleg. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: BUG? "Call fasync() functions without the BKL" is racy 2008-12-01 19:15 ` Oleg Nesterov @ 2008-12-01 19:34 ` Jonathan Corbet 2008-12-02 12:29 ` Oleg Nesterov 2008-12-02 0:15 ` BUG? "Call fasync() functions without the BKL" is racy Andi Kleen 1 sibling, 1 reply; 12+ messages in thread From: Jonathan Corbet @ 2008-12-01 19:34 UTC (permalink / raw) To: Oleg Nesterov; +Cc: Andi Kleen, Al Viro, Vitaly Mayatskikh, linux-kernel On Mon, 1 Dec 2008 20:15:55 +0100 Oleg Nesterov <oleg@redhat.com> wrote: > > Hmm, about checking for this case and retrying? > > > > Or put a fasync mutex into files_struct. > > Perhaps, we can add O_LOCK_FLAGS, then something like > > --- a/fs/fcntl.c > +++ b/fs/fcntl.c > @@ -175,6 +175,15 @@ static int setfl(int fd, struct file * f > if (error) > return error; > > + spin_lock(¤t->files->file_lock); > + if (!(filp->f_flags & O_LOCK_FLAGS)) > + filp->f_flags |= O_LOCK_FLAGS; > + else > + error = -EAGAIN; > + spin_unlock(¤t->files->file_lock); > + if (error) /* pretend ->f_flags was changed after us > */ > + return 0; > + This strikes me as overkill. What we really want to do is to protect against concurrent access to f_flags - something which could come about in a couple of other situations (nfsd/vfs.c tweaks it, for example). We *could* just extend files_lock to cover f_flags too, but that comes at the cost of making ->fasync() atomic when it never has been before - doesn't seem like a good idea. Perhaps we just need a single f_flags_mutex? For code changing f_flags only (it woudn't be needed to query the flags)? Then ioctl_fionbio() and ioctl_fioasync() could use it too. It's hard to imagine that there's enough contention to warrant any more than that, especially given that it all (except ioctl_fionbio()) has been under the BKL until now. jon ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: BUG? "Call fasync() functions without the BKL" is racy 2008-12-01 19:34 ` Jonathan Corbet @ 2008-12-02 12:29 ` Oleg Nesterov 2008-12-02 16:30 ` Andi Kleen 0 siblings, 1 reply; 12+ messages in thread From: Oleg Nesterov @ 2008-12-02 12:29 UTC (permalink / raw) To: Jonathan Corbet; +Cc: Andi Kleen, Al Viro, Vitaly Mayatskikh, linux-kernel On 12/01, Jonathan Corbet wrote: > > On Mon, 1 Dec 2008 20:15:55 +0100 > Oleg Nesterov <oleg@redhat.com> wrote: > > > > Hmm, about checking for this case and retrying? > > > > > > Or put a fasync mutex into files_struct. > > > > Perhaps, we can add O_LOCK_FLAGS, then something like > > > > --- a/fs/fcntl.c > > +++ b/fs/fcntl.c > > @@ -175,6 +175,15 @@ static int setfl(int fd, struct file * f > > if (error) > > return error; > > > > + spin_lock(¤t->files->file_lock); > > + if (!(filp->f_flags & O_LOCK_FLAGS)) > > + filp->f_flags |= O_LOCK_FLAGS; > > + else > > + error = -EAGAIN; > > + spin_unlock(¤t->files->file_lock); > > + if (error) /* pretend ->f_flags was changed after us > > */ > > + return 0; > > + > > This strikes me as overkill. and doesn't really help. fork() clones files_struct, we can't rely on ->file_lock. And we have fd passing. > What we really want to do is to protect > against concurrent access to f_flags - something which could come about > in a couple of other situations (nfsd/vfs.c tweaks it, for example). > We *could* just extend files_lock to cover f_flags too, but that comes > at the cost of making ->fasync() atomic when it never has been before - > doesn't seem like a good idea. > > Perhaps we just need a single f_flags_mutex? For code changing > f_flags only (it woudn't be needed to query the flags)? Then > ioctl_fionbio() and ioctl_fioasync() could use it too. It's hard to > imagine that there's enough contention to warrant any more than that, > especially given that it all (except ioctl_fionbio()) has been under > the BKL until now. A bit ugly to use the global mutex to protect all ->f_flags, but yes, I agree. Imho this is 2.6.28 material, we need the simple fix or the user can crash the kernel. Still I'd like to see the better fix for the long term, the only (afaics) flag with the "side effect" is FASYNC, perhaps we can move it to (say) ->f_mode, but this is ugly of course and still need serialization for the pathes which play with FASYNC. Otherwise, any code which changes ->f_flags can clear FASYNC if we race with sys_fcntl(F_SETFL, FASYNC). If we introduce the new lock, we should change for example tty_io.c:fionbio(), tty has the ->fasync() method. Currently tty_io.c relies on lock_kernel(). Oleg. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: BUG? "Call fasync() functions without the BKL" is racy 2008-12-02 12:29 ` Oleg Nesterov @ 2008-12-02 16:30 ` Andi Kleen 2008-12-03 19:06 ` Oleg Nesterov 0 siblings, 1 reply; 12+ messages in thread From: Andi Kleen @ 2008-12-02 16:30 UTC (permalink / raw) To: Oleg Nesterov; +Cc: Jonathan Corbet, Al Viro, Vitaly Mayatskikh, linux-kernel > Still I'd like to see the better fix for the long term, the only (afaics) > flag with the "side effect" is FASYNC, perhaps we can move it to (say) > ->f_mode, but this is ugly of course and still need serialization for the > pathes which play with FASYNC. I wonder if we need FASYNC at all. This could be gotten implicitely by looking at the fasync_list -Andi ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: BUG? "Call fasync() functions without the BKL" is racy 2008-12-02 16:30 ` Andi Kleen @ 2008-12-03 19:06 ` Oleg Nesterov 2008-12-03 21:21 ` Andi Kleen 0 siblings, 1 reply; 12+ messages in thread From: Oleg Nesterov @ 2008-12-03 19:06 UTC (permalink / raw) To: Andi Kleen; +Cc: Jonathan Corbet, Al Viro, Vitaly Mayatskikh, linux-kernel On 12/02, Andi Kleen wrote: > >> Still I'd like to see the better fix for the long term, the only (afaics) >> flag with the "side effect" is FASYNC, perhaps we can move it to (say) >> ->f_mode, but this is ugly of course and still need serialization for the >> pathes which play with FASYNC. > > I wonder if we need FASYNC at all. This could be gotten implicitely by > looking at the fasync_list Only if socket. Serioulsy, I think the best (partial, yes) fix for now is to restore lock_kernel() in setfl() and change ioctl_fioxxx() accordingly. At least this protect us from tty too. I agree with Jonathan, we need the lock to protect ->f_flags, but this needs changes. Personally, I do not like the global mutex, perhaps we can use some "unused" bit in struct file. Say, ->f_mode is never changed (afaics), we can place it here. Now, any code which changes ->f_flags can do if (test_and_set_bit(FLAGS_LOCK_BIT)) return; whatever(); ->f_flags = new_flags; clear_bit(FLAGS_LOCK_BIT); No need to disable preemption, we never spin waiting for the lock bit. If it is locked - somebody else updates ->f_flags, we can pretend it does this after us. This can confuse F_GETFL after F_SETFL (if F_SETFL "fails"), but I think in that case user-space is wrong anyway, it must not do F_GETFL in parallel. Not that I think this is very good idea though ;) Oleg. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: BUG? "Call fasync() functions without the BKL" is racy 2008-12-03 19:06 ` Oleg Nesterov @ 2008-12-03 21:21 ` Andi Kleen 2008-12-03 22:45 ` Jonathan Corbet 0 siblings, 1 reply; 12+ messages in thread From: Andi Kleen @ 2008-12-03 21:21 UTC (permalink / raw) To: Oleg Nesterov; +Cc: Jonathan Corbet, Al Viro, Vitaly Mayatskikh, linux-kernel >> I wonder if we need FASYNC at all. This could be gotten implicitely by >> looking at the fasync_list > > Only if socket. But the helpers used by the character drivers add it too I think. > Serioulsy, I think the best (partial, yes) fix for now is to restore > lock_kernel() in setfl() and change ioctl_fioxxx() accordingly. > At least this protect us from tty too. For 2.6.28 I agree. > Not that I think this is very good idea though ;) The lock bit sounds reasonable. -Andi ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: BUG? "Call fasync() functions without the BKL" is racy 2008-12-03 21:21 ` Andi Kleen @ 2008-12-03 22:45 ` Jonathan Corbet 2008-12-04 14:34 ` Oleg Nesterov 2008-12-05 23:12 ` [PATCH 2.6.28] Fix FASYNC race Jonathan Corbet 0 siblings, 2 replies; 12+ messages in thread From: Jonathan Corbet @ 2008-12-03 22:45 UTC (permalink / raw) To: Andi Kleen; +Cc: Oleg Nesterov, Al Viro, Vitaly Mayatskikh, linux-kernel On Wed, 03 Dec 2008 22:21:02 +0100 Andi Kleen <ak@linux.intel.com> wrote: > > Serioulsy, I think the best (partial, yes) fix for now is to restore > > lock_kernel() in setfl() and change ioctl_fioxxx() accordingly. > > At least this protect us from tty too. > > For 2.6.28 I agree. OK, what do you all think of the following? It returns fcntl.c to its previous state, and adds locking in fs/ioctl.c. It's worth noting that ioctl_fioasync() has always been racy in exactly the same way. If this passes muster I'll send it upward shortly. jon -- Restore BKL protection to manipulations of f_flags Changeset a238b790d5f99c7832f9b73ac8847025815b85f7 (Call fasync() functions without the BKL) introduced a race which could leave file->f_flags in a state inconsistent with what the underlying driver/filesystem believes. Revert that change, and also fix the same races in ioctl_fioasync() and ioctl_fionbio(). This is a minimal, short-term fix; the real fix will not involve the BKL. Reported-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Jonathan Corbet <corbet@lwn.net> diff --git a/fs/fcntl.c b/fs/fcntl.c index ac4f7db..549daf8 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -19,6 +19,7 @@ #include <linux/signal.h> #include <linux/rcupdate.h> #include <linux/pid_namespace.h> +#include <linux/smp_lock.h> #include <asm/poll.h> #include <asm/siginfo.h> @@ -175,6 +176,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg) if (error) return error; + /* + * We still need a lock here for now to keep multiple FASYNC calls + * from racing with each other. + */ + lock_kernel(); if ((arg ^ filp->f_flags) & FASYNC) { if (filp->f_op && filp->f_op->fasync) { error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0); @@ -185,6 +191,7 @@ static int setfl(int fd, struct file * filp, unsigned long arg) filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK); out: + unlock_kernel(); return error; } diff --git a/fs/ioctl.c b/fs/ioctl.c index d152856..fc8fcaa 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -400,11 +400,9 @@ static int ioctl_fioasync(unsigned int fd, struct file *filp, /* Did FASYNC state change ? */ if ((flag ^ filp->f_flags) & FASYNC) { - if (filp->f_op && filp->f_op->fasync) { - lock_kernel(); + if (filp->f_op && filp->f_op->fasync) error = filp->f_op->fasync(fd, filp, on); - unlock_kernel(); - } else + else error = -ENOTTY; } if (error) @@ -440,11 +438,17 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, break; case FIONBIO: + /* BKL needed to avoid races tweaking f_flags */ + lock_kernel(); error = ioctl_fionbio(filp, argp); + unlock_kernel(); break; case FIOASYNC: + /* BKL needed to avoid races tweaking f_flags */ + lock_kernel(); error = ioctl_fioasync(fd, filp, argp); + unlock_kernel(); break; case FIOQSIZE: ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: BUG? "Call fasync() functions without the BKL" is racy 2008-12-03 22:45 ` Jonathan Corbet @ 2008-12-04 14:34 ` Oleg Nesterov 2008-12-05 23:12 ` [PATCH 2.6.28] Fix FASYNC race Jonathan Corbet 1 sibling, 0 replies; 12+ messages in thread From: Oleg Nesterov @ 2008-12-04 14:34 UTC (permalink / raw) To: Jonathan Corbet; +Cc: Andi Kleen, Al Viro, Vitaly Mayatskikh, linux-kernel On 12/03, Jonathan Corbet wrote: > > On Wed, 03 Dec 2008 22:21:02 +0100 > Andi Kleen <ak@linux.intel.com> wrote: > > > > Serioulsy, I think the best (partial, yes) fix for now is to restore > > > lock_kernel() in setfl() and change ioctl_fioxxx() accordingly. > > > At least this protect us from tty too. > > > > For 2.6.28 I agree. > > OK, what do you all think of the following? It returns fcntl.c to its > previous state, and adds locking in fs/ioctl.c. It's worth noting that > ioctl_fioasync() has always been racy in exactly the same way. Yes, I agree with you and Andi, imho this is what we need for 2.6.28. Thanks Jonathan! Oleg. ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2.6.28] Fix FASYNC race 2008-12-03 22:45 ` Jonathan Corbet 2008-12-04 14:34 ` Oleg Nesterov @ 2008-12-05 23:12 ` Jonathan Corbet 1 sibling, 0 replies; 12+ messages in thread From: Jonathan Corbet @ 2008-12-05 23:12 UTC (permalink / raw) To: Linus Torvalds Cc: Andi Kleen, Oleg Nesterov, Al Viro, Vitaly Mayatskikh, linux-kernel Hi, Linus, The following patch closes a race which was introduced by the fasync() BKL pushdown patch. As it turns out, f_flags handling was already racy, but that change made it worse. Here, we fix it (and a longer-standing race) minimally by reintroducing the BKL; a better fix will be prepared for 2.6.29. jon --- Fix a race condition in FASYNC handling Changeset a238b790d5f99c7832f9b73ac8847025815b85f7 (Call fasync() functions without the BKL) introduced a race which could leave file->f_flags in a state inconsistent with what the underlying driver/filesystem believes. Revert that change, and also fix the same races in ioctl_fioasync() and ioctl_fionbio(). This is a minimal, short-term fix; the real fix will not involve the BKL. Reported-by: Oleg Nesterov <oleg@redhat.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: stable@kernel.org Signed-off-by: Jonathan Corbet <corbet@lwn.net> --- fs/fcntl.c | 7 +++++++ fs/ioctl.c | 12 ++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/fs/fcntl.c b/fs/fcntl.c index ac4f7db..549daf8 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -19,6 +19,7 @@ #include <linux/signal.h> #include <linux/rcupdate.h> #include <linux/pid_namespace.h> +#include <linux/smp_lock.h> #include <asm/poll.h> #include <asm/siginfo.h> @@ -175,6 +176,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg) if (error) return error; + /* + * We still need a lock here for now to keep multiple FASYNC calls + * from racing with each other. + */ + lock_kernel(); if ((arg ^ filp->f_flags) & FASYNC) { if (filp->f_op && filp->f_op->fasync) { error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0); @@ -185,6 +191,7 @@ static int setfl(int fd, struct file * filp, unsigned long arg) filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK); out: + unlock_kernel(); return error; } diff --git a/fs/ioctl.c b/fs/ioctl.c index d152856..fc8fcaa 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -400,11 +400,9 @@ static int ioctl_fioasync(unsigned int fd, struct file *filp, /* Did FASYNC state change ? */ if ((flag ^ filp->f_flags) & FASYNC) { - if (filp->f_op && filp->f_op->fasync) { - lock_kernel(); + if (filp->f_op && filp->f_op->fasync) error = filp->f_op->fasync(fd, filp, on); - unlock_kernel(); - } else + else error = -ENOTTY; } if (error) @@ -440,11 +438,17 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, break; case FIONBIO: + /* BKL needed to avoid races tweaking f_flags */ + lock_kernel(); error = ioctl_fionbio(filp, argp); + unlock_kernel(); break; case FIOASYNC: + /* BKL needed to avoid races tweaking f_flags */ + lock_kernel(); error = ioctl_fioasync(fd, filp, argp); + unlock_kernel(); break; case FIOQSIZE: -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: BUG? "Call fasync() functions without the BKL" is racy 2008-12-01 19:15 ` Oleg Nesterov 2008-12-01 19:34 ` Jonathan Corbet @ 2008-12-02 0:15 ` Andi Kleen 1 sibling, 0 replies; 12+ messages in thread From: Andi Kleen @ 2008-12-02 0:15 UTC (permalink / raw) To: Oleg Nesterov; +Cc: Jonathan Corbet, Al Viro, Vitaly Mayatskikh, linux-kernel > Perhaps, we can add O_LOCK_FLAGS, then something like > > --- a/fs/fcntl.c > +++ b/fs/fcntl.c > @@ -175,6 +175,15 @@ static int setfl(int fd, struct file * f > if (error) > return error; > > + spin_lock(¤t->files->file_lock); > + if (!(filp->f_flags & O_LOCK_FLAGS)) > + filp->f_flags |= O_LOCK_FLAGS; > + else > + error = -EAGAIN; > + spin_unlock(¤t->files->file_lock); > + if (error) /* pretend ->f_flags was changed after us */ > + return 0; > + > if ((arg ^ filp->f_flags) & FASYNC) { > if (filp->f_op && filp->f_op->fasync) { > error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0); > @@ -183,7 +192,8 @@ static int setfl(int fd, struct file * f > } > } > > - filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK); > + filp->f_flags = (arg & SETFL_MASK) | > + (filp->f_flags & ~(SETFL_MASK | O_LOCK_FLAGS)); > out: > return error; > } > > What do you think? Looks reasonable. Just would need to make sure that O_LOCK_FLAGS doesn't leak out to user space. -Andi > ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2008-12-05 23:13 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-11-28 19:25 BUG? "Call fasync() functions without the BKL" is racy Oleg Nesterov 2008-12-01 11:34 ` Andi Kleen 2008-12-01 19:15 ` Oleg Nesterov 2008-12-01 19:34 ` Jonathan Corbet 2008-12-02 12:29 ` Oleg Nesterov 2008-12-02 16:30 ` Andi Kleen 2008-12-03 19:06 ` Oleg Nesterov 2008-12-03 21:21 ` Andi Kleen 2008-12-03 22:45 ` Jonathan Corbet 2008-12-04 14:34 ` Oleg Nesterov 2008-12-05 23:12 ` [PATCH 2.6.28] Fix FASYNC race Jonathan Corbet 2008-12-02 0:15 ` BUG? "Call fasync() functions without the BKL" is racy Andi Kleen
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox