<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux-toradex.git/kernel/cred.c, branch v2.6.32.60</title>
<subtitle>Linux kernel for Apalis and Colibri modules</subtitle>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/'/>
<entry>
<title>cred: copy_process() should clear child-&gt;replacement_session_keyring</title>
<updated>2012-10-07T21:37:30+00:00</updated>
<author>
<name>Oleg Nesterov</name>
<email>oleg@redhat.com</email>
</author>
<published>2012-04-09T19:03:50+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=66174b0e459d78b9bcb77ee37ecff25404f91140'/>
<id>66174b0e459d78b9bcb77ee37ecff25404f91140</id>
<content type='text'>
commit 79549c6dfda0603dba9a70a53467ce62d9335c33 upstream

keyctl_session_to_parent(task) sets -&gt;replacement_session_keyring,
it should be processed and cleared by key_replace_session_keyring().

However, this task can fork before it notices TIF_NOTIFY_RESUME and
the new child gets the bogus -&gt;replacement_session_keyring copied by
dup_task_struct(). This is obviously wrong and, if nothing else, this
leads to put_cred(already_freed_cred).

change copy_creds() to clear this member. If copy_process() fails
before this point the wrong -&gt;replacement_session_keyring doesn't
matter, exit_creds() won't be called.

Cc: &lt;stable@vger.kernel.org&gt;
Signed-off-by: Oleg Nesterov &lt;oleg@redhat.com&gt;
Acked-by: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Willy Tarreau &lt;w@1wt.eu&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
commit 79549c6dfda0603dba9a70a53467ce62d9335c33 upstream

keyctl_session_to_parent(task) sets -&gt;replacement_session_keyring,
it should be processed and cleared by key_replace_session_keyring().

However, this task can fork before it notices TIF_NOTIFY_RESUME and
the new child gets the bogus -&gt;replacement_session_keyring copied by
dup_task_struct(). This is obviously wrong and, if nothing else, this
leads to put_cred(already_freed_cred).

change copy_creds() to clear this member. If copy_process() fails
before this point the wrong -&gt;replacement_session_keyring doesn't
matter, exit_creds() won't be called.

Cc: &lt;stable@vger.kernel.org&gt;
Signed-off-by: Oleg Nesterov &lt;oleg@redhat.com&gt;
Acked-by: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Willy Tarreau &lt;w@1wt.eu&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>CRED: Fix memory and refcount leaks upon security_prepare_creds() failure</title>
<updated>2011-03-02T14:46:39+00:00</updated>
<author>
<name>Tetsuo Handa</name>
<email>penguin-kernel@I-love.SAKURA.ne.jp</email>
</author>
<published>2011-02-07T13:36:16+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=890650798af784a1d7944a762b787784077ed14f'/>
<id>890650798af784a1d7944a762b787784077ed14f</id>
<content type='text'>
commit fb2b2a1d37f80cc818fd4487b510f4e11816e5e1 upstream.

In prepare_kernel_cred() since 2.6.29, put_cred(new) is called without
assigning new-&gt;usage when security_prepare_creds() returned an error.  As a
result, memory for new and refcount for new-&gt;{user,group_info,tgcred} are
leaked because put_cred(new) won't call __put_cred() unless old-&gt;usage == 1.

Fix these leaks by assigning new-&gt;usage (and new-&gt;subscribers which was added
in 2.6.32) before calling security_prepare_creds().

Signed-off-by: Tetsuo Handa &lt;penguin-kernel@I-love.SAKURA.ne.jp&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;

</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
commit fb2b2a1d37f80cc818fd4487b510f4e11816e5e1 upstream.

In prepare_kernel_cred() since 2.6.29, put_cred(new) is called without
assigning new-&gt;usage when security_prepare_creds() returned an error.  As a
result, memory for new and refcount for new-&gt;{user,group_info,tgcred} are
leaked because put_cred(new) won't call __put_cred() unless old-&gt;usage == 1.

Fix these leaks by assigning new-&gt;usage (and new-&gt;subscribers which was added
in 2.6.32) before calling security_prepare_creds().

Signed-off-by: Tetsuo Handa &lt;penguin-kernel@I-love.SAKURA.ne.jp&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;

</pre>
</div>
</content>
</entry>
<entry>
<title>CRED: Fix BUG() upon security_cred_alloc_blank() failure</title>
<updated>2011-03-02T14:46:39+00:00</updated>
<author>
<name>Tetsuo Handa</name>
<email>penguin-kernel@I-love.SAKURA.ne.jp</email>
</author>
<published>2011-02-07T13:36:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=016d370ba62b783a81defeb01aff2ea23d28c28a'/>
<id>016d370ba62b783a81defeb01aff2ea23d28c28a</id>
<content type='text'>
commit 2edeaa34a6e3f2c43b667f6c4f7b27944b811695 upstream.

In cred_alloc_blank() since 2.6.32, abort_creds(new) is called with
new-&gt;security == NULL and new-&gt;magic == 0 when security_cred_alloc_blank()
returns an error.  As a result, BUG() will be triggered if SELinux is enabled
or CONFIG_DEBUG_CREDENTIALS=y.

If CONFIG_DEBUG_CREDENTIALS=y, BUG() is called from __invalid_creds() because
cred-&gt;magic == 0.  Failing that, BUG() is called from selinux_cred_free()
because selinux_cred_free() is not expecting cred-&gt;security == NULL.  This does
not affect smack_cred_free(), tomoyo_cred_free() or apparmor_cred_free().

Fix these bugs by

(1) Set new-&gt;magic before calling security_cred_alloc_blank().

(2) Handle null cred-&gt;security in creds_are_invalid() and selinux_cred_free().

Signed-off-by: Tetsuo Handa &lt;penguin-kernel@I-love.SAKURA.ne.jp&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;

</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
commit 2edeaa34a6e3f2c43b667f6c4f7b27944b811695 upstream.

In cred_alloc_blank() since 2.6.32, abort_creds(new) is called with
new-&gt;security == NULL and new-&gt;magic == 0 when security_cred_alloc_blank()
returns an error.  As a result, BUG() will be triggered if SELinux is enabled
or CONFIG_DEBUG_CREDENTIALS=y.

If CONFIG_DEBUG_CREDENTIALS=y, BUG() is called from __invalid_creds() because
cred-&gt;magic == 0.  Failing that, BUG() is called from selinux_cred_free()
because selinux_cred_free() is not expecting cred-&gt;security == NULL.  This does
not affect smack_cred_free(), tomoyo_cred_free() or apparmor_cred_free().

Fix these bugs by

(1) Set new-&gt;magic before calling security_cred_alloc_blank().

(2) Handle null cred-&gt;security in creds_are_invalid() and selinux_cred_free().

Signed-off-by: Tetsuo Handa &lt;penguin-kernel@I-love.SAKURA.ne.jp&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;

</pre>
</div>
</content>
</entry>
<entry>
<title>CRED: Fix get_task_cred() and task_state() to not resurrect dead credentials</title>
<updated>2011-03-02T14:46:37+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2010-07-29T11:45:49+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=c8fd44092f8f4ddcaac39f898769f64580a5a244'/>
<id>c8fd44092f8f4ddcaac39f898769f64580a5a244</id>
<content type='text'>
commit de09a9771a5346029f4d11e4ac886be7f9bfdd75 upstream.

It's possible for get_task_cred() as it currently stands to 'corrupt' a set of
credentials by incrementing their usage count after their replacement by the
task being accessed.

What happens is that get_task_cred() can race with commit_creds():

	TASK_1			TASK_2			RCU_CLEANER
	--&gt;get_task_cred(TASK_2)
	rcu_read_lock()
	__cred = __task_cred(TASK_2)
				--&gt;commit_creds()
				old_cred = TASK_2-&gt;real_cred
				TASK_2-&gt;real_cred = ...
				put_cred(old_cred)
				  call_rcu(old_cred)
		[__cred-&gt;usage == 0]
	get_cred(__cred)
		[__cred-&gt;usage == 1]
	rcu_read_unlock()
							--&gt;put_cred_rcu()
							[__cred-&gt;usage == 1]
							panic()

However, since a tasks credentials are generally not changed very often, we can
reasonably make use of a loop involving reading the creds pointer and using
atomic_inc_not_zero() to attempt to increment it if it hasn't already hit zero.

If successful, we can safely return the credentials in the knowledge that, even
if the task we're accessing has released them, they haven't gone to the RCU
cleanup code.

We then change task_state() in procfs to use get_task_cred() rather than
calling get_cred() on the result of __task_cred(), as that suffers from the
same problem.

Without this change, a BUG_ON in __put_cred() or in put_cred_rcu() can be
tripped when it is noticed that the usage count is not zero as it ought to be,
for example:

kernel BUG at kernel/cred.c:168!
invalid opcode: 0000 [#1] SMP
last sysfs file: /sys/kernel/mm/ksm/run
CPU 0
Pid: 2436, comm: master Not tainted 2.6.33.3-85.fc13.x86_64 #1 0HR330/OptiPlex
745
RIP: 0010:[&lt;ffffffff81069881&gt;]  [&lt;ffffffff81069881&gt;] __put_cred+0xc/0x45
RSP: 0018:ffff88019e7e9eb8  EFLAGS: 00010202
RAX: 0000000000000001 RBX: ffff880161514480 RCX: 00000000ffffffff
RDX: 00000000ffffffff RSI: ffff880140c690c0 RDI: ffff880140c690c0
RBP: ffff88019e7e9eb8 R08: 00000000000000d0 R09: 0000000000000000
R10: 0000000000000001 R11: 0000000000000040 R12: ffff880140c690c0
R13: ffff88019e77aea0 R14: 00007fff336b0a5c R15: 0000000000000001
FS:  00007f12f50d97c0(0000) GS:ffff880007400000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f8f461bc000 CR3: 00000001b26ce000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process master (pid: 2436, threadinfo ffff88019e7e8000, task ffff88019e77aea0)
Stack:
 ffff88019e7e9ec8 ffffffff810698cd ffff88019e7e9ef8 ffffffff81069b45
&lt;0&gt; ffff880161514180 ffff880161514480 ffff880161514180 0000000000000000
&lt;0&gt; ffff88019e7e9f28 ffffffff8106aace 0000000000000001 0000000000000246
Call Trace:
 [&lt;ffffffff810698cd&gt;] put_cred+0x13/0x15
 [&lt;ffffffff81069b45&gt;] commit_creds+0x16b/0x175
 [&lt;ffffffff8106aace&gt;] set_current_groups+0x47/0x4e
 [&lt;ffffffff8106ac89&gt;] sys_setgroups+0xf6/0x105
 [&lt;ffffffff81009b02&gt;] system_call_fastpath+0x16/0x1b
Code: 48 8d 71 ff e8 7e 4e 15 00 85 c0 78 0b 8b 75 ec 48 89 df e8 ef 4a 15 00
48 83 c4 18 5b c9 c3 55 8b 07 8b 07 48 89 e5 85 c0 74 04 &lt;0f&gt; 0b eb fe 65 48 8b
04 25 00 cc 00 00 48 3b b8 58 04 00 00 75
RIP  [&lt;ffffffff81069881&gt;] __put_cred+0xc/0x45
 RSP &lt;ffff88019e7e9eb8&gt;
---[ end trace df391256a100ebdd ]---

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Acked-by: Jiri Olsa &lt;jolsa@redhat.com&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;

</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
commit de09a9771a5346029f4d11e4ac886be7f9bfdd75 upstream.

It's possible for get_task_cred() as it currently stands to 'corrupt' a set of
credentials by incrementing their usage count after their replacement by the
task being accessed.

What happens is that get_task_cred() can race with commit_creds():

	TASK_1			TASK_2			RCU_CLEANER
	--&gt;get_task_cred(TASK_2)
	rcu_read_lock()
	__cred = __task_cred(TASK_2)
				--&gt;commit_creds()
				old_cred = TASK_2-&gt;real_cred
				TASK_2-&gt;real_cred = ...
				put_cred(old_cred)
				  call_rcu(old_cred)
		[__cred-&gt;usage == 0]
	get_cred(__cred)
		[__cred-&gt;usage == 1]
	rcu_read_unlock()
							--&gt;put_cred_rcu()
							[__cred-&gt;usage == 1]
							panic()

However, since a tasks credentials are generally not changed very often, we can
reasonably make use of a loop involving reading the creds pointer and using
atomic_inc_not_zero() to attempt to increment it if it hasn't already hit zero.

If successful, we can safely return the credentials in the knowledge that, even
if the task we're accessing has released them, they haven't gone to the RCU
cleanup code.

We then change task_state() in procfs to use get_task_cred() rather than
calling get_cred() on the result of __task_cred(), as that suffers from the
same problem.

Without this change, a BUG_ON in __put_cred() or in put_cred_rcu() can be
tripped when it is noticed that the usage count is not zero as it ought to be,
for example:

kernel BUG at kernel/cred.c:168!
invalid opcode: 0000 [#1] SMP
last sysfs file: /sys/kernel/mm/ksm/run
CPU 0
Pid: 2436, comm: master Not tainted 2.6.33.3-85.fc13.x86_64 #1 0HR330/OptiPlex
745
RIP: 0010:[&lt;ffffffff81069881&gt;]  [&lt;ffffffff81069881&gt;] __put_cred+0xc/0x45
RSP: 0018:ffff88019e7e9eb8  EFLAGS: 00010202
RAX: 0000000000000001 RBX: ffff880161514480 RCX: 00000000ffffffff
RDX: 00000000ffffffff RSI: ffff880140c690c0 RDI: ffff880140c690c0
RBP: ffff88019e7e9eb8 R08: 00000000000000d0 R09: 0000000000000000
R10: 0000000000000001 R11: 0000000000000040 R12: ffff880140c690c0
R13: ffff88019e77aea0 R14: 00007fff336b0a5c R15: 0000000000000001
FS:  00007f12f50d97c0(0000) GS:ffff880007400000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f8f461bc000 CR3: 00000001b26ce000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process master (pid: 2436, threadinfo ffff88019e7e8000, task ffff88019e77aea0)
Stack:
 ffff88019e7e9ec8 ffffffff810698cd ffff88019e7e9ef8 ffffffff81069b45
&lt;0&gt; ffff880161514180 ffff880161514480 ffff880161514180 0000000000000000
&lt;0&gt; ffff88019e7e9f28 ffffffff8106aace 0000000000000001 0000000000000246
Call Trace:
 [&lt;ffffffff810698cd&gt;] put_cred+0x13/0x15
 [&lt;ffffffff81069b45&gt;] commit_creds+0x16b/0x175
 [&lt;ffffffff8106aace&gt;] set_current_groups+0x47/0x4e
 [&lt;ffffffff8106ac89&gt;] sys_setgroups+0xf6/0x105
 [&lt;ffffffff81009b02&gt;] system_call_fastpath+0x16/0x1b
Code: 48 8d 71 ff e8 7e 4e 15 00 85 c0 78 0b 8b 75 ec 48 89 df e8 ef 4a 15 00
48 83 c4 18 5b c9 c3 55 8b 07 8b 07 48 89 e5 85 c0 74 04 &lt;0f&gt; 0b eb fe 65 48 8b
04 25 00 cc 00 00 48 3b b8 58 04 00 00 75
RIP  [&lt;ffffffff81069881&gt;] __put_cred+0xc/0x45
 RSP &lt;ffff88019e7e9eb8&gt;
---[ end trace df391256a100ebdd ]---

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Acked-by: Jiri Olsa &lt;jolsa@redhat.com&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;

</pre>
</div>
</content>
</entry>
<entry>
<title>sched: Remove remaining USER_SCHED code</title>
<updated>2011-02-17T23:37:19+00:00</updated>
<author>
<name>Li Zefan</name>
<email>lizf@cn.fujitsu.com</email>
</author>
<published>2011-02-10T08:50:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=05db2a0c01f58216a33f94153cd46a9190de3514'/>
<id>05db2a0c01f58216a33f94153cd46a9190de3514</id>
<content type='text'>
Commit: 32bd7eb5a7f4596c8440dd9440322fe9e686634d upstream

This is left over from commit 7c9414385e ("sched: Remove USER_SCHED"")

Signed-off-by: Li Zefan &lt;lizf@cn.fujitsu.com&gt;
Acked-by: Dhaval Giani &lt;dhaval.giani@gmail.com&gt;
Signed-off-by: Peter Zijlstra &lt;a.p.zijlstra@chello.nl&gt;
Cc: David Howells &lt;dhowells@redhat.com&gt;
LKML-Reference: &lt;4BA9A05F.7010407@cn.fujitsu.com&gt;
Signed-off-by: Ingo Molnar &lt;mingo@elte.hu&gt;
Signed-off-by: Mike Galbraith &lt;efault@gmx.de&gt;
Acked-by: Peter Zijlstra &lt;a.p.zijlstra@chello.nl&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Commit: 32bd7eb5a7f4596c8440dd9440322fe9e686634d upstream

This is left over from commit 7c9414385e ("sched: Remove USER_SCHED"")

Signed-off-by: Li Zefan &lt;lizf@cn.fujitsu.com&gt;
Acked-by: Dhaval Giani &lt;dhaval.giani@gmail.com&gt;
Signed-off-by: Peter Zijlstra &lt;a.p.zijlstra@chello.nl&gt;
Cc: David Howells &lt;dhowells@redhat.com&gt;
LKML-Reference: &lt;4BA9A05F.7010407@cn.fujitsu.com&gt;
Signed-off-by: Ingo Molnar &lt;mingo@elte.hu&gt;
Signed-off-by: Mike Galbraith &lt;efault@gmx.de&gt;
Acked-by: Peter Zijlstra &lt;a.p.zijlstra@chello.nl&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>CRED: Fix a race in creds_are_invalid() in credentials debugging</title>
<updated>2010-05-12T21:57:10+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2010-04-21T09:28:25+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=fd701336cefd200882c5c32dfea09690221067fb'/>
<id>fd701336cefd200882c5c32dfea09690221067fb</id>
<content type='text'>
commit e134d200d57d43b171dcb0b55c178a1a0c7db14a upstream.

creds_are_invalid() reads both cred-&gt;usage and cred-&gt;subscribers and then
compares them to make sure the number of processes subscribed to a cred struct
never exceeds the refcount of that cred struct.

The problem is that this can cause a race with both copy_creds() and
exit_creds() as the two counters, whilst they are of atomic_t type, are only
atomic with respect to themselves, and not atomic with respect to each other.

This means that if creds_are_invalid() can read the values on one CPU whilst
they're being modified on another CPU, and so can observe an evolving state in
which the subscribers count now is greater than the usage count a moment
before.

Switching the order in which the counts are read cannot help, so the thing to
do is to remove that particular check.

I had considered rechecking the values to see if they're in flux if the test
fails, but I can't guarantee they won't appear the same, even if they've
changed several times in the meantime.

Note that this can only happen if CONFIG_DEBUG_CREDENTIALS is enabled.

The problem is only likely to occur with multithreaded programs, and can be
tested by the tst-eintr1 program from glibc's "make check".  The symptoms look
like:

	CRED: Invalid credentials
	CRED: At include/linux/cred.h:240
	CRED: Specified credentials: ffff88003dda5878 [real][eff]
	CRED: -&gt;magic=43736564, put_addr=(null)
	CRED: -&gt;usage=766, subscr=766
	CRED: -&gt;*uid = { 0,0,0,0 }
	CRED: -&gt;*gid = { 0,0,0,0 }
	CRED: -&gt;security is ffff88003d72f538
	CRED: -&gt;security {359, 359}
	------------[ cut here ]------------
	kernel BUG at kernel/cred.c:850!
	...
	RIP: 0010:[&lt;ffffffff81049889&gt;]  [&lt;ffffffff81049889&gt;] __invalid_creds+0x4e/0x52
	...
	Call Trace:
	 [&lt;ffffffff8104a37b&gt;] copy_creds+0x6b/0x23f

Note the -&gt;usage=766 and subscr=766.  The values appear the same because
they've been re-read since the check was made.

Reported-by: Roland McGrath &lt;roland@redhat.com&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: James Morris &lt;jmorris@namei.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;

</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
commit e134d200d57d43b171dcb0b55c178a1a0c7db14a upstream.

creds_are_invalid() reads both cred-&gt;usage and cred-&gt;subscribers and then
compares them to make sure the number of processes subscribed to a cred struct
never exceeds the refcount of that cred struct.

The problem is that this can cause a race with both copy_creds() and
exit_creds() as the two counters, whilst they are of atomic_t type, are only
atomic with respect to themselves, and not atomic with respect to each other.

This means that if creds_are_invalid() can read the values on one CPU whilst
they're being modified on another CPU, and so can observe an evolving state in
which the subscribers count now is greater than the usage count a moment
before.

Switching the order in which the counts are read cannot help, so the thing to
do is to remove that particular check.

I had considered rechecking the values to see if they're in flux if the test
fails, but I can't guarantee they won't appear the same, even if they've
changed several times in the meantime.

Note that this can only happen if CONFIG_DEBUG_CREDENTIALS is enabled.

The problem is only likely to occur with multithreaded programs, and can be
tested by the tst-eintr1 program from glibc's "make check".  The symptoms look
like:

	CRED: Invalid credentials
	CRED: At include/linux/cred.h:240
	CRED: Specified credentials: ffff88003dda5878 [real][eff]
	CRED: -&gt;magic=43736564, put_addr=(null)
	CRED: -&gt;usage=766, subscr=766
	CRED: -&gt;*uid = { 0,0,0,0 }
	CRED: -&gt;*gid = { 0,0,0,0 }
	CRED: -&gt;security is ffff88003d72f538
	CRED: -&gt;security {359, 359}
	------------[ cut here ]------------
	kernel BUG at kernel/cred.c:850!
	...
	RIP: 0010:[&lt;ffffffff81049889&gt;]  [&lt;ffffffff81049889&gt;] __invalid_creds+0x4e/0x52
	...
	Call Trace:
	 [&lt;ffffffff8104a37b&gt;] copy_creds+0x6b/0x23f

Note the -&gt;usage=766 and subscr=766.  The values appear the same because
they've been re-read since the check was made.

Reported-by: Roland McGrath &lt;roland@redhat.com&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: James Morris &lt;jmorris@namei.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;

</pre>
</div>
</content>
</entry>
<entry>
<title>kernel/cred.c: use kmem_cache_free</title>
<updated>2010-02-09T12:51:01+00:00</updated>
<author>
<name>Julia Lawall</name>
<email>julia@diku.dk</email>
</author>
<published>2010-02-02T22:31:36+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=e06fbe9a4092960a1db1fa973c9ec13a3ddce3f9'/>
<id>e06fbe9a4092960a1db1fa973c9ec13a3ddce3f9</id>
<content type='text'>
commit b8a1d37c5f981cdd2e83c9fd98198832324cd57a upstream.

Free memory allocated using kmem_cache_zalloc using kmem_cache_free rather
than kfree.

The semantic patch that makes this change is as follows:
(http://coccinelle.lip6.fr/)

// &lt;smpl&gt;
@@
expression x,E,c;
@@

 x = \(kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache_alloc_node\)(c,...)
 ... when != x = E
     when != &amp;x
?-kfree(x)
+kmem_cache_free(c,x)
// &lt;/smpl&gt;

Signed-off-by: Julia Lawall &lt;julia@diku.dk&gt;
Acked-by: David Howells &lt;dhowells@redhat.com&gt;
Cc: James Morris &lt;jmorris@namei.org&gt;
Cc: Steve Dickson &lt;steved@redhat.com&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: James Morris &lt;jmorris@namei.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;

</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
commit b8a1d37c5f981cdd2e83c9fd98198832324cd57a upstream.

Free memory allocated using kmem_cache_zalloc using kmem_cache_free rather
than kfree.

The semantic patch that makes this change is as follows:
(http://coccinelle.lip6.fr/)

// &lt;smpl&gt;
@@
expression x,E,c;
@@

 x = \(kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache_alloc_node\)(c,...)
 ... when != x = E
     when != &amp;x
?-kfree(x)
+kmem_cache_free(c,x)
// &lt;/smpl&gt;

Signed-off-by: Julia Lawall &lt;julia@diku.dk&gt;
Acked-by: David Howells &lt;dhowells@redhat.com&gt;
Cc: James Morris &lt;jmorris@namei.org&gt;
Cc: Steve Dickson &lt;steved@redhat.com&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: James Morris &lt;jmorris@namei.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@suse.de&gt;

</pre>
</div>
</content>
</entry>
<entry>
<title>creds_are_invalid() needs to be exported for use by modules:</title>
<updated>2009-09-23T18:02:26+00:00</updated>
<author>
<name>Randy Dunlap</name>
<email>randy.dunlap@oracle.com</email>
</author>
<published>2009-09-18T18:06:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=764db03fee50f7a3de91de80ef4a943f0d720801'/>
<id>764db03fee50f7a3de91de80ef4a943f0d720801</id>
<content type='text'>
ERROR: "creds_are_invalid" [fs/cachefiles/cachefiles.ko] undefined!

Signed-off-by: Randy Dunlap &lt;randy.dunlap@oracle.com&gt;
Cc: David Howells &lt;dhowells@redhat.com&gt;
Cc: James Morris &lt;jmorris@namei.org&gt;
Cc: Serge Hallyn &lt;serue@us.ibm.com&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: James Morris &lt;jmorris@namei.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
ERROR: "creds_are_invalid" [fs/cachefiles/cachefiles.ko] undefined!

Signed-off-by: Randy Dunlap &lt;randy.dunlap@oracle.com&gt;
Cc: David Howells &lt;dhowells@redhat.com&gt;
Cc: James Morris &lt;jmorris@namei.org&gt;
Cc: Serge Hallyn &lt;serue@us.ibm.com&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: James Morris &lt;jmorris@namei.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>include/linux/cred.h: fix build</title>
<updated>2009-09-23T18:01:25+00:00</updated>
<author>
<name>Andrew Morton</name>
<email>akpm@linux-foundation.org</email>
</author>
<published>2009-09-18T00:47:12+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=74908a0009eb36054190ab80deb9671014efed96'/>
<id>74908a0009eb36054190ab80deb9671014efed96</id>
<content type='text'>
mips allmodconfig:

include/linux/cred.h: In function `creds_are_invalid':
include/linux/cred.h:187: error: `PAGE_SIZE' undeclared (first use in this function)
include/linux/cred.h:187: error: (Each undeclared identifier is reported only once
include/linux/cred.h:187: error: for each function it appears in.)

Fixes

commit b6dff3ec5e116e3af6f537d4caedcad6b9e5082a
Author:     David Howells &lt;dhowells@redhat.com&gt;
AuthorDate: Fri Nov 14 10:39:16 2008 +1100
Commit:     James Morris &lt;jmorris@namei.org&gt;
CommitDate: Fri Nov 14 10:39:16 2008 +1100

    CRED: Separate task security context from task_struct

I think.

It's way too large to be inlined anyway.

Dunno if this needs an EXPORT_SYMBOL() yet.

Cc: David Howells &lt;dhowells@redhat.com&gt;
Cc: James Morris &lt;jmorris@namei.org&gt;
Cc: Serge Hallyn &lt;serue@us.ibm.com&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Acked-by: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: James Morris &lt;jmorris@namei.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
mips allmodconfig:

include/linux/cred.h: In function `creds_are_invalid':
include/linux/cred.h:187: error: `PAGE_SIZE' undeclared (first use in this function)
include/linux/cred.h:187: error: (Each undeclared identifier is reported only once
include/linux/cred.h:187: error: for each function it appears in.)

Fixes

commit b6dff3ec5e116e3af6f537d4caedcad6b9e5082a
Author:     David Howells &lt;dhowells@redhat.com&gt;
AuthorDate: Fri Nov 14 10:39:16 2008 +1100
Commit:     James Morris &lt;jmorris@namei.org&gt;
CommitDate: Fri Nov 14 10:39:16 2008 +1100

    CRED: Separate task security context from task_struct

I think.

It's way too large to be inlined anyway.

Dunno if this needs an EXPORT_SYMBOL() yet.

Cc: David Howells &lt;dhowells@redhat.com&gt;
Cc: James Morris &lt;jmorris@namei.org&gt;
Cc: Serge Hallyn &lt;serue@us.ibm.com&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Acked-by: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: James Morris &lt;jmorris@namei.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>CRED: Allow put_cred() to cope with a NULL groups list</title>
<updated>2009-09-14T23:10:57+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2009-09-14T11:45:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=4a5d6ba1914d1bf1fcfb5e15834c29d84a879219'/>
<id>4a5d6ba1914d1bf1fcfb5e15834c29d84a879219</id>
<content type='text'>
put_cred() will oops if given a NULL groups list, but that is now possible with
the existence of cred_alloc_blank(), as used in keyctl_session_to_parent().

Added in commit:

	commit ee18d64c1f632043a02e6f5ba5e045bb26a5465f
	Author: David Howells &lt;dhowells@redhat.com&gt;
	Date:   Wed Sep 2 09:14:21 2009 +0100
	KEYS: Add a keyctl to install a process's session keyring on its parent [try #6]

Reported-by: Marc Dionne &lt;marc.c.dionne@gmail.com&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: James Morris &lt;jmorris@namei.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
put_cred() will oops if given a NULL groups list, but that is now possible with
the existence of cred_alloc_blank(), as used in keyctl_session_to_parent().

Added in commit:

	commit ee18d64c1f632043a02e6f5ba5e045bb26a5465f
	Author: David Howells &lt;dhowells@redhat.com&gt;
	Date:   Wed Sep 2 09:14:21 2009 +0100
	KEYS: Add a keyctl to install a process's session keyring on its parent [try #6]

Reported-by: Marc Dionne &lt;marc.c.dionne@gmail.com&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: James Morris &lt;jmorris@namei.org&gt;
</pre>
</div>
</content>
</entry>
</feed>
