<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux-toradex.git/security/keys, branch v3.14.3</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>KEYS: Make the keyring cycle detector ignore other keyrings of the same name</title>
<updated>2014-03-10T01:57:18+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2014-03-09T08:21:58+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=979e0d74651ba5aa533277f2a6423d0f982fb6f6'/>
<id>979e0d74651ba5aa533277f2a6423d0f982fb6f6</id>
<content type='text'>
This fixes CVE-2014-0102.

The following command sequence produces an oops:

	keyctl new_session
	i=`keyctl newring _ses @s`
	keyctl link @s $i

The problem is that search_nested_keyrings() sees two keyrings that have
matching type and description, so keyring_compare_object() returns true.
s_n_k() then passes the key to the iterator function -
keyring_detect_cycle_iterator() - which *should* check to see whether this is
the keyring of interest, not just one with the same name.

Because assoc_array_find() will return one and only one match, I assumed that
the iterator function would only see an exact match or never be called - but
the iterator isn't only called from assoc_array_find()...

The oops looks something like this:

	kernel BUG at /data/fs/linux-2.6-fscache/security/keys/keyring.c:1003!
	invalid opcode: 0000 [#1] SMP
	...
	RIP: keyring_detect_cycle_iterator+0xe/0x1f
	...
	Call Trace:
	  search_nested_keyrings+0x76/0x2aa
	  __key_link_check_live_key+0x50/0x5f
	  key_link+0x4e/0x85
	  keyctl_keyring_link+0x60/0x81
	  SyS_keyctl+0x65/0xe4
	  tracesys+0xdd/0xe2

The fix is to make keyring_detect_cycle_iterator() check that the key it
has is the key it was actually looking for rather than calling BUG_ON().

A testcase has been included in the keyutils testsuite for this:

	http://git.kernel.org/cgit/linux/kernel/git/dhowells/keyutils.git/commit/?id=891f3365d07f1996778ade0e3428f01878a1790b

Reported-by: Tommi Rantala &lt;tt.rantala@gmail.com&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Acked-by: James Morris &lt;james.l.morris@oracle.com&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This fixes CVE-2014-0102.

The following command sequence produces an oops:

	keyctl new_session
	i=`keyctl newring _ses @s`
	keyctl link @s $i

The problem is that search_nested_keyrings() sees two keyrings that have
matching type and description, so keyring_compare_object() returns true.
s_n_k() then passes the key to the iterator function -
keyring_detect_cycle_iterator() - which *should* check to see whether this is
the keyring of interest, not just one with the same name.

Because assoc_array_find() will return one and only one match, I assumed that
the iterator function would only see an exact match or never be called - but
the iterator isn't only called from assoc_array_find()...

The oops looks something like this:

	kernel BUG at /data/fs/linux-2.6-fscache/security/keys/keyring.c:1003!
	invalid opcode: 0000 [#1] SMP
	...
	RIP: keyring_detect_cycle_iterator+0xe/0x1f
	...
	Call Trace:
	  search_nested_keyrings+0x76/0x2aa
	  __key_link_check_live_key+0x50/0x5f
	  key_link+0x4e/0x85
	  keyctl_keyring_link+0x60/0x81
	  SyS_keyctl+0x65/0xe4
	  tracesys+0xdd/0xe2

The fix is to make keyring_detect_cycle_iterator() check that the key it
has is the key it was actually looking for rather than calling BUG_ON().

A testcase has been included in the keyutils testsuite for this:

	http://git.kernel.org/cgit/linux/kernel/git/dhowells/keyutils.git/commit/?id=891f3365d07f1996778ade0e3428f01878a1790b

Reported-by: Tommi Rantala &lt;tt.rantala@gmail.com&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Acked-by: James Morris &lt;james.l.morris@oracle.com&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>security: shmem: implement kernel private shmem inodes</title>
<updated>2013-12-02T11:24:19+00:00</updated>
<author>
<name>Eric Paris</name>
<email>eparis@redhat.com</email>
</author>
<published>2013-12-02T11:24:19+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=c7277090927a5e71871e799a355ed2940f6c8fc6'/>
<id>c7277090927a5e71871e799a355ed2940f6c8fc6</id>
<content type='text'>
We have a problem where the big_key key storage implementation uses a
shmem backed inode to hold the key contents.  Because of this detail of
implementation LSM checks are being done between processes trying to
read the keys and the tmpfs backed inode.  The LSM checks are already
being handled on the key interface level and should not be enforced at
the inode level (since the inode is an implementation detail, not a
part of the security model)

This patch implements a new function shmem_kernel_file_setup() which
returns the equivalent to shmem_file_setup() only the underlying inode
has S_PRIVATE set.  This means that all LSM checks for the inode in
question are skipped.  It should only be used for kernel internal
operations where the inode is not exposed to userspace without proper
LSM checking.  It is possible that some other users of
shmem_file_setup() should use the new interface, but this has not been
explored.

Reproducing this bug is a little bit difficult.  The steps I used on
Fedora are:

 (1) Turn off selinux enforcing:

	setenforce 0

 (2) Create a huge key

	k=`dd if=/dev/zero bs=8192 count=1 | keyctl padd big_key test-key @s`

 (3) Access the key in another context:

	runcon system_u:system_r:httpd_t:s0-s0:c0.c1023 keyctl print $k &gt;/dev/null

 (4) Examine the audit logs:

	ausearch -m AVC -i --subject httpd_t | audit2allow

If the last command's output includes a line that looks like:

	allow httpd_t user_tmpfs_t:file { open read };

There was an inode check between httpd and the tmpfs filesystem.  With
this patch no such denial will be seen.  (NOTE! you should clear your
audit log if you have tested for this previously)

(Please return you box to enforcing)

Signed-off-by: Eric Paris &lt;eparis@redhat.com&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
cc: Hugh Dickins &lt;hughd@google.com&gt;
cc: linux-mm@kvack.org
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We have a problem where the big_key key storage implementation uses a
shmem backed inode to hold the key contents.  Because of this detail of
implementation LSM checks are being done between processes trying to
read the keys and the tmpfs backed inode.  The LSM checks are already
being handled on the key interface level and should not be enforced at
the inode level (since the inode is an implementation detail, not a
part of the security model)

This patch implements a new function shmem_kernel_file_setup() which
returns the equivalent to shmem_file_setup() only the underlying inode
has S_PRIVATE set.  This means that all LSM checks for the inode in
question are skipped.  It should only be used for kernel internal
operations where the inode is not exposed to userspace without proper
LSM checking.  It is possible that some other users of
shmem_file_setup() should use the new interface, but this has not been
explored.

Reproducing this bug is a little bit difficult.  The steps I used on
Fedora are:

 (1) Turn off selinux enforcing:

	setenforce 0

 (2) Create a huge key

	k=`dd if=/dev/zero bs=8192 count=1 | keyctl padd big_key test-key @s`

 (3) Access the key in another context:

	runcon system_u:system_r:httpd_t:s0-s0:c0.c1023 keyctl print $k &gt;/dev/null

 (4) Examine the audit logs:

	ausearch -m AVC -i --subject httpd_t | audit2allow

If the last command's output includes a line that looks like:

	allow httpd_t user_tmpfs_t:file { open read };

There was an inode check between httpd and the tmpfs filesystem.  With
this patch no such denial will be seen.  (NOTE! you should clear your
audit log if you have tested for this previously)

(Please return you box to enforcing)

Signed-off-by: Eric Paris &lt;eparis@redhat.com&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
cc: Hugh Dickins &lt;hughd@google.com&gt;
cc: linux-mm@kvack.org
</pre>
</div>
</content>
</entry>
<entry>
<title>KEYS: Fix searching of nested keyrings</title>
<updated>2013-12-02T11:24:19+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2013-12-02T11:24:19+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=9c5e45df215b4788f7a41c983ce862d08a083c2d'/>
<id>9c5e45df215b4788f7a41c983ce862d08a083c2d</id>
<content type='text'>
If a keyring contains more than 16 keyrings (the capacity of a single node in
the associative array) then those keyrings are split over multiple nodes
arranged as a tree.

If search_nested_keyrings() is called to search the keyring then it will
attempt to manually walk over just the 0 branch of the associative array tree
where all the keyring links are stored.  This works provided the key is found
before the algorithm steps from one node containing keyrings to a child node
or if there are sufficiently few keyring links that the keyrings are all in
one node.

However, if the algorithm does need to step from a node to a child node, it
doesn't change the node pointer unless a shortcut also gets transited.  This
means that the algorithm will keep scanning the same node over and over again
without terminating and without returning.

To fix this, move the internal-pointer-to-node translation from inside the
shortcut transit handler so that it applies it to node arrival as well.

This can be tested by:

	r=`keyctl newring sandbox @s`
	for ((i=0; i&lt;=16; i++)); do keyctl newring ring$i $r; done
	for ((i=0; i&lt;=16; i++)); do keyctl add user a$i a %:ring$i; done
	for ((i=0; i&lt;=16; i++)); do keyctl search $r user a$i; done
	for ((i=17; i&lt;=20; i++)); do keyctl search $r user a$i; done

The searches should all complete successfully (or with an error for 17-20),
but instead one or more of them will hang.

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Tested-by: Stephen Gallagher &lt;sgallagh@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
If a keyring contains more than 16 keyrings (the capacity of a single node in
the associative array) then those keyrings are split over multiple nodes
arranged as a tree.

If search_nested_keyrings() is called to search the keyring then it will
attempt to manually walk over just the 0 branch of the associative array tree
where all the keyring links are stored.  This works provided the key is found
before the algorithm steps from one node containing keyrings to a child node
or if there are sufficiently few keyring links that the keyrings are all in
one node.

However, if the algorithm does need to step from a node to a child node, it
doesn't change the node pointer unless a shortcut also gets transited.  This
means that the algorithm will keep scanning the same node over and over again
without terminating and without returning.

To fix this, move the internal-pointer-to-node translation from inside the
shortcut transit handler so that it applies it to node arrival as well.

This can be tested by:

	r=`keyctl newring sandbox @s`
	for ((i=0; i&lt;=16; i++)); do keyctl newring ring$i $r; done
	for ((i=0; i&lt;=16; i++)); do keyctl add user a$i a %:ring$i; done
	for ((i=0; i&lt;=16; i++)); do keyctl search $r user a$i; done
	for ((i=17; i&lt;=20; i++)); do keyctl search $r user a$i; done

The searches should all complete successfully (or with an error for 17-20),
but instead one or more of them will hang.

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Tested-by: Stephen Gallagher &lt;sgallagh@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>KEYS: Fix multiple key add into associative array</title>
<updated>2013-12-02T11:24:18+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2013-12-02T11:24:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=23fd78d76415729b338ff1802a0066b4a62f7fb8'/>
<id>23fd78d76415729b338ff1802a0066b4a62f7fb8</id>
<content type='text'>
If sufficient keys (or keyrings) are added into a keyring such that a node in
the associative array's tree overflows (each node has a capacity N, currently
16) and such that all N+1 keys have the same index key segment for that level
of the tree (the level'th nibble of the index key), then assoc_array_insert()
calls ops-&gt;diff_objects() to indicate at which bit position the two index keys
vary.

However, __key_link_begin() passes a NULL object to assoc_array_insert() with
the intention of supplying the correct pointer later before we commit the
change.  This means that keyring_diff_objects() is given a NULL pointer as one
of its arguments which it does not expect.  This results in an oops like the
attached.

With the previous patch to fix the keyring hash function, this can be forced
much more easily by creating a keyring and only adding keyrings to it.  Add any
other sort of key and a different insertion path is taken - all 16+1 objects
must want to cluster in the same node slot.

This can be tested by:

	r=`keyctl newring sandbox @s`
	for ((i=0; i&lt;=16; i++)); do keyctl newring ring$i $r; done

This should work fine, but oopses when the 17th keyring is added.

Since ops-&gt;diff_objects() is always called with the first pointer pointing to
the object to be inserted (ie. the NULL pointer), we can fix the problem by
changing the to-be-inserted object pointer to point to the index key passed
into assoc_array_insert() instead.

Whilst we're at it, we also switch the arguments so that they are the same as
for -&gt;compare_object().

BUG: unable to handle kernel NULL pointer dereference at 0000000000000088
IP: [&lt;ffffffff81191ee4&gt;] hash_key_type_and_desc+0x18/0xb0
...
RIP: 0010:[&lt;ffffffff81191ee4&gt;] hash_key_type_and_desc+0x18/0xb0
...
Call Trace:
 [&lt;ffffffff81191f9d&gt;] keyring_diff_objects+0x21/0xd2
 [&lt;ffffffff811f09ef&gt;] assoc_array_insert+0x3b6/0x908
 [&lt;ffffffff811929a7&gt;] __key_link_begin+0x78/0xe5
 [&lt;ffffffff81191a2e&gt;] key_create_or_update+0x17d/0x36a
 [&lt;ffffffff81192e0a&gt;] SyS_add_key+0x123/0x183
 [&lt;ffffffff81400ddb&gt;] tracesys+0xdd/0xe2

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Tested-by: Stephen Gallagher &lt;sgallagh@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
If sufficient keys (or keyrings) are added into a keyring such that a node in
the associative array's tree overflows (each node has a capacity N, currently
16) and such that all N+1 keys have the same index key segment for that level
of the tree (the level'th nibble of the index key), then assoc_array_insert()
calls ops-&gt;diff_objects() to indicate at which bit position the two index keys
vary.

However, __key_link_begin() passes a NULL object to assoc_array_insert() with
the intention of supplying the correct pointer later before we commit the
change.  This means that keyring_diff_objects() is given a NULL pointer as one
of its arguments which it does not expect.  This results in an oops like the
attached.

With the previous patch to fix the keyring hash function, this can be forced
much more easily by creating a keyring and only adding keyrings to it.  Add any
other sort of key and a different insertion path is taken - all 16+1 objects
must want to cluster in the same node slot.

This can be tested by:

	r=`keyctl newring sandbox @s`
	for ((i=0; i&lt;=16; i++)); do keyctl newring ring$i $r; done

This should work fine, but oopses when the 17th keyring is added.

Since ops-&gt;diff_objects() is always called with the first pointer pointing to
the object to be inserted (ie. the NULL pointer), we can fix the problem by
changing the to-be-inserted object pointer to point to the index key passed
into assoc_array_insert() instead.

Whilst we're at it, we also switch the arguments so that they are the same as
for -&gt;compare_object().

BUG: unable to handle kernel NULL pointer dereference at 0000000000000088
IP: [&lt;ffffffff81191ee4&gt;] hash_key_type_and_desc+0x18/0xb0
...
RIP: 0010:[&lt;ffffffff81191ee4&gt;] hash_key_type_and_desc+0x18/0xb0
...
Call Trace:
 [&lt;ffffffff81191f9d&gt;] keyring_diff_objects+0x21/0xd2
 [&lt;ffffffff811f09ef&gt;] assoc_array_insert+0x3b6/0x908
 [&lt;ffffffff811929a7&gt;] __key_link_begin+0x78/0xe5
 [&lt;ffffffff81191a2e&gt;] key_create_or_update+0x17d/0x36a
 [&lt;ffffffff81192e0a&gt;] SyS_add_key+0x123/0x183
 [&lt;ffffffff81400ddb&gt;] tracesys+0xdd/0xe2

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Tested-by: Stephen Gallagher &lt;sgallagh@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>KEYS: Fix the keyring hash function</title>
<updated>2013-12-02T11:24:18+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2013-12-02T11:24:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=d54e58b7f01552b0eb7d445f4b58de4499ad5ea6'/>
<id>d54e58b7f01552b0eb7d445f4b58de4499ad5ea6</id>
<content type='text'>
The keyring hash function (used by the associative array) is supposed to clear
the bottommost nibble of the index key (where the hash value resides) for
keyrings and make sure it is non-zero for non-keyrings.  This is done to make
keyrings cluster together on one branch of the tree separately to other keys.

Unfortunately, the wrong mask is used, so only the bottom two bits are
examined and cleared and not the whole bottom nibble.  This means that keys
and keyrings can still be successfully searched for under most circumstances
as the hash is consistent in its miscalculation, but if a keyring's
associative array bottom node gets filled up then approx 75% of the keyrings
will not be put into the 0 branch.

The consequence of this is that a key in a keyring linked to by another
keyring, ie.

	keyring A -&gt; keyring B -&gt; key

may not be found if the search starts at keyring A and then descends into
keyring B because search_nested_keyrings() only searches up the 0 branch (as it
"knows" all keyrings must be there and not elsewhere in the tree).

The fix is to use the right mask.

This can be tested with:

	r=`keyctl newring sandbox @s`
	for ((i=0; i&lt;=16; i++)); do keyctl newring ring$i $r; done
	for ((i=0; i&lt;=16; i++)); do keyctl add user a$i a %:ring$i; done
	for ((i=0; i&lt;=16; i++)); do keyctl search $r user a$i; done

This creates a sandbox keyring, then creates 17 keyrings therein (labelled
ring0..ring16).  This causes the root node of the sandbox's associative array
to overflow and for the tree to have extra nodes inserted.

Each keyring then is given a user key (labelled aN for ringN) for us to search
for.

We then search for the user keys we added, starting from the sandbox.  If
working correctly, it should return the same ordered list of key IDs as
for...keyctl add... did.  Without this patch, it reports ENOKEY "Required key
not available" for some of the keys.  Just which keys get this depends as the
kernel pointer to the key type forms part of the hash function.

Reported-by: Nalin Dahyabhai &lt;nalin@redhat.com&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Tested-by: Stephen Gallagher &lt;sgallagh@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The keyring hash function (used by the associative array) is supposed to clear
the bottommost nibble of the index key (where the hash value resides) for
keyrings and make sure it is non-zero for non-keyrings.  This is done to make
keyrings cluster together on one branch of the tree separately to other keys.

Unfortunately, the wrong mask is used, so only the bottom two bits are
examined and cleared and not the whole bottom nibble.  This means that keys
and keyrings can still be successfully searched for under most circumstances
as the hash is consistent in its miscalculation, but if a keyring's
associative array bottom node gets filled up then approx 75% of the keyrings
will not be put into the 0 branch.

The consequence of this is that a key in a keyring linked to by another
keyring, ie.

	keyring A -&gt; keyring B -&gt; key

may not be found if the search starts at keyring A and then descends into
keyring B because search_nested_keyrings() only searches up the 0 branch (as it
"knows" all keyrings must be there and not elsewhere in the tree).

The fix is to use the right mask.

This can be tested with:

	r=`keyctl newring sandbox @s`
	for ((i=0; i&lt;=16; i++)); do keyctl newring ring$i $r; done
	for ((i=0; i&lt;=16; i++)); do keyctl add user a$i a %:ring$i; done
	for ((i=0; i&lt;=16; i++)); do keyctl search $r user a$i; done

This creates a sandbox keyring, then creates 17 keyrings therein (labelled
ring0..ring16).  This causes the root node of the sandbox's associative array
to overflow and for the tree to have extra nodes inserted.

Each keyring then is given a user key (labelled aN for ringN) for us to search
for.

We then search for the user keys we added, starting from the sandbox.  If
working correctly, it should return the same ordered list of key IDs as
for...keyctl add... did.  Without this patch, it reports ENOKEY "Required key
not available" for some of the keys.  Just which keys get this depends as the
kernel pointer to the key type forms part of the hash function.

Reported-by: Nalin Dahyabhai &lt;nalin@redhat.com&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Tested-by: Stephen Gallagher &lt;sgallagh@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>KEYS: Pre-clear struct key on allocation</title>
<updated>2013-12-02T11:24:18+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2013-12-02T11:24:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=2480f57fb3023eb047c5f2d6dfefef41ab9b893c'/>
<id>2480f57fb3023eb047c5f2d6dfefef41ab9b893c</id>
<content type='text'>
The second word of key-&gt;payload does not get initialised in key_alloc(), but
the big_key type is relying on it having been cleared.  The problem comes when
big_key fails to instantiate a large key and doesn't then set the payload.  The
big_key_destroy() op is called from the garbage collector and this assumes that
the dentry pointer stored in the second word will be NULL if instantiation did
not complete.

Therefore just pre-clear the entire struct key on allocation rather than trying
to be clever and only initialising to 0 only those bits that aren't otherwise
initialised.

The lack of initialisation can lead to a bug report like the following if
big_key failed to initialise its file:

	general protection fault: 0000 [#1] SMP
	Modules linked in: ...
	CPU: 0 PID: 51 Comm: kworker/0:1 Not tainted 3.10.0-53.el7.x86_64 #1
	Hardware name: Dell Inc. PowerEdge 1955/0HC513, BIOS 1.4.4 12/09/2008
	Workqueue: events key_garbage_collector
	task: ffff8801294f5680 ti: ffff8801296e2000 task.ti: ffff8801296e2000
	RIP: 0010:[&lt;ffffffff811b4a51&gt;] dput+0x21/0x2d0
	...
	Call Trace:
	 [&lt;ffffffff811a7b06&gt;] path_put+0x16/0x30
	 [&lt;ffffffff81235604&gt;] big_key_destroy+0x44/0x60
	 [&lt;ffffffff8122dc4b&gt;] key_gc_unused_keys.constprop.2+0x5b/0xe0
	 [&lt;ffffffff8122df2f&gt;] key_garbage_collector+0x1df/0x3c0
	 [&lt;ffffffff8107759b&gt;] process_one_work+0x17b/0x460
	 [&lt;ffffffff8107834b&gt;] worker_thread+0x11b/0x400
	 [&lt;ffffffff81078230&gt;] ? rescuer_thread+0x3e0/0x3e0
	 [&lt;ffffffff8107eb00&gt;] kthread+0xc0/0xd0
	 [&lt;ffffffff8107ea40&gt;] ? kthread_create_on_node+0x110/0x110
	 [&lt;ffffffff815c4bec&gt;] ret_from_fork+0x7c/0xb0
	 [&lt;ffffffff8107ea40&gt;] ? kthread_create_on_node+0x110/0x110

Reported-by: Patrik Kis &lt;pkis@redhat.com&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Reviewed-by: Stephen Gallagher &lt;sgallagh@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The second word of key-&gt;payload does not get initialised in key_alloc(), but
the big_key type is relying on it having been cleared.  The problem comes when
big_key fails to instantiate a large key and doesn't then set the payload.  The
big_key_destroy() op is called from the garbage collector and this assumes that
the dentry pointer stored in the second word will be NULL if instantiation did
not complete.

Therefore just pre-clear the entire struct key on allocation rather than trying
to be clever and only initialising to 0 only those bits that aren't otherwise
initialised.

The lack of initialisation can lead to a bug report like the following if
big_key failed to initialise its file:

	general protection fault: 0000 [#1] SMP
	Modules linked in: ...
	CPU: 0 PID: 51 Comm: kworker/0:1 Not tainted 3.10.0-53.el7.x86_64 #1
	Hardware name: Dell Inc. PowerEdge 1955/0HC513, BIOS 1.4.4 12/09/2008
	Workqueue: events key_garbage_collector
	task: ffff8801294f5680 ti: ffff8801296e2000 task.ti: ffff8801296e2000
	RIP: 0010:[&lt;ffffffff811b4a51&gt;] dput+0x21/0x2d0
	...
	Call Trace:
	 [&lt;ffffffff811a7b06&gt;] path_put+0x16/0x30
	 [&lt;ffffffff81235604&gt;] big_key_destroy+0x44/0x60
	 [&lt;ffffffff8122dc4b&gt;] key_gc_unused_keys.constprop.2+0x5b/0xe0
	 [&lt;ffffffff8122df2f&gt;] key_garbage_collector+0x1df/0x3c0
	 [&lt;ffffffff8107759b&gt;] process_one_work+0x17b/0x460
	 [&lt;ffffffff8107834b&gt;] worker_thread+0x11b/0x400
	 [&lt;ffffffff81078230&gt;] ? rescuer_thread+0x3e0/0x3e0
	 [&lt;ffffffff8107eb00&gt;] kthread+0xc0/0xd0
	 [&lt;ffffffff8107ea40&gt;] ? kthread_create_on_node+0x110/0x110
	 [&lt;ffffffff815c4bec&gt;] ret_from_fork+0x7c/0xb0
	 [&lt;ffffffff8107ea40&gt;] ? kthread_create_on_node+0x110/0x110

Reported-by: Patrik Kis &lt;pkis@redhat.com&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Reviewed-by: Stephen Gallagher &lt;sgallagh@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>KEYS: Fix keyring content gc scanner</title>
<updated>2013-11-14T14:09:53+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2013-11-14T13:02:31+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=62fe318256befbd1b4a6765e71d9c997f768fe79'/>
<id>62fe318256befbd1b4a6765e71d9c997f768fe79</id>
<content type='text'>
Key pointers stored in the keyring are marked in bit 1 to indicate if they
point to a keyring.  We need to strip off this bit before using the pointer
when iterating over the keyring for the purpose of looking for links to garbage
collect.

This means that expirable keyrings aren't correctly expiring because the
checker is seeing their key pointer with 2 added to it.

Since the fix for this involves knowing about the internals of the keyring,
key_gc_keyring() is moved to keyring.c and merged into keyring_gc().

This can be tested by:

	echo 2 &gt;/proc/sys/kernel/keys/gc_delay
	keyctl timeout `keyctl add keyring qwerty "" @s` 2
	cat /proc/keys
	sleep 5; cat /proc/keys

which should see a keyring called "qwerty" appear in the session keyring and
then disappear after it expires, and:

	echo 2 &gt;/proc/sys/kernel/keys/gc_delay
	a=`keyctl get_persistent @s`
	b=`keyctl add keyring 0 "" $a`
	keyctl add user a a $b
	keyctl timeout $b 2
	cat /proc/keys
	sleep 5; cat /proc/keys

which should see a keyring called "0" with a key called "a" in it appear in the
user's persistent keyring (which will be attached to the session keyring) and
then both the "0" keyring and the "a" key should disappear when the "0" keyring
expires.

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Acked-by: Simo Sorce &lt;simo@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Key pointers stored in the keyring are marked in bit 1 to indicate if they
point to a keyring.  We need to strip off this bit before using the pointer
when iterating over the keyring for the purpose of looking for links to garbage
collect.

This means that expirable keyrings aren't correctly expiring because the
checker is seeing their key pointer with 2 added to it.

Since the fix for this involves knowing about the internals of the keyring,
key_gc_keyring() is moved to keyring.c and merged into keyring_gc().

This can be tested by:

	echo 2 &gt;/proc/sys/kernel/keys/gc_delay
	keyctl timeout `keyctl add keyring qwerty "" @s` 2
	cat /proc/keys
	sleep 5; cat /proc/keys

which should see a keyring called "qwerty" appear in the session keyring and
then disappear after it expires, and:

	echo 2 &gt;/proc/sys/kernel/keys/gc_delay
	a=`keyctl get_persistent @s`
	b=`keyctl add keyring 0 "" $a`
	keyctl add user a a $b
	keyctl timeout $b 2
	cat /proc/keys
	sleep 5; cat /proc/keys

which should see a keyring called "0" with a key called "a" in it appear in the
user's persistent keyring (which will be attached to the session keyring) and
then both the "0" keyring and the "a" key should disappear when the "0" keyring
expires.

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Acked-by: Simo Sorce &lt;simo@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>KEYS: Fix error handling in big_key instantiation</title>
<updated>2013-11-13T16:51:06+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2013-11-13T16:51:06+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=97826c821ec6724fc359d9b7840dc10af914c641'/>
<id>97826c821ec6724fc359d9b7840dc10af914c641</id>
<content type='text'>
In the big_key_instantiate() function we return 0 if kernel_write() returns us
an error rather than returning an error.  This can potentially lead to
dentry_open() giving a BUG when called from big_key_read() with an unset
tmpfile path.

	------------[ cut here ]------------
	kernel BUG at fs/open.c:798!
	...
	RIP: 0010:[&lt;ffffffff8119bbd1&gt;] dentry_open+0xd1/0xe0
	...
	Call Trace:
	 [&lt;ffffffff812350c5&gt;] big_key_read+0x55/0x100
	 [&lt;ffffffff81231084&gt;] keyctl_read_key+0xb4/0xe0
	 [&lt;ffffffff81231e58&gt;] SyS_keyctl+0xf8/0x1d0
	 [&lt;ffffffff815bb799&gt;] system_call_fastpath+0x16/0x1b


Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Reviewed-by: Stephen Gallagher &lt;sgallagh@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
In the big_key_instantiate() function we return 0 if kernel_write() returns us
an error rather than returning an error.  This can potentially lead to
dentry_open() giving a BUG when called from big_key_read() with an unset
tmpfile path.

	------------[ cut here ]------------
	kernel BUG at fs/open.c:798!
	...
	RIP: 0010:[&lt;ffffffff8119bbd1&gt;] dentry_open+0xd1/0xe0
	...
	Call Trace:
	 [&lt;ffffffff812350c5&gt;] big_key_read+0x55/0x100
	 [&lt;ffffffff81231084&gt;] keyctl_read_key+0xb4/0xe0
	 [&lt;ffffffff81231e58&gt;] SyS_keyctl+0xf8/0x1d0
	 [&lt;ffffffff815bb799&gt;] system_call_fastpath+0x16/0x1b


Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Reviewed-by: Stephen Gallagher &lt;sgallagh@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>KEYS: Fix UID check in keyctl_get_persistent()</title>
<updated>2013-11-06T14:01:51+00:00</updated>
<author>
<name>David Howells</name>
<email>dhowells@redhat.com</email>
</author>
<published>2013-11-06T14:01:51+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=fbf8c53f1a2ac7610ed124043600dc074992e71b'/>
<id>fbf8c53f1a2ac7610ed124043600dc074992e71b</id>
<content type='text'>
If the UID is specified by userspace when calling the KEYCTL_GET_PERSISTENT
function and the process does not have the CAP_SETUID capability, then the
function will return -EPERM if the current process's uid, suid, euid and fsuid
all match the requested UID.  This is incorrect.

Fix it such that when a non-privileged caller requests a persistent keyring by
a specific UID they can only request their own (ie. the specified UID matches
either then process's UID or the process's EUID).

This can be tested by logging in as the user and doing:

	keyctl get_persistent @p
	keyctl get_persistent @p `id -u`
	keyctl get_persistent @p 0

The first two should successfully print the same key ID.  The third should do
the same if called by UID 0 or indicate Operation Not Permitted otherwise.

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Acked-by: Stephen Gallagher &lt;sgallagh@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
If the UID is specified by userspace when calling the KEYCTL_GET_PERSISTENT
function and the process does not have the CAP_SETUID capability, then the
function will return -EPERM if the current process's uid, suid, euid and fsuid
all match the requested UID.  This is incorrect.

Fix it such that when a non-privileged caller requests a persistent keyring by
a specific UID they can only request their own (ie. the specified UID matches
either then process's UID or the process's EUID).

This can be tested by logging in as the user and doing:

	keyctl get_persistent @p
	keyctl get_persistent @p `id -u`
	keyctl get_persistent @p 0

The first two should successfully print the same key ID.  The third should do
the same if called by UID 0 or indicate Operation Not Permitted otherwise.

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Acked-by: Stephen Gallagher &lt;sgallagh@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>KEYS: fix error return code in big_key_instantiate()</title>
<updated>2013-10-30T12:54:29+00:00</updated>
<author>
<name>Wei Yongjun</name>
<email>yongjun_wei@trendmicro.com.cn</email>
</author>
<published>2013-10-30T03:23:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=d2b86970245b64652c4d7799e707dd8bd1533b64'/>
<id>d2b86970245b64652c4d7799e707dd8bd1533b64</id>
<content type='text'>
Fix to return a negative error code from the error handling
case instead of 0, as done elsewhere in this function.

Signed-off-by: Wei Yongjun &lt;yongjun_wei@trendmicro.com.cn&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Fix to return a negative error code from the error handling
case instead of 0, as done elsewhere in this function.

Signed-off-by: Wei Yongjun &lt;yongjun_wei@trendmicro.com.cn&gt;
Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
