All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kirill Tkhai <tkhai@yandex.ru>
To: Oleg Nesterov <oleg@redhat.com>, Kirill Tkhai <ktkhai@parallels.com>
Cc: linux-kernel@vger.kernel.org,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,
	Vladimir Davydov <vdavydov@parallels.com>
Subject: Re: [PATCH v3] sched/numa: fix unsafe get_task_struct() in task_numa_assign()
Date: Tue, 21 Oct 2014 00:18:46 +0400	[thread overview]
Message-ID: <54456E26.2000103@yandex.ru> (raw)
In-Reply-To: <20141020182748.GA20424@redhat.com>

Hi, Oleg,

On 20.10.2014 22:27, Oleg Nesterov wrote:
> On 10/20, Oleg Nesterov wrote:
>>
>> On 10/20, Oleg Nesterov wrote:
>>>
>>> Again, perhaps we will need to change the lifetime rules for task_struct
>>> anyway, if we have more problems like this. But until then this looks like
>>> an overkill to me. Plus rq_curr_if_not_put() looks too subtle, and it is
>>> not generic.
>>
>> Yes... otoh, perhaps we can do something more generic? Something like
>>
>> 	struct task_struct *xxx(struct task_struct **ptask)
>> 	{
>> 		struct task_struct *task;
>> 		void *sighand;
>> 	retry:
>> 		task = ACCESS_ONCE(*ptask);
>> 		if (!task)
>> 			return NULL;
>>
>> 		if (IS_ENABLED(CONFIG_DEBUG_PAGEALLOC)) {
>> 			if (probe_kernel_read(&sighand, &task->sighand, sizeof(sighand)))
>> 				goto retry;
>> 		} else {
>> 			sighand = task->sighand;
>> 		}
>>
>> 		if (!sighand)
>> 			return NULL;
>> 		/*
>> 		 * Pairs with atomic_dec_and_test() in put_task_struct(task).
>> 		 * If we have read the freed/reused memory, we must see that
>> 		 * the pointer was updated.
>> 		 */
>> 		smp_rmb();
>> 		if (task != ACCESS_ONCE(*ptask))
>> 			goto retry;
>>
>> 		return task;
>> 	}
>>
>> task_numa_compare() can do cur = xxx(&rc->curr), but this helper can work
>> with any "task_struct *" pointer assuming that somehow this pointer is
>> cleared or changed before the final put_task_struct().
>>
>> What do you think? Peter?
> 
> And if we introduce this helper, it would better to check "sighand != NULL"
> after "task != *ptask":
> 
> 	struct task_struct *xxx(struct task_struct **ptask)
> 	{
> 		struct task_struct *task;
> 		struct sighand_struct *sighand;
> 
> 	retry:
> 		task = ACCESS_ONCE(*ptask);
> 		if (!task)
> 			return task;
> 
> 		if (IS_ENABLED(CONFIG_DEBUG_PAGEALLOC)) {
> 			if (probe_kernel_read(&sighand, &task->sighand, sizeof(sighand)))
> 				goto retry;
> 		} else {
> 			sighand = task->sighand;
> 		}
> 		/*
> 		 * Pairs with atomic_dec_and_test() in put_task_struct(task).
> 		 * If we have read the freed/reused memory, we must see that
> 		 * the pointer was updated.
> 		 */
> 		smp_rmb();
> 		if (unlikely(task != ACCESS_ONCE(*ptask)))
> 			goto retry;
> 		/*
> 		 * release_task(task) was already called, potentially before
> 		 * the caller took rcu_read_lock() and in this case it can be
> 		 * freed before rcu_read_unlock().
> 		 */
> 		if (!sighand)
> 			return NULL;
> 		return task;
> 	}
> 
> Of course, task_numa_compare() do not really need "retry", and task == NULL
> is not possible. But this way the new helper can (probably) have more users,
> and this just looks better imo.

I think generic helper is a good idea. The prototype looks OK.

But I'm a little doubt about retry loop. If this helper is generic and
one day it may move to ./include directory, isn't there a probability
people will use it wrong? This loop may bring delays or something bad.
Nothing specific, just suspicion...

And since we still depends on RCU, I'd suggest to add its lockdep assert.

Kirill

  reply	other threads:[~2014-10-20 20:18 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-20 10:15 [PATCH v3] sched/numa: fix unsafe get_task_struct() in task_numa_assign() Kirill Tkhai
2014-10-20 14:47 ` Oleg Nesterov
2014-10-20 16:56   ` Oleg Nesterov
2014-10-20 18:27     ` Oleg Nesterov
2014-10-20 20:18       ` Kirill Tkhai [this message]
2014-10-20 20:50         ` Oleg Nesterov
2014-10-20 21:05           ` Kirill Tkhai
2014-10-20 21:34             ` Oleg Nesterov
2014-10-20 22:57               ` Peter Zijlstra
2014-10-21  9:45           ` Peter Zijlstra
2014-10-21 19:03             ` Oleg Nesterov
2014-10-21 20:03               ` Kirill Tkhai
2014-10-21 20:10                 ` Kirill Tkhai
2014-10-22  9:09               ` Peter Zijlstra
2014-10-22 16:14                 ` Oleg Nesterov
2014-10-22 16:37                   ` Peter Zijlstra
2014-10-22 18:14                     ` introduce probe_slab_address? (Was: sched/numa: fix unsafe get_task_struct() in task_numa_assign()) Oleg Nesterov
2014-10-22 18:59                       ` introduce probe_slab_address? David Miller
2014-10-22 19:42                         ` Oleg Nesterov
2014-10-22 20:08                           ` David Miller
2014-10-22 20:20                             ` Oleg Nesterov
2014-10-24  9:44                         ` Peter Zijlstra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54456E26.2000103@yandex.ru \
    --to=tkhai@yandex.ru \
    --cc=ktkhai@parallels.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=oleg@redhat.com \
    --cc=peterz@infradead.org \
    --cc=vdavydov@parallels.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.