lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1207690074.4687.18.camel@bobble.smo.corp.google.com>
Date:	Tue, 08 Apr 2008 14:27:54 -0700
From:	Frank Mayhar <fmayhar@...gle.com>
To:	Roland McGrath <roland@...hat.com>
Cc:	frank@...t.com, linux-kernel@...r.kernel.org
Subject: Re: posix-cpu-timers revamp

On Mon, 2008-04-07 at 13:08 -0700, Roland McGrath wrote:
> > Regarding the second approach, without locking wouldn't that still be
> > racy?  Couldn't exit_state change (and therefore __exit_signal() run)
> > between the check and the dereference?
> No.  current->exit_state can go from zero to nonzero only by current
> running code in the do_exit path.  current does not progress on that
> path while current is inside one update_process_times call.

Okay.  One of the paths to the update code is through update_curr() in
sched_fair.c, which (in my tree) calls account_group_exec_runtime() to
update the sum_exec_runtime field:

	delta_exec = (unsigned long)(now - curr->exec_start);

	__update_curr(cfs_rq, curr, delta_exec);
	curr->exec_start = now;

	if (entity_is_task(curr)) {
		struct task_struct *curtask = task_of(curr);

		cpuacct_charge(curtask, delta_exec);
		account_group_exec_runtime(curtask, delta_exec);
	}

To make sure that I understand what's going on, I put an invariant at
the beginning of account_group_exec_runtime():

static inline void account_group_exec_runtime(struct task_struct *tsk,
					       unsigned long long ns)
{
	struct signal_struct *sig = tsk->signal;
	struct task_cputime *times;

	BUG_ON(tsk != current);
	if (unlikely(tsk->exit_state))
		return;
	if (!sig->cputime.totals)
		return;
	times = per_cpu_ptr(sig->cputime.totals, get_cpu());
	times->sum_exec_runtime += ns;
	put_cpu_no_resched();
}

And, you guessed it, the invariant gets violated.  Apparently the passed
task_struct isn't the same as "current" at this point.

Any ideas?  Am I checking the wrong thing?  If we're really not updating
current then the task we are updating could very easily be running
through __exit_signal() on another CPU.  (And while I wait for your
response I will of course continue to try to figure this out.)
-- 
Frank Mayhar <fmayhar@...gle.com>
Google, Inc.

--
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

Powered by Openwall GNU/*/Linux Powered by OpenVZ