[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20110830155733.GB22754@redhat.com>
Date: Tue, 30 Aug 2011 17:57:33 +0200
From: Oleg Nesterov <oleg@...hat.com>
To: David Rientjes <rientjes@...gle.com>
Cc: Andrew Morton <akpm@...ux-foundation.org>,
Ying Han <yinghan@...gle.com>,
KOSAKI Motohiro <kosaki.motohiro@...fujitsu.com>,
linux-kernel@...r.kernel.org, linux-mm@...ck.org
Subject: Re: [patch 2/2] oom: fix race while temporarily setting current's
oom_score_adj
On 08/30, David Rientjes wrote:
>
> Using that function to both set oom_score_adj to OOM_SCORE_ADJ_MAX and
> then reinstate the previous value is racy since it's possible that
> userspace can set the value to something else itself before the old value
> is reinstated. That results in userspace setting current's oom_score_adj
> to a different value and then the kernel immediately setting it back to
> its previous value without notification.
Sure,
> To fix this, a new compare_swap_oom_score_adj() function is introduced
> with the same semantics as the compare and swap CAS instruction, or
> CMPXCHG on x86. It is used to reinstate the previous value of
> oom_score_adj if and only if the present value is the same as the old
> value.
But this can't fix the race completely ?
> +void compare_swap_oom_score_adj(int old_val, int new_val)
> +{
> + struct sighand_struct *sighand = current->sighand;
> +
> + spin_lock_irq(&sighand->siglock);
> + if (current->signal->oom_score_adj == old_val)
> + current->signal->oom_score_adj = new_val;
> + spin_unlock_irq(&sighand->siglock);
> +}
So. This is used this way:
old_val = test_set_oom_score_adj(OOM_SCORE_ADJ_MAX);
do_something();
compare_swap_oom_score_adj(OOM_SCORE_ADJ_MAX, old_val);
What if userspace sets oom_score_adj = OOM_SCORE_ADJ_MAX in between?
May be the callers should use OOM_SCORE_ADJ_MAX + 1 instead, this way
we can't confuse old_val with the value from the userspace...
But in fact I am writing this email because I have the question.
Do we really need 2 helpers, and do we really need to allow to set
the arbitrary value?
I mean, perhaps we can do something like
void set_oom_victim(bool on)
{
if (on) {
oom_score_adj += ADJ_MAX - ADJ_MIN + 1;
} else if (oom_score_adj > ADJ_MAX) {
oom_score_adj -= ADJ_MAX - ADJ_MIN + 1;
}
}
Not sure this really makes sense, just curious.
Oleg.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists