Re: [RFC PATCH 1/2] Fix PF_NOFREEZE and freezeable race

Gautham R Shenoy
2007-04-23T10:27:42Z

On Fri, Apr 20, 2007 at 10:02:08PM +0400, Oleg Nesterov wrote:
> On 04/19, Rafael J. Wysocki wrote:
> >
> > On Thursday, 19 April 2007 14:02, Gautham R Shenoy wrote:
> > > This patch fixes the race pointed out by Oleg Nesterov.
> > >
> > > * Freezer marks a thread as freezeable.
> > > * The thread now marks itself PF_NOFREEZE causing it to
> > > freeze on calling try_to_freeze(). Thus the task is frozen, even though
> > > it doesn't want to.
> > > * Subsequent thaw_processes() will also fail to thaw the task since it is
> > > marked PF_NOFREEZE.
> > >
> > > Avoid this problem by checking the current task's PF_NOFREEZE status in the
> > > refrigerator before marking current as frozen.
> > >
> > > Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
> >
> > Looks good, although I'm not sure if we don't need to call recalc_sigpending()
> > for tasks that turn out to be PF_NOFREEZE.
>
> I agree, we should clear TIF_SIGPENDING. It is not so critical for user-space
> tasks, but for the kernel thread it may remain pending forever, causing subtle
> failures.
>
> Gautham, isn't it possible to make a more simpler patch ? Just add PF_NOFREEZE
> check to frozen_process,
>
> static inline void frozen_process(struct task_struct *p)
> {
> if (!unlikely(current->flags & PF_NOFREEZE)) {
> p->flags |= PF_FROZEN;
> wmb();
> }
> clear_tsk_thread_flag(p, TIF_FREEZE);
> }
>
> No?

Actually yes. The idea anyway was to check one last time before declaring
ourselves as frozen. So I thought the best place was inside refrigerator since
we are already holding the task_lock there.
I wasn't too sure about calling recalc_sigpending(), but now that you
mention it, I agree, this would be a nicer way to do it.

Btw, since frozen_process is currently being called only from
refrigerator, I am wondering if we still need the struct task_struct *p
parameter there. It's very unlikely that some other task would mark a
particular task as frozen. No?

Anyways, Andrew, Could you please replace the earlier sent patch titled
"fix_pf_nofreeze_and_freezeable_race.patch" with the following one?

Thanks and Regards
gautham.

-->
This patch fixes the race pointed out by Oleg Nesterov.

* Freezer marks a thread as freezeable.
* The thread now marks itself PF_NOFREEZE causing it to
freeze on calling try_to_freeze(). Thus the task is frozen, even though
it doesn't want to.
* Subsequent thaw_processes() will also fail to thaw the task since it is
marked PF_NOFREEZE.

Avoid this problem by checking the task's PF_NOFREEZE status in
frozen_processes() before marking the task as frozen.

Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
---
include/linux/freezer.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

Index: linux-2.6.21-rc6/include/linux/freezer.h
===================================================================
--- linux-2.6.21-rc6.orig/include/linux/freezer.h
+++ linux-2.6.21-rc6/include/linux/freezer.h
@@ -57,8 +57,10 @@ static inline int thaw_process(struct ta
*/
static inline void frozen_process(struct task_struct *p)
{
- p->flags |= PF_FROZEN;
- wmb();
+ if (!unlikely(p->flags & PF_NOFREEZE)) {
+ p->flags |= PF_FROZEN;
+ wmb();
+ }
clear_tsk_thread_flag(p, TIF_FREEZE);
}

--
Gautham R Shenoy
Linux Technology Center
IBM India.
"Freedom comes with a price tag of responsibility, which is still a bargain,
because Freedom is priceless!"