When CacheFiles cache objects are in use, they have in-memory representations,
as defined by the cachefiles_object struct. These are kept in a tree rooted in
the cache and indexed by dentry pointer (since there's a unique mapping between
object index key and dentry).
Collisions can occur between a representation already in the tree and a new
representation being set up because it takes time to dispose of an old
representation - particularly if it must be unlinked or renamed.
When such a collision occurs, cachefiles_mark_object_active() is meant to check
to see if the old, already-present representation is in the process of being
discarded (ie. FSCACHE_OBJECT_IS_LIVE is not set on it) - and, if so, wait for
the representation to be removed (ie. CACHEFILES_OBJECT_ACTIVE is then
cleared).
However, the test for whether the old representation is still live is checking
the new object - which always will be live at this point. This leads to an
oops looking like:
CacheFiles: Error: Unexpected object collision
object: OBJ1b354
objstate=LOOK_UP_OBJECT fl=8 wbusy=2 ev=0[0]
ops=0 inp=0 exc=0
parent=ffff88053f5417c0
cookie=ffff880538f202a0 [pr=ffff8805381b7160 nd=ffff880509c6eb78 fl=27]
key=[8] '2490000000000000'
xobject: OBJ1a600
xobjstate=DROP_OBJECT fl=70 wbusy=2 ev=0[0]
xops=0 inp=0 exc=0
xparent=ffff88053f5417c0
xcookie=ffff88050f4cbf70 [pr=ffff8805381b7160 nd= (null) fl=12]
------------[ cut here ]------------
kernel BUG at fs/cachefiles/namei.c:200!
...
Workqueue: fscache_object fscache_object_work_func [fscache]
...
RIP: ... cachefiles_walk_to_object+0x7ea/0x860 [cachefiles]
...
Call Trace:
[<ffffffffa04dadd8>] ? cachefiles_lookup_object+0x58/0x100 [cachefiles]
[<ffffffffa01affe9>] ? fscache_look_up_object+0xb9/0x1d0 [fscache]
[<ffffffffa01afc4d>] ? fscache_parent_ready+0x2d/0x80 [fscache]
[<ffffffffa01b0672>] ? fscache_object_work_func+0x92/0x1f0 [fscache]
[<ffffffff8107e82b>] ? process_one_work+0x16b/0x400
[<ffffffff8107fc16>] ? worker_thread+0x116/0x380
[<ffffffff8107fb00>] ? manage_workers.isra.21+0x290/0x290
[<ffffffff81085edc>] ? kthread+0xbc/0xe0
[<ffffffff81085e20>] ? flush_kthread_worker+0x80/0x80
[<ffffffff81502d0c>] ? ret_from_fork+0x7c/0xb0
[<ffffffff81085e20>] ? flush_kthread_worker+0x80/0x80
Reported-by: Manuel Schölling <manuel.schoelling@gmx.de>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Steve Dickson <steved@redhat.com>
Module signing matches keys by comparing against the key description exactly.
However, the way the key description gets constructed got changed to be
composed of the subject name plus the certificate serial number instead of the
subject name and the subjectKeyId. I changed this to avoid problems with
certificates that don't *have* a subjectKeyId.
Instead, if available, use the raw subjectKeyId to form the key description
and only use the serial number if the subjectKeyId doesn't exist.
Reported-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
Signed-off-by: David Howells <dhowells@redhat.com>
If a cache object gets killed whilst in the process of being set up - for
instance if the netfs relinquishes the cookie that the object is associated
with - then the object's state machine will transit to the DROP_OBJECT state
without necessarily going through the LOOKUP_OBJECT or CREATE_OBJECT states.
This is a problem for CacheFiles because cachefiles_drop_object() assumes that
object->dentry will be set upon reaching the DROP_OBJECT state and has an
ASSERT() to that effect (see the oops below) - but object->dentry doesn't get
set until the LOOKUP_OBJECT or CREATE_OBJECT states (and not always then if
they fail).
To fix this, just make the dentry cleanup in cachefiles_drop_object()
conditional on the dentry actually being set and remove the assertion.
CacheFiles: Assertion failed
------------[ cut here ]------------
kernel BUG at .../fs/cachefiles/namei.c:425!
...
Workqueue: fscache_object fscache_object_work_func [fscache]
...
RIP: ... cachefiles_delete_object+0xcd/0x110 [cachefiles]
...
Call Trace:
[<ffffffffa043280f>] ? cachefiles_drop_object+0xff/0x130 [cachefiles]
[<ffffffffa02ac511>] ? fscache_drop_object+0xd1/0x1d0 [fscache]
[<ffffffffa02ac697>] ? fscache_object_work_func+0x87/0x210 [fscache]
[<ffffffff81080635>] ? process_one_work+0x155/0x450
[<ffffffff81081c44>] ? worker_thread+0x114/0x370
[<ffffffff81081b30>] ? manage_workers.isra.21+0x2c0/0x2c0
[<ffffffff81087fcc>] ? kthread+0xbc/0xe0
[<ffffffff81087f10>] ? flush_kthread_worker+0xa0/0xa0
[<ffffffff8150638c>] ? ret_from_fork+0x7c/0xb0
[<ffffffff81087f10>] ? flush_kthread_worker+0xa0/0xa0
Reported-by: Manuel Schölling <manuel.schoelling@gmx.de>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Steve Dickson <steved@redhat.com>
As it stands, the code to generate an asymmetric key ID prechecks the hex
string it is given whilst determining the length, before it allocates the
buffer for hex2bin() to translate into - which mean that checking the result of
hex2bin() is redundant.
Unfortunately, hex2bin() is marked as __must_check, which means that the
following warning may be generated if the return value isn't checked:
crypto/asymmetric_keys/asymmetric_type.c: In function
asymmetric_key_hex_to_key_id:
crypto/asymmetric_keys/asymmetric_type.c:110: warning: ignoring return
value of hex2bin, declared with attribute warn_unused_result
The warning can't be avoided by casting the result to void.
Instead, use strlen() to check the length of the string and ignore the fact
that the string might not be entirely valid hex until after the allocation has
been done - in which case we can use the result of hex2bin() for this.
Signed-off-by: David Howells <dhowells@redhat.com>
Not all filesystems now provide the rename i_op - ext4 for one - but rather
provide the rename2 i_op. CacheFiles checks that the filesystem has rename
and so will reject ext4 now with EPERM:
CacheFiles: Failed to register: -1
Fix this by checking for rename2 as an alternative. The call to vfs_rename()
actually handles selection of the appropriate function, so we needn't worry
about that.
Turning on debugging shows:
[cachef] ==> cachefiles_get_directory(,,cache)
[cachef] subdir -> ffff88000b22b778 positive
[cachef] <== cachefiles_get_directory() = -1 [check]
where -1 is EPERM.
Signed-off-by: David Howells <dhowells@redhat.com>
Changes for next to improve the matching of asymmetric keys and to improve the
handling of PKCS#7 certificates:
(1) Provide a method to preparse the data supplied for matching a key. This
permits they key type to extract out the bits it needs for matching once
only.
Further, the type of search (direct lookup or iterative) can be set and
the function used to actually check the match can be set by preparse
rather than being hard coded for the type.
(2) Improves asymmetric keys identification.
Keys derived from X.509 certs now get labelled with IDs derived from their
issuer and certificate number (required to match PKCS#7) and from their
SKID and subject (required to match X.509).
IDs are now binary and match criterion preparsing is provided so that
criteria can be turned into binary blobs to make matching faster.
(3) Improves PKCS#7 message handling to permit PKCS#7 messages without X.509
cert lists to be matched to trusted keys, thereby allowing minimally sized
PKCS#7 certs to be used.
(4) Improves PKCS#7 message handling to better handle certificate chains that
are broken due to unsupported crypto that can otherwise by used to
intersect a trust keyring.
These must go on top of the PKCS#7 parser cleanup fixes.
Signed-off-by: David Howells <dhowells@redhat.com>
The X.509 certificate list in a PKCS#7 message is optional. To save space, we
can omit the inclusion of any X.509 certificates if we are sure that we can
look the relevant public key up by the serial number and issuer given in a
signed info block.
This also supports use of a signed info block for which we can't find a
matching X.509 cert in the certificate list, though it be populated.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Provide better handling of unsupported crypto when verifying a PKCS#7 message.
If we can't bridge the gap between a pair of X.509 certs or between a signed
info block and an X.509 cert because it involves some crypto we don't support,
that's not necessarily the end of the world as there may be other ways points
at which we can intersect with a ring of trusted keys.
Instead, only produce ENOPKG immediately if all the signed info blocks in a
PKCS#7 message require unsupported crypto to bridge to the first X.509 cert.
Otherwise, we defer the generation of ENOPKG until we get ENOKEY during trust
validation.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Make use of the new match string preparsing to overhaul key identification
when searching for asymmetric keys. The following changes are made:
(1) Use the previously created asymmetric_key_id struct to hold the following
key IDs derived from the X.509 certificate or PKCS#7 message:
id: serial number + issuer
skid: subjKeyId + subject
authority: authKeyId + issuer
(2) Replace the hex fingerprint attached to key->type_data[1] with an
asymmetric_key_ids struct containing the id and the skid (if present).
(3) Make the asymmetric_type match data preparse select one of two searches:
(a) An iterative search for the key ID given if prefixed with "id:". The
prefix is expected to be followed by a hex string giving the ID to
search for. The criterion key ID is checked against all key IDs
recorded on the key.
(b) A direct search if the key ID is not prefixed with "id:". This will
look for an exact match on the key description.
(4) Make x509_request_asymmetric_key() take a key ID. This is then converted
into "id:<hex>" and passed into keyring_search() where match preparsing
will turn it back into a binary ID.
(5) X.509 certificate verification then takes the authority key ID and looks
up a key that matches it to find the public key for the certificate
signature.
(6) PKCS#7 certificate verification then takes the id key ID and looks up a
key that matches it to find the public key for the signed information
block signature.
Additional changes:
(1) Multiple subjKeyId and authKeyId values on an X.509 certificate cause the
cert to be rejected with -EBADMSG.
(2) The 'fingerprint' ID is gone. This was primarily intended to convey PGP
public key fingerprints. If PGP is supported in future, this should
generate a key ID that carries the fingerprint.
(3) Th ca_keyid= kernel command line option is now converted to a key ID and
used to match the authority key ID. Possibly this should only match the
actual authKeyId part and not the issuer as well.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Implement the first step in using binary key IDs for asymmetric keys rather
than hex string keys.
The previously added match data preparsing will be able to convert hex
criterion strings into binary which can then be compared more rapidly.
Further, we actually want more then one ID string per public key. The problem
is that X.509 certs refer to other X.509 certs by matching Issuer + AuthKeyId
to Subject + SubjKeyId, but PKCS#7 messages match against X.509 Issuer +
SerialNumber.
This patch just provides facilities for a later patch to make use of.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Make the key matching functions pointed to by key_match_data::cmp return bool
rather than int.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
A previous patch added a ->match_preparse() method to the key type. This is
allowed to override the function called by the iteration algorithm.
Therefore, we can just set a default that simply checks for an exact match of
the key description with the original criterion data and allow match_preparse
to override it as needed.
The key_type::match op is then redundant and can be removed, as can the
user_match() function.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Remove key_type::def_lookup_type as it's no longer used. The information now
defaults to KEYRING_SEARCH_LOOKUP_DIRECT but may be overridden by
type->match_preparse().
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Preparse the match data. This provides several advantages:
(1) The preparser can reject invalid criteria up front.
(2) The preparser can convert the criteria to binary data if necessary (the
asymmetric key type really wants to do binary comparison of the key IDs).
(3) The preparser can set the type of search to be performed. This means
that it's not then a one-off setting in the key type.
(4) The preparser can set an appropriate comparator function.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Provide a function to convert a buffer of binary data into an unterminated
ascii hex string representation of that data.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Merge in keyrings fixes, at least some of which later patches depend on:
(1) Reinstate the production of EPERM for key types beginning with '.' in
requests from userspace.
(2) Tidy up the cleanup of PKCS#7 message signed information blocks and fix a
bug this made more obvious.
Signed-off-by: David Howells <dhowells@redhat.coM>
Fix the parser cleanup code to drain parsed out X.509 certs in the case that
the decode fails and we jump to error_decode.
The function is rearranged so that the same cleanup code is used in the success
case as the error case - just that the message descriptor under construction is
only released if it is still pointed to by the context struct at that point.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
The code to free a signed info block is repeated several times, so move the
code to do it into a function of its own. This gives us a place to add clean
ups for stuff that gets added to pkcs7_signed_info.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Reinstate the generation of EPERM for a key type name beginning with a '.' in
a userspace call. Types whose name begins with a '.' are internal only.
The test was removed by:
commit a4e3b8d79a
Author: Mimi Zohar <zohar@linux.vnet.ibm.com>
Date: Thu May 22 14:02:23 2014 -0400
Subject: KEYS: special dot prefixed keyring name bug fix
I think we want to keep the restriction on type name so that userspace can't
add keys of a special internal type.
Note that removal of the test causes several of the tests in the keyutils
testsuite to fail.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
cc: Mimi Zohar <zohar@linux.vnet.ibm.com>
This fixes CVE-2014-3631.
It is possible for an associative array to end up with a shortcut node at the
root of the tree if there are more than fan-out leaves in the tree, but they
all crowd into the same slot in the lowest level (ie. they all have the same
first nibble of their index keys).
When assoc_array_gc() returns back up the tree after scanning some leaves, it
can fall off of the root and crash because it assumes that the back pointer
from a shortcut (after label ascend_old_tree) must point to a normal node -
which isn't true of a shortcut node at the root.
Should we find we're ascending rootwards over a shortcut, we should check to
see if the backpointer is zero - and if it is, we have completed the scan.
This particular bug cannot occur if the root node is not a shortcut - ie. if
you have fewer than 17 keys in a keyring or if you have at least two keys that
sit into separate slots (eg. a keyring and a non keyring).
This can be reproduced by:
ring=`keyctl newring bar @s`
for ((i=1; i<=18; i++)); do last_key=`keyctl newring foo$i $ring`; done
keyctl timeout $last_key 2
Doing this:
echo 3 >/proc/sys/kernel/keys/gc_delay
first will speed things up.
If we do fall off of the top of the tree, we get the following oops:
BUG: unable to handle kernel NULL pointer dereference at 0000000000000018
IP: [<ffffffff8136cea7>] assoc_array_gc+0x2f7/0x540
PGD dae15067 PUD cfc24067 PMD 0
Oops: 0000 [#1] SMP
Modules linked in: xt_nat xt_mark nf_conntrack_netbios_ns nf_conntrack_broadcast ip6t_rpfilter ip6t_REJECT xt_conntrack ebtable_nat ebtable_broute bridge stp llc ebtable_filter ebtables ip6table_ni
CPU: 0 PID: 26011 Comm: kworker/0:1 Not tainted 3.14.9-200.fc20.x86_64 #1
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
Workqueue: events key_garbage_collector
task: ffff8800918bd580 ti: ffff8800aac14000 task.ti: ffff8800aac14000
RIP: 0010:[<ffffffff8136cea7>] [<ffffffff8136cea7>] assoc_array_gc+0x2f7/0x540
RSP: 0018:ffff8800aac15d40 EFLAGS: 00010206
RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff8800aaecacc0
RDX: ffff8800daecf440 RSI: 0000000000000001 RDI: ffff8800aadc2bc0
RBP: ffff8800aac15da8 R08: 0000000000000001 R09: 0000000000000003
R10: ffffffff8136ccc7 R11: 0000000000000000 R12: 0000000000000000
R13: 0000000000000000 R14: 0000000000000070 R15: 0000000000000001
FS: 0000000000000000(0000) GS:ffff88011fc00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000018 CR3: 00000000db10d000 CR4: 00000000000006f0
Stack:
ffff8800aac15d50 0000000000000011 ffff8800aac15db8 ffffffff812e2a70
ffff880091a00600 0000000000000000 ffff8800aadc2bc3 00000000cd42c987
ffff88003702df20 ffff88003702dfa0 0000000053b65c09 ffff8800aac15fd8
Call Trace:
[<ffffffff812e2a70>] ? keyring_detect_cycle_iterator+0x30/0x30
[<ffffffff812e3e75>] keyring_gc+0x75/0x80
[<ffffffff812e1424>] key_garbage_collector+0x154/0x3c0
[<ffffffff810a67b6>] process_one_work+0x176/0x430
[<ffffffff810a744b>] worker_thread+0x11b/0x3a0
[<ffffffff810a7330>] ? rescuer_thread+0x3b0/0x3b0
[<ffffffff810ae1a8>] kthread+0xd8/0xf0
[<ffffffff810ae0d0>] ? insert_kthread_work+0x40/0x40
[<ffffffff816ffb7c>] ret_from_fork+0x7c/0xb0
[<ffffffff810ae0d0>] ? insert_kthread_work+0x40/0x40
Code: 08 4c 8b 22 0f 84 bf 00 00 00 41 83 c7 01 49 83 e4 fc 41 83 ff 0f 4c 89 65 c0 0f 8f 5a fe ff ff 48 8b 45 c0 4d 63 cf 49 83 c1 02 <4e> 8b 34 c8 4d 85 f6 0f 84 be 00 00 00 41 f6 c6 01 0f 84 92
RIP [<ffffffff8136cea7>] assoc_array_gc+0x2f7/0x540
RSP <ffff8800aac15d40>
CR2: 0000000000000018
---[ end trace 1129028a088c0cbd ]---
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Don Zickus <dzickus@redhat.com>
Signed-off-by: James Morris <james.l.morris@oracle.com>
Fix a missing __user annotation in a cast of a user space pointer (found by
checker).
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Printing in base signature handling should have a prefix, so set pr_fmt().
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: James Morris <james.l.morris@oracle.com>
Relax the check on the length of the PKCS#7 cert as it appears that the PE
file wrapper size gets rounded up to the nearest 8.
The debugging output looks like this:
PEFILE: ==> verify_pefile_signature()
PEFILE: ==> pefile_parse_binary()
PEFILE: checksum @ 110
PEFILE: header size = 200
PEFILE: cert = 968 @547be0 [68 09 00 00 00 02 02 00 30 82 09 56 ]
PEFILE: sig wrapper = { 968, 200, 2 }
PEFILE: Signature data not PKCS#7
The wrapper is the first 8 bytes of the hex dump inside []. This indicates a
length of 0x968 bytes, including the wrapper header - so 0x960 bytes of
payload.
The ASN.1 wrapper begins [ ... 30 82 09 56 ]. That indicates an object of size
0x956 - a four byte discrepency, presumably just padding for alignment
purposes.
So we just check that the ASN.1 container is no bigger than the payload and
reduce the recorded size appropriately.
Whilst we're at it, allow shorter PKCS#7 objects that manage to squeeze within
127 or 255 bytes. It's just about conceivable if no X.509 certs are included
in the PKCS#7 message.
Reported-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Acked-by: Peter Jones <pjones@redhat.com>
Signed-off-by: James Morris <james.l.morris@oracle.com>
The length of the name of an asymmetric key subtype must be stored in struct
asymmetric_key_subtype::name_len so that it can be matched by a search for
"<subkey_name>:<partial_fingerprint>". Fix the public_key subtype to have
name_len set.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: James Morris <james.l.morris@oracle.com>
Need to export x509_request_asymmetric_key() so that PKCS#7 can use it if
compiled as a module.
Reported-by: James Morris <jmorris@namei.org>
Signed-off-by: David Howells <dhowells@redhat.com>
X.509 certificate issuer and subject fields are mandatory fields in the ASN.1
and so their existence needn't be tested for. They are guaranteed to end up
with an empty string if the name material has nothing we can use (see
x509_fabricate_name()).
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Correctly assemble the client UUID by OR'ing in the flags rather than
assigning them over the other components.
Reported-by: Himangi Saraogi <himangi774@gmail.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
pkcs7_request_asymmetric_key() and x509_request_asymmetric_key() do the same
thing, the latter being a copy of the former created by the IMA folks, so drop
the PKCS#7 version as the X.509 location is more general.
Whilst we're at it, rename the arguments of x509_request_asymmetric_key() to
better reflect what the values being passed in are intended to match on an
X.509 cert.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
x509_request_asymmetric_keys() doesn't need the lengths of the NUL-terminated
strings passing in as it can work that out for itself.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
crypto/asymmetric_keys/pkcs7_key_type.c needs to #include linux/err.h rather
than relying on getting it through other headers.
Without this, the powerpc allyesconfig build fails.
Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: David Howells <dhowells@redhat.com>
Here's a set of changes that implement a PE file signature checker.
This provides the following facility:
(1) Extract the signature from the PE file. This is a PKCS#7 message
containing, as its data, a hash of the signed parts of the file.
(2) Digest the signed parts of the file.
(3) Compare the digest with the one from the PKCS#7 message.
(4) Validate the signatures on the PKCS#7 message and indicate
whether it was matched by a trusted key.
Signed-off-by: David Howells <dhowells@redhat.com>
Here's a set of changes that implement a PKCS#7 message parser in the kernel.
The PKCS#7 message parsing will then be used to limit kexec to authenticated
kernels only if so configured.
The changes provide the following facilities:
(1) Parse an ASN.1 PKCS#7 message and pick out useful bits such as the data
content and the X.509 certificates used to sign it and all the data
signatures.
(2) Verify all the data signatures against the set of X.509 certificates
available in the message.
(3) Follow the certificate chains and verify that:
(a) for every self-signed X.509 certificate, check that it validly signed
itself, and:
(b) for every non-self-signed certificate, if we have a 'parent'
certificate, the former is validly signed by the latter.
(4) Look for intersections between the certificate chains and the trusted
keyring, if any intersections are found, verify that the trusted
certificates signed the intersection point in the chain.
(5) For testing purposes, a key type can be made available that will take a
PKCS#7 message, check that the message is trustworthy, and if so, add its
data content into the key.
Note that (5) has to be altered to take account of the preparsing patches
already committed to this branch.
Signed-off-by: David Howells <dhowells@redhat.com>
Here are a set of changes that make all but encrypted and trusted keys use
preparsing. Unfortunately, encrypted and trusted keys incorrectly use the
update op to alter a key, so other changes will need to be made for them.
These changes permit payload parsing when instantiating or updating a key to be
done before locks are taken and to determine the amount of quota that will be
required in advance. The latter will make it possible to do LRU discard before
any locks are taken.
Signed-off-by: David Howells <dhowells@redhat.com>
Provide key preparsing for the request_key_auth key type so that we can make
preparsing mandatory. This does nothing as this type can only be set up
internally to the kernel.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Steve Dickson <steved@redhat.com>
Acked-by: Jeff Layton <jlayton@primarydata.com>
Provide key preparsing in the keyring so that we can make preparsing
mandatory. For keyrings, however, only an empty payload is permitted.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Steve Dickson <steved@redhat.com>
Acked-by: Jeff Layton <jlayton@primarydata.com>
Make use of key preparsing in the big key type so that quota size determination
can take place prior to keyring locking when a key is being added.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Steve Dickson <steved@redhat.com>
Make use of key preparsing in the RxRPC protocol so that quota size
determination can take place prior to keyring locking when a key is being
added.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Steve Dickson <steved@redhat.com>
Make use of key preparsing in the DNS resolver so that quota size determination
can take place prior to keyring locking when a key is being added.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Steve Dickson <steved@redhat.com>
Acked-by: Jeff Layton <jlayton@primarydata.com>
Make use of key preparsing in Ceph so that quota size determination can take
place prior to keyring locking when a key is being added.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Steve Dickson <steved@redhat.com>
Reviewed-by: Sage Weil <sage@redhat.com>
cc: Tommi Virtanen <tommi.virtanen@dreamhost.com>
Make use of key preparsing in user-defined and logon keys so that quota size
determination can take place prior to keyring locking when a key is being
added.
Also the idmapper key types need to change to match as they use the
user-defined key type routines.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Steve Dickson <steved@redhat.com>
Acked-by: Jeff Layton <jlayton@primarydata.com>
Call the ->free_preparse() key type op even after ->preparse() returns an
error as it does cleaning up type stuff.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Steve Dickson <steved@redhat.com>
Acked-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Sage Weil <sage@redhat.com>
Provide a generic instantiation function for key types that use the preparse
hook. This makes it easier to prereserve key quota before keyrings get locked
to retain the new key.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Steve Dickson <steved@redhat.com>
Acked-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Sage Weil <sage@redhat.com>
Special kernel keys, such as those used to hold DNS results for AFS, CIFS and
NFS and those used to hold idmapper results for NFS, used to be
'invalidateable' with key_revoke(). However, since the default permissions for
keys were reduced:
Commit: 96b5c8fea6
KEYS: Reduce initial permissions on keys
it has become impossible to do this.
Add a key flag (KEY_FLAG_ROOT_CAN_INVAL) that will permit a key to be
invalidated by root. This should not be used for system keyrings as the
garbage collector will try and remove any invalidate key. For system keyrings,
KEY_FLAG_ROOT_CAN_CLEAR can be used instead.
After this, from userspace, keyctl_invalidate() and "keyctl invalidate" can be
used by any possessor of CAP_SYS_ADMIN (typically root) to invalidate DNS and
idmapper keys. Invalidated keys are immediately garbage collected and will be
immediately rerequested if needed again.
Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: Steve Dickson <steved@redhat.com>
Validate the PKCS#7 trust chain against the contents of the system keyring.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Digest the signed parts of the PE binary, canonicalising the section table
before we need it, and then compare the the resulting digest to the one in the
PKCS#7 signed content.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
The PKCS#7 certificate should contain a "Microsoft individual code signing"
data blob as its signed content. This blob contains a digest of the signed
content of the PE binary and the OID of the digest algorithm used (typically
SHA256).
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
The certificate data block in a PE binary has a wrapper around the PKCS#7
signature we actually want to get at. Strip this off and check that we've got
something that appears to be a PKCS#7 signature.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Parse a PE binary to find a key and a signature contained therein. Later
patches will check the signature and add the key if the signature checks out.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Provide some PE binary structural and constant definitions as taken from the
pesign package sources.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Find the intersection between the X.509 certificate chain contained in a PKCS#7
message and a set of keys that we already know and trust.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Verify certificate chain in the X.509 certificates contained within the PKCS#7
message as far as possible. If any signature that we should be able to verify
fails, we reject the whole lot.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Find the appropriate key in the PKCS#7 key list and verify the signature with
it. There may be several keys in there forming a chain. Any link in that
chain or the root of that chain may be in our keyrings.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Digest the data in a PKCS#7 signed-data message and attach to the
public_key_signature struct contained in the pkcs7_message struct.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
PKCS#7 validation requires access to the serial number and the raw names in an
X.509 certificate.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Josh Boyer <jwboyer@redhat.com>
call->async_workfn() can take an afs_call* arg rather than a work_struct* as
the functions assigned there are now called from afs_async_workfn() which has
to call container_of() anyway.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Nathaniel Wesley Filardo <nwf@cs.jhu.edu>
Reviewed-by: Tejun Heo <tj@kernel.org>
Fix the cache manager RPC service handlers. The afs_send_empty_reply() and
afs_send_simple_reply() functions:
(a) Kill the call and free up the buffers associated with it if they fail.
(b) Return with call intact if it they succeed.
However, none of the callers actually check the result or clean up if
successful - and may use the now non-existent data if it fails.
This was detected by Dan Carpenter using a static checker:
The patch 08e0e7c82e: "[AF_RXRPC]: Make the in-kernel AFS
filesystem use AF_RXRPC." from Apr 26, 2007, leads to the following
static checker warning:
"fs/afs/cmservice.c:155 SRXAFSCB_CallBack()
warn: 'call' was already freed."
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Make delayed_free() call free_vfsmnt() so that we don't have two functions
doing the same job. This requires the calls to mnt_free_id() in free_vfsmnt()
to be moved into the callers of that function.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Move the flags representing required permission to linux/key.h as the perm
parameter of security_key_permission() is in terms of them - and not the
permissions mask flags used in key->perm.
Whilst we're at it:
(1) Rename them to be KEY_NEED_xxx rather than KEY_xxx to avoid collisions
with symbols in uapi/linux/input.h.
(2) Don't use key_perm_t for a mask of required permissions, but rather limit
it to the permissions mask attached to the key and arguments related
directly to that.
Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
The SMBUS tracepoints can be enabled thusly:
echo 1 >/sys/kernel/debug/tracing/events/i2c/enable
and will dump messages that can be viewed in /sys/kernel/debug/tracing/trace
that look like:
... smbus_read: i2c-0 a=051 f=0000 c=fa BYTE_DATA
... smbus_reply: i2c-0 a=051 f=0000 c=fa BYTE_DATA l=1 [39]
... smbus_result: i2c-0 a=051 f=0000 c=fa BYTE_DATA rd res=0
formatted as:
i2c-<adapter-nr>
a=<addr>
f=<flags>
c=<command>
<protocol-name>
<rd|wr>
res=<result>
l=<data-len>
[<data-block>]
The adapters to be traced can be selected by something like:
echo adapter_nr==1 >/sys/kernel/debug/tracing/events/i2c/filter
Note that this shares the same filter and enablement as i2c.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Add tracepoints into the I2C message transfer function to retrieve the message
sent or received. The following config options must be turned on to make use
of the facility:
CONFIG_FTRACE
CONFIG_ENABLE_DEFAULT_TRACERS
The I2C tracepoint can be enabled thusly:
echo 1 >/sys/kernel/debug/tracing/events/i2c/enable
and will dump messages that can be viewed in /sys/kernel/debug/tracing/trace
that look like:
... i2c_write: i2c-5 #0 a=044 f=0000 l=2 [02-14]
... i2c_read: i2c-5 #1 a=044 f=0001 l=4
... i2c_reply: i2c-5 #1 a=044 f=0001 l=4 [33-00-00-00]
... i2c_result: i2c-5 n=2 ret=2
formatted as:
i2c-<adapter-nr>
#<message-array-index>
a=<addr>
f=<flags>
l=<datalen>
n=<message-array-size>
ret=<result>
[<data>]
The operation is done between the i2c_write/i2c_read lines and the i2c_reply
and i2c_result lines so that if the hardware hangs, the trace buffer can be
consulted to determine the problematic operation.
The adapters to be traced can be selected by something like:
echo adapter_nr==1 >/sys/kernel/debug/tracing/events/i2c/filter
These changes are based on code from Steven Rostedt.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
[wsa: adapted path for 'enable' in the commit msg]
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
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 <tt.rantala@gmail.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <james.l.morris@oracle.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Set the RxRPC header flag to request an ACK packet for every odd-numbered DATA
packet unless it's the last one (which implicitly requests an ACK anyway).
This is similar to how librx appears to work.
If we don't do this, we'll send out a full window of packets and then just sit
there until the other side gets bored and sends an ACK to indicate that it's
been idle for a while and has received no new packets.
Requesting a lot of ACKs shouldn't be a problem as ACKs should be merged when
possible.
As AF_RXRPC currently works, it will schedule an ACK to be generated upon
receipt of a DATA packet with the ACK-request packet set - and in the time
taken to schedule this in a work queue, several other packets are likely to
arrive and then all get ACK'd together.
Signed-off-by: David Howells <dhowells@redhat.com>
Expose RxRPC parameters via sysctls to control the Rx window size, the Rx MTU
maximum size and the number of packets that can be glued into a jumbo packet.
More info added to Documentation/networking/rxrpc.txt.
Signed-off-by: David Howells <dhowells@redhat.com>
Improve ACK production by the following means:
(1) Don't send an ACK_REQUESTED ack immediately even if the RXRPC_MORE_PACKETS
flag isn't set on a data packet that has also has RXRPC_REQUEST_ACK set.
MORE_PACKETS just means that the sender just emptied its Tx data buffer.
More data will be forthcoming unless RXRPC_LAST_PACKET is also flagged.
It is possible to see runs of DATA packets with MORE_PACKETS unset that
aren't waiting for an ACK.
It is therefore better to wait a small instant to see if we can combine an
ACK for several packets.
(2) Don't send an ACK_IDLE ack immediately unless we're responding to the
terminal data packet of a call.
Whilst sending an ACK_IDLE mid-call serves to let the other side know
that we won't be asking it to resend certain Tx buffers and that it can
discard them, spamming it with loads of acks just because we've
temporarily run out of data just distracts it.
(3) Put the ACK_IDLE ack generation timeout up to half a second rather than a
single jiffy. Just because we haven't been given more data immediately
doesn't mean that more isn't forthcoming. The other side may be busily
finding the data to send to us.
Signed-off-by: David Howells <dhowells@redhat.com>
Add sysctls for configuring RxRPC protocol handling, specifically controls on
delays before ack generation, the delay before resending a packet, the maximum
lifetime of a call and the expiration times of calls, connections and
transports that haven't been recently used.
More info added in Documentation/networking/rxrpc.txt.
Signed-off-by: David Howells <dhowells@redhat.com>
AF_RXRPC sends UDP packets with the "Don't Fragment" bit set in an attempt to
determine the maximum packet size between the local socket and the peer by
invoking the generation of ICMP_FRAG_NEEDED packets.
Once a packet is sent with the "Don't Fragment" bit set, it is then
inconvenient to break it up as that requires recalculating all the rxrpc serial
and sequence numbers and reencrypting all the fragments, so we switch off the
"Don't Fragment" service temporarily and send the bounced packet again. Future
packets then use the new MTU.
That's all fine. The problem lies in rxrpc_UDP_error_report() where the code
that deals with ICMP_FRAG_NEEDED packets lives. Packets of this type have a
field (ee_info) to indicate the maximum packet size at the reporting node - but
sometimes ee_info isn't filled in and is just left as 0 and the code must allow
for this.
When ee_info is 0, the code should take the MTU size we're currently using and
reduce it for the next packet we want to send. However, it takes ee_info
(which is known to be 0) and tries to reduce that instead.
This was discovered by Coverity.
Reported-by: Dave Jones <davej@redhat.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Delete ARM's asm/system.h. It's the last holdout and should be got rid of.
This builds for defconfig, lpc32xx_defconfig, exynos_defconfig + XEN, the
previous changed to a Gemini system and an omap3 config with TI_DAVINCI_EMAC.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Cc: linux-arm-kernel@lists.infradead.org
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
When FS-Cache allocates an object, the following sequence of events can
occur:
-->fscache_alloc_object()
-->cachefiles_alloc_object() [via cache->ops->alloc_object]
<--[returns new object]
-->fscache_attach_object()
<--[failed]
-->cachefiles_put_object() [via cache->ops->put_object]
-->fscache_object_destroy()
-->fscache_objlist_remove()
-->rb_erase() to remove the object from fscache_object_list.
resulting in a crash in the rbtree code.
The problem is that the object is only added to fscache_object_list on
the success path of fscache_attach_object() where it calls
fscache_objlist_add().
So if fscache_attach_object() fails, the object won't have been added to
the objlist rbtree. We do, however, unconditionally try to remove the
object from the tree.
Thanks to NeilBrown for finding this and suggesting this solution.
Reported-by: NeilBrown <neilb@suse.de>
Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: (a customer of) NeilBrown <neilb@suse.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Fix the following warning in the aty128fb driver:
drivers/video/aty/aty128fb.c:363:12: warning: 'backlight' defined but not used [-Wunused-variable]
static int backlight = 0;
^
as the variable's value is only read if CONFIG_FB_ATY128_BACKLIGHT=y. The
variable is also set if MODULE is unset[*].
[*] I wonder if the conditional wrapper around aty128fb_setup() should be
using CONFIG_MODULE rather than MODULE.
Signed-off-by: David Howells <dhowells@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Fix up the following pointer-integer size mismatch warning in
tps65217_probe():
drivers/mfd/tps65217.c: In function 'tps65217_probe':
drivers/mfd/tps65217.c:173:13: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
chip_id = (unsigned int)match->data;
^
Signed-off-by: David Howells <dhowells@redhat.com>
Cc: AnilKumar Ch <anilkumar@ti.com>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Fix up the following pointer-integer size mismatch warning in
max8998_i2c_get_driver_data():
drivers/mfd/max8998.c: In function 'max8998_i2c_get_driver_data':
drivers/mfd/max8998.c:178:10: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
return (int)match->data;
^
Signed-off-by: David Howells <dhowells@redhat.com>
Cc: Tomasz Figa <t.figa@samsung.com>
Cc: Mark Brown <broonie@linaro.org>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Fix the following warning:
drivers/gpu/drm/gma500/backlight.c:29:13: warning: 'do_gma_backlight_set' defined but not used [-Wunused-function]
by moving the entire function inside the conditional section currently
inside of it. All the places that call it are so conditionalised.
Signed-off-by: David Howells <dhowells@redhat.com>
Cc: Alan Cox <alan@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Fix up the following pointer-integer size mismatch warning in tps62360_probe():
drivers/regulator/tps62360-regulator.c: In function 'tps62360_probe':
drivers/regulator/tps62360-regulator.c:363:13: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
chip_id = (int)match->data;
^
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
Use the new %pd printk() specifier in eCryptFS to replace passing of dentry
name or dentry name and name length * 2 with just passing the dentry.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: ecryptfs@vger.kernel.org
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Fix the gathering of certificates from both the source tree and the build tree
to correctly calculate the pathnames of all the certificates.
The problem was that if the default generated cert, signing_key.x509, didn't
exist then it would not have a path attached and if it did, it would have a
path attached.
This means that the contents of kernel/.x509.list would change between the
first compilation in a directory and the second. After the second it would
remain stable because the signing_key.x509 file exists.
The consequence was that the kernel would get relinked unconditionally on the
second recompilation. The second recompilation would also show something like
this:
X.509 certificate list changed
CERTS kernel/x509_certificate_list
- Including cert /home/torvalds/v2.6/linux/signing_key.x509
AS kernel/system_certificates.o
LD kernel/built-in.o
which is why the relink would happen.
Unfortunately, it isn't a simple matter of just sticking a path on the front
of the filename of the certificate in the build directory as make can't then
work out how to build it.
So the path has to be prepended to the name for sorting and duplicate
elimination and then removed for the make rule if it is in the build tree.
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: David Howells <dhowells@redhat.com>
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<=16; i++)); do keyctl newring ring$i $r; done
for ((i=0; i<=16; i++)); do keyctl add user a$i a %:ring$i; done
for ((i=0; i<=16; i++)); do keyctl search $r user a$i; done
for ((i=17; i<=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 <dhowells@redhat.com>
Tested-by: Stephen Gallagher <sgallagh@redhat.com>
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->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<=16; i++)); do keyctl newring ring$i $r; done
This should work fine, but oopses when the 17th keyring is added.
Since ops->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 ->compare_object().
BUG: unable to handle kernel NULL pointer dereference at 0000000000000088
IP: [<ffffffff81191ee4>] hash_key_type_and_desc+0x18/0xb0
...
RIP: 0010:[<ffffffff81191ee4>] hash_key_type_and_desc+0x18/0xb0
...
Call Trace:
[<ffffffff81191f9d>] keyring_diff_objects+0x21/0xd2
[<ffffffff811f09ef>] assoc_array_insert+0x3b6/0x908
[<ffffffff811929a7>] __key_link_begin+0x78/0xe5
[<ffffffff81191a2e>] key_create_or_update+0x17d/0x36a
[<ffffffff81192e0a>] SyS_add_key+0x123/0x183
[<ffffffff81400ddb>] tracesys+0xdd/0xe2
Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: Stephen Gallagher <sgallagh@redhat.com>
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 -> keyring B -> 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<=16; i++)); do keyctl newring ring$i $r; done
for ((i=0; i<=16; i++)); do keyctl add user a$i a %:ring$i; done
for ((i=0; i<=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 <nalin@redhat.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: Stephen Gallagher <sgallagh@redhat.com>
The second word of key->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:[<ffffffff811b4a51>] dput+0x21/0x2d0
...
Call Trace:
[<ffffffff811a7b06>] path_put+0x16/0x30
[<ffffffff81235604>] big_key_destroy+0x44/0x60
[<ffffffff8122dc4b>] key_gc_unused_keys.constprop.2+0x5b/0xe0
[<ffffffff8122df2f>] key_garbage_collector+0x1df/0x3c0
[<ffffffff8107759b>] process_one_work+0x17b/0x460
[<ffffffff8107834b>] worker_thread+0x11b/0x400
[<ffffffff81078230>] ? rescuer_thread+0x3e0/0x3e0
[<ffffffff8107eb00>] kthread+0xc0/0xd0
[<ffffffff8107ea40>] ? kthread_create_on_node+0x110/0x110
[<ffffffff815c4bec>] ret_from_fork+0x7c/0xb0
[<ffffffff8107ea40>] ? kthread_create_on_node+0x110/0x110
Reported-by: Patrik Kis <pkis@redhat.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Stephen Gallagher <sgallagh@redhat.com>