Merge tag 'keys-next-20151021' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs into next
diff --git a/Documentation/crypto/asymmetric-keys.txt b/Documentation/crypto/asymmetric-keys.txt
index b767590..8c07e0e 100644
--- a/Documentation/crypto/asymmetric-keys.txt
+++ b/Documentation/crypto/asymmetric-keys.txt
@@ -186,7 +186,7 @@
 					const struct public_key_signature *sig);
 	};
 
-Asymmetric keys point to this with their type_data[0] member.
+Asymmetric keys point to this with their payload[asym_subtype] member.
 
 The owner and name fields should be set to the owning module and the name of
 the subtype.  Currently, the name is only used for print statements.
@@ -269,8 +269,7 @@
 
 	struct key_preparsed_payload {
 		char		*description;
-		void		*type_data[2];
-		void		*payload;
+		void		*payload[4];
 		const void	*data;
 		size_t		datalen;
 		size_t		quotalen;
@@ -283,16 +282,18 @@
      not theirs.
 
      If the parser is happy with the blob, it should propose a description for
-     the key and attach it to ->description, ->type_data[0] should be set to
-     point to the subtype to be used, ->payload should be set to point to the
-     initialised data for that subtype, ->type_data[1] should point to a hex
-     fingerprint and quotalen should be updated to indicate how much quota this
-     key should account for.
+     the key and attach it to ->description, ->payload[asym_subtype] should be
+     set to point to the subtype to be used, ->payload[asym_crypto] should be
+     set to point to the initialised data for that subtype,
+     ->payload[asym_key_ids] should point to one or more hex fingerprints and
+     quotalen should be updated to indicate how much quota this key should
+     account for.
 
-     When clearing up, the data attached to ->type_data[1] and ->description
-     will be kfree()'d and the data attached to ->payload will be passed to the
-     subtype's ->destroy() method to be disposed of.  A module reference for
-     the subtype pointed to by ->type_data[0] will be put.
+     When clearing up, the data attached to ->payload[asym_key_ids] and
+     ->description will be kfree()'d and the data attached to
+     ->payload[asm_crypto] will be passed to the subtype's ->destroy() method
+     to be disposed of.  A module reference for the subtype pointed to by
+     ->payload[asym_subtype] will be put.
 
 
      If the data format is not recognised, -EBADMSG should be returned.  If it
diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
index c9e7f4f..8c18387 100644
--- a/Documentation/security/keys.txt
+++ b/Documentation/security/keys.txt
@@ -1049,12 +1049,12 @@
 NOTES ON ACCESSING PAYLOAD CONTENTS
 ===================================
 
-The simplest payload is just a number in key->payload.value. In this case,
-there's no need to indulge in RCU or locking when accessing the payload.
+The simplest payload is just data stored in key->payload directly.  In this
+case, there's no need to indulge in RCU or locking when accessing the payload.
 
-More complex payload contents must be allocated and a pointer to them set in
-key->payload.data. One of the following ways must be selected to access the
-data:
+More complex payload contents must be allocated and pointers to them set in the
+key->payload.data[] array.  One of the following ways must be selected to
+access the data:
 
  (1) Unmodifiable key type.
 
@@ -1092,6 +1092,13 @@
      the payload. key->datalen cannot be relied upon to be consistent with the
      payload just dereferenced if the key's semaphore is not held.
 
+     Note that key->payload.data[0] has a shadow that is marked for __rcu
+     usage.  This is called key->payload.rcu_data0.  The following accessors
+     wrap the RCU calls to this element:
+
+	rcu_assign_keypointer(struct key *key, void *data);
+	void *rcu_dereference_key(struct key *key);
+
 
 ===================
 DEFINING A KEY TYPE
@@ -1143,8 +1150,7 @@
 
 	struct key_preparsed_payload {
 		char		*description;
-		void		*type_data[2];
-		void		*payload;
+		union key_payload payload;
 		const void	*data;
 		size_t		datalen;
 		size_t		quotalen;
@@ -1160,10 +1166,9 @@
      attached as a string to the description field.  This will be used for the
      key description if the caller of add_key() passes NULL or "".
 
-     The method can attach anything it likes to type_data[] and payload.  These
-     are merely passed along to the instantiate() or update() operations.  If
-     set, the expiry time will be applied to the key if it is instantiated from
-     this data.
+     The method can attach anything it likes to payload.  This is merely passed
+     along to the instantiate() or update() operations.  If set, the expiry
+     time will be applied to the key if it is instantiated from this data.
 
      The method should return 0 if successful or a negative error code
      otherwise.
@@ -1172,11 +1177,10 @@
  (*) void (*free_preparse)(struct key_preparsed_payload *prep);
 
      This method is only required if the preparse() method is provided,
-     otherwise it is unused.  It cleans up anything attached to the
-     description, type_data and payload fields of the key_preparsed_payload
-     struct as filled in by the preparse() method.  It will always be called
-     after preparse() returns successfully, even if instantiate() or update()
-     succeed.
+     otherwise it is unused.  It cleans up anything attached to the description
+     and payload fields of the key_preparsed_payload struct as filled in by the
+     preparse() method.  It will always be called after preparse() returns
+     successfully, even if instantiate() or update() succeed.
 
 
  (*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep);
@@ -1197,6 +1201,11 @@
 
      It is safe to sleep in this method.
 
+     generic_key_instantiate() is provided to simply copy the data from
+     prep->payload.data[] to key->payload.data[], with RCU-safe assignment on
+     the first element.  It will then clear prep->payload.data[] so that the
+     free_preparse method doesn't release the data.
+
 
  (*) int (*update)(struct key *key, const void *data, size_t datalen);
 
diff --git a/certs/.gitignore b/certs/.gitignore
new file mode 100644
index 0000000..f51aea4
--- /dev/null
+++ b/certs/.gitignore
@@ -0,0 +1,4 @@
+#
+# Generated files
+#
+x509_certificate_list
diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h
index 3f5b537..1d450b5 100644
--- a/crypto/asymmetric_keys/asymmetric_keys.h
+++ b/crypto/asymmetric_keys/asymmetric_keys.h
@@ -14,8 +14,3 @@
 extern int __asymmetric_key_hex_to_key_id(const char *id,
 					  struct asymmetric_key_id *match_id,
 					  size_t hexlen);
-static inline
-const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key)
-{
-	return key->type_data.p[1];
-}
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index 1916680..9f2165b 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -307,25 +307,34 @@
 }
 
 /*
- * Clean up the preparse data
+ * Clean up the key ID list
  */
-static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
+static void asymmetric_key_free_kids(struct asymmetric_key_ids *kids)
 {
-	struct asymmetric_key_subtype *subtype = prep->type_data[0];
-	struct asymmetric_key_ids *kids = prep->type_data[1];
 	int i;
 
-	pr_devel("==>%s()\n", __func__);
-
-	if (subtype) {
-		subtype->destroy(prep->payload[0]);
-		module_put(subtype->owner);
-	}
 	if (kids) {
 		for (i = 0; i < ARRAY_SIZE(kids->id); i++)
 			kfree(kids->id[i]);
 		kfree(kids);
 	}
+}
+
+/*
+ * Clean up the preparse data
+ */
+static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
+{
+	struct asymmetric_key_subtype *subtype = prep->payload.data[asym_subtype];
+	struct asymmetric_key_ids *kids = prep->payload.data[asym_key_ids];
+
+	pr_devel("==>%s()\n", __func__);
+
+	if (subtype) {
+		subtype->destroy(prep->payload.data[asym_crypto]);
+		module_put(subtype->owner);
+	}
+	asymmetric_key_free_kids(kids);
 	kfree(prep->description);
 }
 
@@ -335,20 +344,19 @@
 static void asymmetric_key_destroy(struct key *key)
 {
 	struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
-	struct asymmetric_key_ids *kids = key->type_data.p[1];
+	struct asymmetric_key_ids *kids = key->payload.data[asym_key_ids];
+	void *data = key->payload.data[asym_crypto];
+
+	key->payload.data[asym_crypto] = NULL;
+	key->payload.data[asym_subtype] = NULL;
+	key->payload.data[asym_key_ids] = NULL;
 
 	if (subtype) {
-		subtype->destroy(key->payload.data);
+		subtype->destroy(data);
 		module_put(subtype->owner);
-		key->type_data.p[0] = NULL;
 	}
 
-	if (kids) {
-		kfree(kids->id[0]);
-		kfree(kids->id[1]);
-		kfree(kids);
-		key->type_data.p[1] = NULL;
-	}
+	asymmetric_key_free_kids(kids);
 }
 
 struct key_type key_type_asymmetric = {
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 81efccb..6db4c01 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -49,7 +49,7 @@
 static void public_key_describe(const struct key *asymmetric_key,
 				struct seq_file *m)
 {
-	struct public_key *key = asymmetric_key->payload.data;
+	struct public_key *key = asymmetric_key->payload.data[asym_crypto];
 
 	if (key)
 		seq_printf(m, "%s.%s",
@@ -112,7 +112,7 @@
 static int public_key_verify_signature_2(const struct key *key,
 					 const struct public_key_signature *sig)
 {
-	const struct public_key *pk = key->payload.data;
+	const struct public_key *pk = key->payload.data[asym_crypto];
 	return public_key_verify_signature(pk, sig);
 }
 
diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c
index 7525fd1..9441240 100644
--- a/crypto/asymmetric_keys/signature.c
+++ b/crypto/asymmetric_keys/signature.c
@@ -37,7 +37,7 @@
 		return -EINVAL;
 	subtype = asymmetric_key_subtype(key);
 	if (!subtype ||
-	    !key->payload.data)
+	    !key->payload.data[0])
 		return -EINVAL;
 	if (!subtype->verify_signature)
 		return -ENOTSUPP;
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
index 1de01ea..dbeed60 100644
--- a/crypto/asymmetric_keys/x509_parser.h
+++ b/crypto/asymmetric_keys/x509_parser.h
@@ -11,6 +11,7 @@
 
 #include <linux/time.h>
 #include <crypto/public_key.h>
+#include <keys/asymmetric-type.h>
 
 struct x509_certificate {
 	struct x509_certificate *next;
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 1970966..64d4298 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -266,7 +266,8 @@
 	if (!IS_ERR(key))  {
 		if (!use_builtin_keys
 		    || test_bit(KEY_FLAG_BUILTIN, &key->flags))
-			ret = x509_check_signature(key->payload.data, cert);
+			ret = x509_check_signature(key->payload.data[asym_crypto],
+						   cert);
 		key_put(key);
 	}
 	return ret;
@@ -352,9 +353,9 @@
 
 	/* We're pinning the module by being linked against it */
 	__module_get(public_key_subtype.owner);
-	prep->type_data[0] = &public_key_subtype;
-	prep->type_data[1] = kids;
-	prep->payload[0] = cert->pub;
+	prep->payload.data[asym_subtype] = &public_key_subtype;
+	prep->payload.data[asym_key_ids] = kids;
+	prep->payload.data[asym_crypto] = cert->pub;
 	prep->description = desc;
 	prep->quotalen = 100;
 
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index f4cf200..6908080 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -42,7 +42,7 @@
 		goto error;
 
 	/* attach the data */
-	key->payload.data = payload;
+	key->payload.data[0] = payload;
 	ret = 0;
 
 error:
@@ -52,7 +52,7 @@
 static void
 cifs_spnego_key_destroy(struct key *key)
 {
-	kfree(key->payload.data);
+	kfree(key->payload.data[0]);
 }
 
 
@@ -167,7 +167,7 @@
 
 #ifdef CONFIG_CIFS_DEBUG2
 	if (cifsFYI && !IS_ERR(spnego_key)) {
-		struct cifs_spnego_msg *msg = spnego_key->payload.data;
+		struct cifs_spnego_msg *msg = spnego_key->payload.data[0];
 		cifs_dump_mem("SPNEGO reply blob:", msg->data, min(1024U,
 				msg->secblob_len + msg->sesskey_len));
 	}
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 1ea780b..3f9312591 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -58,16 +58,15 @@
 	 * dereference payload.data!
 	 */
 	if (prep->datalen <= sizeof(key->payload)) {
-		key->payload.value = 0;
-		memcpy(&key->payload.value, prep->data, prep->datalen);
-		key->datalen = prep->datalen;
-		return 0;
+		key->payload.data[0] = NULL;
+		memcpy(&key->payload, prep->data, prep->datalen);
+	} else {
+		payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
+		if (!payload)
+			return -ENOMEM;
+		key->payload.data[0] = payload;
 	}
-	payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
-	if (!payload)
-		return -ENOMEM;
 
-	key->payload.data = payload;
 	key->datalen = prep->datalen;
 	return 0;
 }
@@ -76,7 +75,7 @@
 cifs_idmap_key_destroy(struct key *key)
 {
 	if (key->datalen > sizeof(key->payload))
-		kfree(key->payload.data);
+		kfree(key->payload.data[0]);
 }
 
 static struct key_type cifs_idmap_key_type = {
@@ -233,8 +232,8 @@
 	 * it could be.
 	 */
 	ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
-		(struct cifs_sid *)&sidkey->payload.value :
-		(struct cifs_sid *)sidkey->payload.data;
+		(struct cifs_sid *)&sidkey->payload :
+		(struct cifs_sid *)sidkey->payload.data[0];
 
 	ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
 	if (ksid_size > sidkey->datalen) {
@@ -307,14 +306,14 @@
 	if (sidtype == SIDOWNER) {
 		kuid_t uid;
 		uid_t id;
-		memcpy(&id, &sidkey->payload.value, sizeof(uid_t));
+		memcpy(&id, &sidkey->payload.data[0], sizeof(uid_t));
 		uid = make_kuid(&init_user_ns, id);
 		if (uid_valid(uid))
 			fuid = uid;
 	} else {
 		kgid_t gid;
 		gid_t id;
-		memcpy(&id, &sidkey->payload.value, sizeof(gid_t));
+		memcpy(&id, &sidkey->payload.data[0], sizeof(gid_t));
 		gid = make_kgid(&init_user_ns, id);
 		if (gid_valid(gid))
 			fgid = gid;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 773f4dc..3f22285 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2325,13 +2325,14 @@
 cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
 {
 	int rc = 0;
-	char *desc, *delim, *payload;
+	const char *delim, *payload;
+	char *desc;
 	ssize_t len;
 	struct key *key;
 	struct TCP_Server_Info *server = ses->server;
 	struct sockaddr_in *sa;
 	struct sockaddr_in6 *sa6;
-	struct user_key_payload *upayload;
+	const struct user_key_payload *upayload;
 
 	desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
 	if (!desc)
@@ -2374,14 +2375,14 @@
 	}
 
 	down_read(&key->sem);
-	upayload = key->payload.data;
+	upayload = user_key_payload(key);
 	if (IS_ERR_OR_NULL(upayload)) {
 		rc = upayload ? PTR_ERR(upayload) : -EINVAL;
 		goto out_key_put;
 	}
 
 	/* find first : in payload */
-	payload = (char *)upayload->data;
+	payload = upayload->data;
 	delim = strnchr(payload, upayload->datalen, ':');
 	cifs_dbg(FYI, "payload=%s\n", payload);
 	if (!delim) {
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index bce6fdc..59727e3 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -988,7 +988,7 @@
 		goto out;
 	}
 
-	msg = spnego_key->payload.data;
+	msg = spnego_key->payload.data[0];
 	/*
 	 * check version field to make sure that cifs.upcall is
 	 * sending us a response in an expected form
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index ce83e2e..52d14c9 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -660,7 +660,7 @@
 			goto ssetup_exit;
 		}
 
-		msg = spnego_key->payload.data;
+		msg = spnego_key->payload.data[0];
 		/*
 		 * check version field to make sure that cifs.upcall is
 		 * sending us a response in an expected form
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 5ba029e..7b39260 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -86,7 +86,7 @@
 {
 	if (key->type == &key_type_encrypted)
 		return (struct ecryptfs_auth_tok *)
-			(&((struct encrypted_key_payload *)key->payload.data)->payload_data);
+			(&((struct encrypted_key_payload *)key->payload.data[0])->payload_data);
 	else
 		return NULL;
 }
@@ -117,8 +117,7 @@
 
 	auth_tok = ecryptfs_get_encrypted_key_payload_data(key);
 	if (!auth_tok)
-		return (struct ecryptfs_auth_tok *)
-			(((struct user_key_payload *)key->payload.data)->data);
+		return (struct ecryptfs_auth_tok *)user_key_payload(key)->data;
 	else
 		return auth_tok;
 }
diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
index 1d510c1..5c52c79 100644
--- a/fs/ext4/crypto_key.c
+++ b/fs/ext4/crypto_key.c
@@ -121,7 +121,7 @@
 	struct key *keyring_key = NULL;
 	struct ext4_encryption_key *master_key;
 	struct ext4_encryption_context ctx;
-	struct user_key_payload *ukp;
+	const struct user_key_payload *ukp;
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	struct crypto_ablkcipher *ctfm;
 	const char *cipher_str;
@@ -209,7 +209,7 @@
 	}
 	crypt_info->ci_keyring_key = keyring_key;
 	BUG_ON(keyring_key->type != &key_type_logon);
-	ukp = ((struct user_key_payload *)keyring_key->payload.data);
+	ukp = user_key_payload(keyring_key);
 	if (ukp->datalen != sizeof(struct ext4_encryption_key)) {
 		res = -EINVAL;
 		goto out;
diff --git a/fs/f2fs/crypto_key.c b/fs/f2fs/crypto_key.c
index 9f77de2..5de2d86 100644
--- a/fs/f2fs/crypto_key.c
+++ b/fs/f2fs/crypto_key.c
@@ -122,7 +122,7 @@
 	struct key *keyring_key = NULL;
 	struct f2fs_encryption_key *master_key;
 	struct f2fs_encryption_context ctx;
-	struct user_key_payload *ukp;
+	const struct user_key_payload *ukp;
 	struct crypto_ablkcipher *ctfm;
 	const char *cipher_str;
 	char raw_key[F2FS_MAX_KEY_SIZE];
@@ -199,7 +199,7 @@
 	}
 	crypt_info->ci_keyring_key = keyring_key;
 	BUG_ON(keyring_key->type != &key_type_logon);
-	ukp = ((struct user_key_payload *)keyring_key->payload.data);
+	ukp = user_key_payload(keyring_key);
 	if (ukp->datalen != sizeof(struct f2fs_encryption_key)) {
 		res = -EINVAL;
 		goto out;
diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c
index 51dde81..6b028b7 100644
--- a/fs/fscache/object-list.c
+++ b/fs/fscache/object-list.c
@@ -316,7 +316,7 @@
 static void fscache_objlist_config(struct fscache_objlist_data *data)
 {
 #ifdef CONFIG_KEYS
-	struct user_key_payload *confkey;
+	const struct user_key_payload *confkey;
 	unsigned long config;
 	struct key *key;
 	const char *buf;
@@ -329,7 +329,7 @@
 	config = 0;
 	rcu_read_lock();
 
-	confkey = key->payload.data;
+	confkey = user_key_payload(key);
 	buf = confkey->data;
 
 	for (len = confkey->datalen - 1; len >= 0; len--) {
diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c
index 2e49022..5ba22c6 100644
--- a/fs/nfs/nfs4idmap.c
+++ b/fs/nfs/nfs4idmap.c
@@ -297,7 +297,7 @@
 {
 	const struct cred *saved_cred;
 	struct key *rkey;
-	struct user_key_payload *payload;
+	const struct user_key_payload *payload;
 	ssize_t ret;
 
 	saved_cred = override_creds(id_resolver_cache);
@@ -316,7 +316,7 @@
 	if (ret < 0)
 		goto out_up;
 
-	payload = rcu_dereference(rkey->payload.rcudata);
+	payload = user_key_payload(rkey);
 	if (IS_ERR_OR_NULL(payload)) {
 		ret = PTR_ERR(payload);
 		goto out_up;
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index 067c242..cc2516d 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -15,7 +15,6 @@
 #define _LINUX_PUBLIC_KEY_H
 
 #include <linux/mpi.h>
-#include <keys/asymmetric-type.h>
 #include <crypto/hash_info.h>
 
 enum pkey_algo {
diff --git a/include/keys/asymmetric-subtype.h b/include/keys/asymmetric-subtype.h
index 4b840e8..4915d40 100644
--- a/include/keys/asymmetric-subtype.h
+++ b/include/keys/asymmetric-subtype.h
@@ -49,7 +49,7 @@
 static inline
 struct asymmetric_key_subtype *asymmetric_key_subtype(const struct key *key)
 {
-	return key->type_data.p[0];
+	return key->payload.data[asym_subtype];
 }
 
 #endif /* _KEYS_ASYMMETRIC_SUBTYPE_H */
diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h
index c0754ab..59c1df9 100644
--- a/include/keys/asymmetric-type.h
+++ b/include/keys/asymmetric-type.h
@@ -19,6 +19,16 @@
 extern struct key_type key_type_asymmetric;
 
 /*
+ * The key payload is four words.  The asymmetric-type key uses them as
+ * follows:
+ */
+enum asymmetric_payload_bits {
+	asym_crypto,
+	asym_subtype,
+	asym_key_ids,
+};
+
+/*
  * Identifiers for an asymmetric key ID.  We have three ways of looking up a
  * key derived from an X.509 certificate:
  *
@@ -58,6 +68,11 @@
 							    size_t len_1,
 							    const void *val_2,
 							    size_t len_2);
+static inline
+const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key)
+{
+	return key->payload.data[asym_key_ids];
+}
 
 /*
  * The payload is at the discretion of the subtype.
diff --git a/include/keys/user-type.h b/include/keys/user-type.h
index cebefb0..c56fef4 100644
--- a/include/keys/user-type.h
+++ b/include/keys/user-type.h
@@ -15,6 +15,8 @@
 #include <linux/key.h>
 #include <linux/rcupdate.h>
 
+#ifdef CONFIG_KEYS
+
 /*****************************************************************************/
 /*
  * the payload for a key of type "user" or "logon"
@@ -46,5 +48,11 @@
 extern long user_read(const struct key *key,
 		      char __user *buffer, size_t buflen);
 
+static inline const struct user_key_payload *user_key_payload(const struct key *key)
+{
+	return (struct user_key_payload *)rcu_dereference_key(key);
+}
+
+#endif /* CONFIG_KEYS */
 
 #endif /* _KEYS_USER_TYPE_H */
diff --git a/include/linux/key-type.h b/include/linux/key-type.h
index ff9f1d3..7463355 100644
--- a/include/linux/key-type.h
+++ b/include/linux/key-type.h
@@ -40,8 +40,7 @@
  */
 struct key_preparsed_payload {
 	char		*description;	/* Proposed key description (or NULL) */
-	void		*type_data[2];	/* Private key-type data */
-	void		*payload[2];	/* Proposed payload */
+	union key_payload payload;	/* Proposed payload */
 	const void	*data;		/* Raw data */
 	size_t		datalen;	/* Raw datalen */
 	size_t		quotalen;	/* Quota length for proposed payload */
diff --git a/include/linux/key.h b/include/linux/key.h
index e1d4715..66f7052 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -89,6 +89,11 @@
 	size_t			desc_len;
 };
 
+union key_payload {
+	void __rcu		*rcu_data0;
+	void			*data[4];
+};
+
 /*****************************************************************************/
 /*
  * key reference with possession attribute handling
@@ -186,28 +191,18 @@
 		};
 	};
 
-	/* type specific data
-	 * - this is used by the keyring type to index the name
-	 */
-	union {
-		struct list_head	link;
-		unsigned long		x[2];
-		void			*p[2];
-		int			reject_error;
-	} type_data;
-
 	/* key data
 	 * - this is used to hold the data actually used in cryptography or
 	 *   whatever
 	 */
 	union {
-		union {
-			unsigned long		value;
-			void __rcu		*rcudata;
-			void			*data;
-			void			*data2[2];
-		} payload;
-		struct assoc_array keys;
+		union key_payload payload;
+		struct {
+			/* Keyring bits */
+			struct list_head name_link;
+			struct assoc_array keys;
+		};
+		int reject_error;
 	};
 };
 
@@ -336,12 +331,12 @@
 }
 
 #define rcu_dereference_key(KEY)					\
-	(rcu_dereference_protected((KEY)->payload.rcudata,		\
+	(rcu_dereference_protected((KEY)->payload.rcu_data0,		\
 				   rwsem_is_locked(&((struct key *)(KEY))->sem)))
 
 #define rcu_assign_keypointer(KEY, PAYLOAD)				\
 do {									\
-	rcu_assign_pointer((KEY)->payload.rcudata, (PAYLOAD));		\
+	rcu_assign_pointer((KEY)->payload.rcu_data0, (PAYLOAD));	\
 } while (0)
 
 #ifdef CONFIG_SYSCTL
diff --git a/kernel/.gitignore b/kernel/.gitignore
index 790d83c..b3097bd 100644
--- a/kernel/.gitignore
+++ b/kernel/.gitignore
@@ -5,4 +5,3 @@
 config_data.gz
 timeconst.h
 hz.bc
-x509_certificate_list
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
index bd62f5c..6528a79 100644
--- a/kernel/module_signing.c
+++ b/kernel/module_signing.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/errno.h>
 #include <keys/system_keyring.h>
 #include <crypto/public_key.h>
 #include "module-internal.h"
diff --git a/lib/digsig.c b/lib/digsig.c
index ae05ea39..07be6c1 100644
--- a/lib/digsig.c
+++ b/lib/digsig.c
@@ -79,12 +79,13 @@
 	unsigned char *out1 = NULL;
 	const char *m;
 	MPI in = NULL, res = NULL, pkey[2];
-	uint8_t *p, *datap, *endp;
-	struct user_key_payload *ukp;
+	uint8_t *p, *datap;
+	const uint8_t *endp;
+	const struct user_key_payload *ukp;
 	struct pubkey_hdr *pkh;
 
 	down_read(&key->sem);
-	ukp = key->payload.data;
+	ukp = user_key_payload(key);
 
 	if (ukp->datalen < sizeof(*pkh))
 		goto err1;
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
index 54a00d6..78f098a 100644
--- a/net/ceph/ceph_common.c
+++ b/net/ceph/ceph_common.c
@@ -318,7 +318,7 @@
 		goto out;
 	}
 
-	ckey = ukey->payload.data;
+	ckey = ukey->payload.data[0];
 	err = ceph_crypto_key_clone(dst, ckey);
 	if (err)
 		goto out_key;
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c
index 4440edc..42e8649 100644
--- a/net/ceph/crypto.c
+++ b/net/ceph/crypto.c
@@ -537,7 +537,7 @@
 	if (ret < 0)
 		goto err_ckey;
 
-	prep->payload[0] = ckey;
+	prep->payload.data[0] = ckey;
 	prep->quotalen = datalen;
 	return 0;
 
@@ -549,14 +549,14 @@
 
 static void ceph_key_free_preparse(struct key_preparsed_payload *prep)
 {
-	struct ceph_crypto_key *ckey = prep->payload[0];
+	struct ceph_crypto_key *ckey = prep->payload.data[0];
 	ceph_crypto_key_destroy(ckey);
 	kfree(ckey);
 }
 
 static void ceph_key_destroy(struct key *key)
 {
-	struct ceph_crypto_key *ckey = key->payload.data;
+	struct ceph_crypto_key *ckey = key->payload.data[0];
 
 	ceph_crypto_key_destroy(ckey);
 	kfree(ckey);
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
index 31cd4fd..c79b85e 100644
--- a/net/dns_resolver/dns_key.c
+++ b/net/dns_resolver/dns_key.c
@@ -122,7 +122,7 @@
 					goto bad_option_value;
 
 				kdebug("dns error no. = %lu", derrno);
-				prep->type_data[0] = ERR_PTR(-derrno);
+				prep->payload.data[dns_key_error] = ERR_PTR(-derrno);
 				continue;
 			}
 
@@ -137,8 +137,8 @@
 
 	/* don't cache the result if we're caching an error saying there's no
 	 * result */
-	if (prep->type_data[0]) {
-		kleave(" = 0 [h_error %ld]", PTR_ERR(prep->type_data[0]));
+	if (prep->payload.data[dns_key_error]) {
+		kleave(" = 0 [h_error %ld]", PTR_ERR(prep->payload.data[dns_key_error]));
 		return 0;
 	}
 
@@ -155,7 +155,7 @@
 	memcpy(upayload->data, data, result_len);
 	upayload->data[result_len] = '\0';
 
-	prep->payload[0] = upayload;
+	prep->payload.data[dns_key_data] = upayload;
 	kleave(" = 0");
 	return 0;
 }
@@ -167,7 +167,7 @@
 {
 	pr_devel("==>%s()\n", __func__);
 
-	kfree(prep->payload[0]);
+	kfree(prep->payload.data[dns_key_data]);
 }
 
 /*
@@ -223,10 +223,10 @@
  */
 static void dns_resolver_describe(const struct key *key, struct seq_file *m)
 {
-	int err = key->type_data.x[0];
-
 	seq_puts(m, key->description);
 	if (key_is_instantiated(key)) {
+		int err = PTR_ERR(key->payload.data[dns_key_error]);
+
 		if (err)
 			seq_printf(m, ": %d", err);
 		else
@@ -241,8 +241,10 @@
 static long dns_resolver_read(const struct key *key,
 			      char __user *buffer, size_t buflen)
 {
-	if (key->type_data.x[0])
-		return key->type_data.x[0];
+	int err = PTR_ERR(key->payload.data[dns_key_error]);
+
+	if (err)
+		return err;
 
 	return user_read(key, buffer, buflen);
 }
diff --git a/net/dns_resolver/dns_query.c b/net/dns_resolver/dns_query.c
index 39d2c39..4677b6f 100644
--- a/net/dns_resolver/dns_query.c
+++ b/net/dns_resolver/dns_query.c
@@ -70,7 +70,7 @@
 	      const char *options, char **_result, time_t *_expiry)
 {
 	struct key *rkey;
-	struct user_key_payload *upayload;
+	const struct user_key_payload *upayload;
 	const struct cred *saved_cred;
 	size_t typelen, desclen;
 	char *desc, *cp;
@@ -137,12 +137,11 @@
 		goto put;
 
 	/* If the DNS server gave an error, return that to the caller */
-	ret = rkey->type_data.x[0];
+	ret = PTR_ERR(rkey->payload.data[dns_key_error]);
 	if (ret)
 		goto put;
 
-	upayload = rcu_dereference_protected(rkey->payload.data,
-					     lockdep_is_held(&rkey->sem));
+	upayload = user_key_payload(rkey);
 	len = upayload->datalen;
 
 	ret = -ENOMEM;
diff --git a/net/dns_resolver/internal.h b/net/dns_resolver/internal.h
index 7af1ed3..0c570d4 100644
--- a/net/dns_resolver/internal.h
+++ b/net/dns_resolver/internal.h
@@ -23,6 +23,14 @@
 #include <linux/sched.h>
 
 /*
+ * Layout of key payload words.
+ */
+enum {
+	dns_key_data,
+	dns_key_error,
+};
+
+/*
  * dns_key.c
  */
 extern const struct cred *dns_resolver_cache;
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 25d60ed..1f8a144 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -305,7 +305,7 @@
 
 	if (!key)
 		key = rx->key;
-	if (key && !key->payload.data)
+	if (key && !key->payload.data[0])
 		key = NULL; /* a no-security key */
 
 	bundle = rxrpc_get_bundle(rx, trans, key, service_id, gfp);
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c
index db0f39f..da3cc09 100644
--- a/net/rxrpc/ar-key.c
+++ b/net/rxrpc/ar-key.c
@@ -148,10 +148,10 @@
 		       token->kad->ticket[6], token->kad->ticket[7]);
 
 	/* count the number of tokens attached */
-	prep->type_data[0] = (void *)((unsigned long)prep->type_data[0] + 1);
+	prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 1);
 
 	/* attach the data */
-	for (pptoken = (struct rxrpc_key_token **)&prep->payload[0];
+	for (pptoken = (struct rxrpc_key_token **)&prep->payload.data[0];
 	     *pptoken;
 	     pptoken = &(*pptoken)->next)
 		continue;
@@ -522,7 +522,7 @@
 		goto inval;
 
 	/* attach the payload */
-	for (pptoken = (struct rxrpc_key_token **)&prep->payload[0];
+	for (pptoken = (struct rxrpc_key_token **)&prep->payload.data[0];
 	     *pptoken;
 	     pptoken = &(*pptoken)->next)
 		continue;
@@ -764,10 +764,10 @@
 	memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length);
 
 	/* count the number of tokens attached */
-	prep->type_data[0] = (void *)((unsigned long)prep->type_data[0] + 1);
+	prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 1);
 
 	/* attach the data */
-	pp = (struct rxrpc_key_token **)&prep->payload[0];
+	pp = (struct rxrpc_key_token **)&prep->payload.data[0];
 	while (*pp)
 		pp = &(*pp)->next;
 	*pp = token;
@@ -814,7 +814,7 @@
  */
 static void rxrpc_free_preparse(struct key_preparsed_payload *prep)
 {
-	rxrpc_free_token_list(prep->payload[0]);
+	rxrpc_free_token_list(prep->payload.data[0]);
 }
 
 /*
@@ -831,7 +831,7 @@
 	if (prep->datalen != 8)
 		return -EINVAL;
 
-	memcpy(&prep->type_data, prep->data, 8);
+	memcpy(&prep->payload.data[2], prep->data, 8);
 
 	ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(ci)) {
@@ -842,7 +842,7 @@
 	if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0)
 		BUG();
 
-	prep->payload[0] = ci;
+	prep->payload.data[0] = ci;
 	_leave(" = 0");
 	return 0;
 }
@@ -852,8 +852,8 @@
  */
 static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep)
 {
-	if (prep->payload[0])
-		crypto_free_blkcipher(prep->payload[0]);
+	if (prep->payload.data[0])
+		crypto_free_blkcipher(prep->payload.data[0]);
 }
 
 /*
@@ -861,7 +861,7 @@
  */
 static void rxrpc_destroy(struct key *key)
 {
-	rxrpc_free_token_list(key->payload.data);
+	rxrpc_free_token_list(key->payload.data[0]);
 }
 
 /*
@@ -869,9 +869,9 @@
  */
 static void rxrpc_destroy_s(struct key *key)
 {
-	if (key->payload.data) {
-		crypto_free_blkcipher(key->payload.data);
-		key->payload.data = NULL;
+	if (key->payload.data[0]) {
+		crypto_free_blkcipher(key->payload.data[0]);
+		key->payload.data[0] = NULL;
 	}
 }
 
@@ -1070,7 +1070,7 @@
 	size += 1 * 4;	/* token count */
 
 	ntoks = 0;
-	for (token = key->payload.data; token; token = token->next) {
+	for (token = key->payload.data[0]; token; token = token->next) {
 		toksize = 4;	/* sec index */
 
 		switch (token->security_index) {
@@ -1163,7 +1163,7 @@
 	ENCODE(ntoks);
 
 	tok = 0;
-	for (token = key->payload.data; token; token = token->next) {
+	for (token = key->payload.data[0]; token; token = token->next) {
 		toksize = toksizes[tok++];
 		ENCODE(toksize);
 		oldxdr = xdr;
diff --git a/net/rxrpc/ar-output.c b/net/rxrpc/ar-output.c
index c004280..a40d3af 100644
--- a/net/rxrpc/ar-output.c
+++ b/net/rxrpc/ar-output.c
@@ -158,7 +158,7 @@
 			service_id = htons(srx->srx_service);
 		}
 		key = rx->key;
-		if (key && !rx->key->payload.data)
+		if (key && !rx->key->payload.data[0])
 			key = NULL;
 		bundle = rxrpc_get_bundle(rx, trans, key, service_id,
 					  GFP_KERNEL);
diff --git a/net/rxrpc/ar-security.c b/net/rxrpc/ar-security.c
index 49b3cc31..8334474 100644
--- a/net/rxrpc/ar-security.c
+++ b/net/rxrpc/ar-security.c
@@ -137,9 +137,9 @@
 	if (ret < 0)
 		return ret;
 
-	if (!key->payload.data)
+	token = key->payload.data[0];
+	if (!token)
 		return -EKEYREJECTED;
-	token = key->payload.data;
 
 	sec = rxrpc_security_lookup(token->security_index);
 	if (!sec)
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index f226709..d7a9ab5 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -67,7 +67,7 @@
 
 	_enter("{%d},{%x}", conn->debug_id, key_serial(conn->key));
 
-	token = conn->key->payload.data;
+	token = conn->key->payload.data[0];
 	conn->security_ix = token->security_index;
 
 	ci = crypto_alloc_blkcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC);
@@ -125,7 +125,7 @@
 	if (!conn->key)
 		return;
 
-	token = conn->key->payload.data;
+	token = conn->key->payload.data[0];
 	memcpy(&iv, token->kad->session_key, sizeof(iv));
 
 	desc.tfm = conn->cipher;
@@ -221,7 +221,7 @@
 	rxkhdr.checksum = 0;
 
 	/* encrypt from the session key */
-	token = call->conn->key->payload.data;
+	token = call->conn->key->payload.data[0];
 	memcpy(&iv, token->kad->session_key, sizeof(iv));
 	desc.tfm = call->conn->cipher;
 	desc.info = iv.x;
@@ -433,7 +433,7 @@
 	skb_to_sgvec(skb, sg, 0, skb->len);
 
 	/* decrypt from the session key */
-	token = call->conn->key->payload.data;
+	token = call->conn->key->payload.data[0];
 	memcpy(&iv, token->kad->session_key, sizeof(iv));
 	desc.tfm = call->conn->cipher;
 	desc.info = iv.x;
@@ -780,7 +780,7 @@
 	if (conn->security_level < min_level)
 		goto protocol_error;
 
-	token = conn->key->payload.data;
+	token = conn->key->payload.data[0];
 
 	/* build the response packet */
 	memset(&resp, 0, sizeof(resp));
@@ -848,12 +848,12 @@
 		}
 	}
 
-	ASSERT(conn->server_key->payload.data != NULL);
+	ASSERT(conn->server_key->payload.data[0] != NULL);
 	ASSERTCMP((unsigned long) ticket & 7UL, ==, 0);
 
-	memcpy(&iv, &conn->server_key->type_data, sizeof(iv));
+	memcpy(&iv, &conn->server_key->payload.data[2], sizeof(iv));
 
-	desc.tfm = conn->server_key->payload.data;
+	desc.tfm = conn->server_key->payload.data[0];
 	desc.info = iv.x;
 	desc.flags = 0;
 
diff --git a/scripts/extract-module-sig.pl b/scripts/extract-module-sig.pl
new file mode 100755
index 0000000..faac6f2
--- /dev/null
+++ b/scripts/extract-module-sig.pl
@@ -0,0 +1,136 @@
+#!/usr/bin/perl -w
+#
+# extract-mod-sig <part> <module-file>
+#
+# Reads the module file and writes out some or all of the signature
+# section to stdout.  Part is the bit to be written and is one of:
+#
+#  -0: The unsigned module, no signature data at all
+#  -a: All of the signature data, including magic number
+#  -d: Just the descriptor values as a sequence of numbers
+#  -n: Just the signer's name
+#  -k: Just the key ID
+#  -s: Just the crypto signature or PKCS#7 message
+#
+use strict;
+
+die "Format: $0 -[0adnks] module-file >out\n"
+    if ($#ARGV != 1);
+
+my $part = $ARGV[0];
+my $modfile = $ARGV[1];
+
+my $magic_number = "~Module signature appended~\n";
+
+#
+# Read the module contents
+#
+open FD, "<$modfile" || die $modfile;
+binmode(FD);
+my @st = stat(FD);
+die "$modfile" unless (@st);
+my $buf = "";
+my $len = sysread(FD, $buf, $st[7]);
+die "$modfile" unless (defined($len));
+die "Short read on $modfile\n" unless ($len == $st[7]);
+close(FD) || die $modfile;
+
+print STDERR "Read ", $len, " bytes from module file\n";
+
+die "The file is too short to have a sig magic number and descriptor\n"
+    if ($len < 12 + length($magic_number));
+
+#
+# Check for the magic number and extract the information block
+#
+my $p = $len - length($magic_number);
+my $raw_magic = substr($buf, $p);
+
+die "Magic number not found at $len\n"
+    if ($raw_magic ne $magic_number);
+print STDERR "Found magic number at $len\n";
+
+$p -= 12;
+my $raw_info = substr($buf, $p, 12);
+
+my @info = unpack("CCCCCxxxN", $raw_info);
+my ($algo, $hash, $id_type, $name_len, $kid_len, $sig_len) = @info;
+
+if ($id_type == 0) {
+    print STDERR "Found PGP key identifier\n";
+} elsif ($id_type == 1) {
+    print STDERR "Found X.509 cert identifier\n";
+} elsif ($id_type == 2) {
+    print STDERR "Found PKCS#7/CMS encapsulation\n";
+} else {
+    print STDERR "Found unsupported identifier type $id_type\n";
+}
+
+#
+# Extract the three pieces of info data
+#
+die "Insufficient name+kid+sig data in file\n"
+    unless ($p >= $name_len + $kid_len + $sig_len);
+
+$p -= $sig_len;
+my $raw_sig = substr($buf, $p, $sig_len);
+$p -= $kid_len;
+my $raw_kid = substr($buf, $p, $kid_len);
+$p -= $name_len;
+my $raw_name = substr($buf, $p, $name_len);
+
+my $module_len = $p;
+
+if ($sig_len > 0) {
+    print STDERR "Found $sig_len bytes of signature [";
+    my $n = $sig_len > 16 ? 16 : $sig_len;
+    foreach my $i (unpack("C" x $n, substr($raw_sig, 0, $n))) {
+	printf STDERR "%02x", $i;
+    }
+    print STDERR "]\n";
+}
+
+if ($kid_len > 0) {
+    print STDERR "Found $kid_len bytes of key identifier [";
+    my $n = $kid_len > 16 ? 16 : $kid_len;
+    foreach my $i (unpack("C" x $n, substr($raw_kid, 0, $n))) {
+	printf STDERR "%02x", $i;
+    }
+    print STDERR "]\n";
+}
+
+if ($name_len > 0) {
+    print STDERR "Found $name_len bytes of signer's name [$raw_name]\n";
+}
+
+#
+# Produce the requested output
+#
+if ($part eq "-0") {
+    # The unsigned module, no signature data at all
+    binmode(STDOUT);
+    print substr($buf, 0, $module_len);
+} elsif ($part eq "-a") {
+    # All of the signature data, including magic number
+    binmode(STDOUT);
+    print substr($buf, $module_len);
+} elsif ($part eq "-d") {
+    # Just the descriptor values as a sequence of numbers
+    print join(" ", @info), "\n";
+} elsif ($part eq "-n") {
+    # Just the signer's name
+    print STDERR "No signer's name for PKCS#7 message type sig\n"
+	if ($id_type == 2);
+    binmode(STDOUT);
+    print $raw_name;
+} elsif ($part eq "-k") {
+    # Just the key identifier
+    print STDERR "No key ID for PKCS#7 message type sig\n"
+	if ($id_type == 2);
+    binmode(STDOUT);
+    print $raw_kid;
+} elsif ($part eq "-s") {
+    # Just the crypto signature or PKCS#7 message
+    binmode(STDOUT);
+    print $raw_sig;
+}
diff --git a/scripts/extract-sys-certs.pl b/scripts/extract-sys-certs.pl
new file mode 100755
index 0000000..d476e7d
--- /dev/null
+++ b/scripts/extract-sys-certs.pl
@@ -0,0 +1,144 @@
+#!/usr/bin/perl -w
+#
+use strict;
+use Math::BigInt;
+use Fcntl "SEEK_SET";
+
+die "Format: $0 [-s <systemmap-file>] <vmlinux-file> <keyring-file>\n"
+    if ($#ARGV != 1 && $#ARGV != 3 ||
+	$#ARGV == 3 && $ARGV[0] ne "-s");
+
+my $sysmap = "";
+if ($#ARGV == 3) {
+    shift;
+    $sysmap = $ARGV[0];
+    shift;
+}
+
+my $vmlinux = $ARGV[0];
+my $keyring = $ARGV[1];
+
+#
+# Parse the vmlinux section table
+#
+open FD, "objdump -h $vmlinux |" || die $vmlinux;
+my @lines = <FD>;
+close(FD) || die $vmlinux;
+
+my @sections = ();
+
+foreach my $line (@lines) {
+    chomp($line);
+    if ($line =~ /\s*([0-9]+)\s+(\S+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+2[*][*]([0-9]+)/
+	) {
+	my $seg  = $1;
+	my $name = $2;
+	my $len  = Math::BigInt->new("0x" . $3);
+	my $vma  = Math::BigInt->new("0x" . $4);
+	my $lma  = Math::BigInt->new("0x" . $5);
+	my $foff = Math::BigInt->new("0x" . $6);
+	my $align = 2 ** $7;
+
+	push @sections, { name => $name,
+			  vma => $vma,
+			  len => $len,
+			  foff => $foff };
+    }
+}
+
+print "Have $#sections sections\n";
+
+#
+# Try and parse the vmlinux symbol table.  If the vmlinux file has been created
+# from a vmlinuz file with extract-vmlinux then the symbol table will be empty.
+#
+open FD, "nm $vmlinux 2>/dev/null |" || die $vmlinux;
+@lines = <FD>;
+close(FD) || die $vmlinux;
+
+my %symbols = ();
+my $nr_symbols = 0;
+
+sub parse_symbols(@) {
+    foreach my $line (@_) {
+	chomp($line);
+	if ($line =~ /([0-9a-f]+)\s([a-zA-Z])\s(\S+)/
+	    ) {
+	    my $addr = "0x" . $1;
+	    my $type = $2;
+	    my $name = $3;
+
+	    $symbols{$name} = $addr;
+	    $nr_symbols++;
+	}
+    }
+}
+parse_symbols(@lines);
+
+if ($nr_symbols == 0 && $sysmap ne "") {
+    print "No symbols in vmlinux, trying $sysmap\n";
+
+    open FD, "<$sysmap" || die $sysmap;
+    @lines = <FD>;
+    close(FD) || die $sysmap;
+    parse_symbols(@lines);
+}
+
+die "No symbols available\n"
+    if ($nr_symbols == 0);
+
+print "Have $nr_symbols symbols\n";
+
+die "Can't find system certificate list"
+    unless (exists($symbols{"__cert_list_start"}) &&
+	    exists($symbols{"__cert_list_end"}));
+
+my $start = Math::BigInt->new($symbols{"__cert_list_start"});
+my $end = Math::BigInt->new($symbols{"__cert_list_end"});
+my $size = $end - $start;
+
+printf "Have %u bytes of certs at VMA 0x%x\n", $size, $start;
+
+my $s = undef;
+foreach my $sec (@sections) {
+    my $s_name = $sec->{name};
+    my $s_vma = $sec->{vma};
+    my $s_len = $sec->{len};
+    my $s_foff = $sec->{foff};
+    my $s_vend = $s_vma + $s_len;
+
+    next unless ($start >= $s_vma);
+    next if ($start >= $s_vend);
+
+    die "Cert object partially overflows section $s_name\n"
+	if ($end > $s_vend);
+
+    die "Cert object in multiple sections: ", $s_name, " and ", $s->{name}, "\n"
+	if ($s);
+    $s = $sec;
+}
+
+die "Cert object not inside a section\n"
+    unless ($s);
+
+print "Certificate list in section ", $s->{name}, "\n";
+
+my $foff = $start - $s->{vma} + $s->{foff};
+
+printf "Certificate list at file offset 0x%x\n", $foff;
+
+open FD, "<$vmlinux" || die $vmlinux;
+binmode(FD);
+die $vmlinux if (!defined(sysseek(FD, $foff, SEEK_SET)));
+my $buf = "";
+my $len = sysread(FD, $buf, $size);
+die "$vmlinux" if (!defined($len));
+die "Short read on $vmlinux\n" if ($len != $size);
+close(FD) || die $vmlinux;
+
+open FD, ">$keyring" || die $keyring;
+binmode(FD);
+$len = syswrite(FD, $buf, $size);
+die "$keyring" if (!defined($len));
+die "Short write on $keyring\n" if ($len != $size);
+close(FD) || die $keyring;
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index 159ef3e..461f8d8 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -247,7 +247,7 @@
 		return -ENOENT;
 
 	down_read(&evm_key->sem);
-	ekp = evm_key->payload.data;
+	ekp = evm_key->payload.data[0];
 	if (ekp->decrypted_datalen > MAX_KEY_SIZE) {
 		rc = -EINVAL;
 		goto out;
diff --git a/security/keys/big_key.c b/security/keys/big_key.c
index b6adb94..907c152 100644
--- a/security/keys/big_key.c
+++ b/security/keys/big_key.c
@@ -21,6 +21,16 @@
 MODULE_LICENSE("GPL");
 
 /*
+ * Layout of key payload words.
+ */
+enum {
+	big_key_data,
+	big_key_path,
+	big_key_path_2nd_part,
+	big_key_len,
+};
+
+/*
  * If the data is under this limit, there's no point creating a shm file to
  * hold it as the permanently resident metadata for the shmem fs will be at
  * least as large as the data.
@@ -47,7 +57,7 @@
  */
 int big_key_preparse(struct key_preparsed_payload *prep)
 {
-	struct path *path = (struct path *)&prep->payload;
+	struct path *path = (struct path *)&prep->payload.data[big_key_path];
 	struct file *file;
 	ssize_t written;
 	size_t datalen = prep->datalen;
@@ -60,7 +70,7 @@
 	/* Set an arbitrary quota */
 	prep->quotalen = 16;
 
-	prep->type_data[1] = (void *)(unsigned long)datalen;
+	prep->payload.data[big_key_len] = (void *)(unsigned long)datalen;
 
 	if (datalen > BIG_KEY_FILE_THRESHOLD) {
 		/* Create a shmem file to store the data in.  This will permit the data
@@ -94,7 +104,8 @@
 		if (!data)
 			return -ENOMEM;
 
-		prep->payload[0] = memcpy(data, prep->data, prep->datalen);
+		prep->payload.data[big_key_data] = data;
+		memcpy(data, prep->data, prep->datalen);
 	}
 	return 0;
 
@@ -110,10 +121,10 @@
 void big_key_free_preparse(struct key_preparsed_payload *prep)
 {
 	if (prep->datalen > BIG_KEY_FILE_THRESHOLD) {
-		struct path *path = (struct path *)&prep->payload;
+		struct path *path = (struct path *)&prep->payload.data[big_key_path];
 		path_put(path);
 	} else {
-		kfree(prep->payload[0]);
+		kfree(prep->payload.data[big_key_data]);
 	}
 }
 
@@ -123,11 +134,12 @@
  */
 void big_key_revoke(struct key *key)
 {
-	struct path *path = (struct path *)&key->payload.data2;
+	struct path *path = (struct path *)&key->payload.data[big_key_path];
 
 	/* clear the quota */
 	key_payload_reserve(key, 0);
-	if (key_is_instantiated(key) && key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD)
+	if (key_is_instantiated(key) &&
+	    (size_t)key->payload.data[big_key_len] > BIG_KEY_FILE_THRESHOLD)
 		vfs_truncate(path, 0);
 }
 
@@ -136,14 +148,16 @@
  */
 void big_key_destroy(struct key *key)
 {
-	if (key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD) {
-		struct path *path = (struct path *)&key->payload.data2;
+	size_t datalen = (size_t)key->payload.data[big_key_len];
+
+	if (datalen) {
+		struct path *path = (struct path *)&key->payload.data[big_key_path];
 		path_put(path);
 		path->mnt = NULL;
 		path->dentry = NULL;
 	} else {
-		kfree(key->payload.data);
-		key->payload.data = NULL;
+		kfree(key->payload.data[big_key_data]);
+		key->payload.data[big_key_data] = NULL;
 	}
 }
 
@@ -152,12 +166,12 @@
  */
 void big_key_describe(const struct key *key, struct seq_file *m)
 {
-	unsigned long datalen = key->type_data.x[1];
+	size_t datalen = (size_t)key->payload.data[big_key_len];
 
 	seq_puts(m, key->description);
 
 	if (key_is_instantiated(key))
-		seq_printf(m, ": %lu [%s]",
+		seq_printf(m, ": %zu [%s]",
 			   datalen,
 			   datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff");
 }
@@ -168,14 +182,14 @@
  */
 long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
 {
-	unsigned long datalen = key->type_data.x[1];
+	size_t datalen = (size_t)key->payload.data[big_key_len];
 	long ret;
 
 	if (!buffer || buflen < datalen)
 		return datalen;
 
 	if (datalen > BIG_KEY_FILE_THRESHOLD) {
-		struct path *path = (struct path *)&key->payload.data2;
+		struct path *path = (struct path *)&key->payload.data[big_key_path];
 		struct file *file;
 		loff_t pos;
 
@@ -190,7 +204,8 @@
 			ret = -EIO;
 	} else {
 		ret = datalen;
-		if (copy_to_user(buffer, key->payload.data, datalen) != 0)
+		if (copy_to_user(buffer, key->payload.data[big_key_data],
+				 datalen) != 0)
 			ret = -EFAULT;
 	}
 
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index 7bed4ad..927db9f 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -303,10 +303,10 @@
  *
  * Use a user provided key to encrypt/decrypt an encrypted-key.
  */
-static struct key *request_user_key(const char *master_desc, u8 **master_key,
+static struct key *request_user_key(const char *master_desc, const u8 **master_key,
 				    size_t *master_keylen)
 {
-	struct user_key_payload *upayload;
+	const struct user_key_payload *upayload;
 	struct key *ukey;
 
 	ukey = request_key(&key_type_user, master_desc, NULL);
@@ -314,7 +314,7 @@
 		goto error;
 
 	down_read(&ukey->sem);
-	upayload = ukey->payload.data;
+	upayload = user_key_payload(ukey);
 	*master_key = upayload->data;
 	*master_keylen = upayload->datalen;
 error:
@@ -426,7 +426,7 @@
 }
 
 static struct key *request_master_key(struct encrypted_key_payload *epayload,
-				      u8 **master_key, size_t *master_keylen)
+				      const u8 **master_key, size_t *master_keylen)
 {
 	struct key *mkey = NULL;
 
@@ -653,7 +653,7 @@
 {
 	struct key *mkey;
 	u8 derived_key[HASH_SIZE];
-	u8 *master_key;
+	const u8 *master_key;
 	u8 *hmac;
 	const char *hex_encoded_data;
 	unsigned int encrypted_datalen;
@@ -837,7 +837,7 @@
  */
 static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
 {
-	struct encrypted_key_payload *epayload = key->payload.data;
+	struct encrypted_key_payload *epayload = key->payload.data[0];
 	struct encrypted_key_payload *new_epayload;
 	char *buf;
 	char *new_master_desc = NULL;
@@ -896,7 +896,7 @@
 {
 	struct encrypted_key_payload *epayload;
 	struct key *mkey;
-	u8 *master_key;
+	const u8 *master_key;
 	size_t master_keylen;
 	char derived_key[HASH_SIZE];
 	char *ascii_buf;
@@ -957,13 +957,13 @@
  */
 static void encrypted_destroy(struct key *key)
 {
-	struct encrypted_key_payload *epayload = key->payload.data;
+	struct encrypted_key_payload *epayload = key->payload.data[0];
 
 	if (!epayload)
 		return;
 
 	memset(epayload->decrypted_data, 0, epayload->decrypted_datalen);
-	kfree(key->payload.data);
+	kfree(key->payload.data[0]);
 }
 
 struct key_type key_type_encrypted = {
diff --git a/security/keys/encrypted-keys/encrypted.h b/security/keys/encrypted-keys/encrypted.h
index 8136a2d..47802c0 100644
--- a/security/keys/encrypted-keys/encrypted.h
+++ b/security/keys/encrypted-keys/encrypted.h
@@ -5,10 +5,10 @@
 #if defined(CONFIG_TRUSTED_KEYS) || \
   (defined(CONFIG_TRUSTED_KEYS_MODULE) && defined(CONFIG_ENCRYPTED_KEYS_MODULE))
 extern struct key *request_trusted_key(const char *trusted_desc,
-				       u8 **master_key, size_t *master_keylen);
+				       const u8 **master_key, size_t *master_keylen);
 #else
 static inline struct key *request_trusted_key(const char *trusted_desc,
-					      u8 **master_key,
+					      const u8 **master_key,
 					      size_t *master_keylen)
 {
 	return ERR_PTR(-EOPNOTSUPP);
diff --git a/security/keys/encrypted-keys/masterkey_trusted.c b/security/keys/encrypted-keys/masterkey_trusted.c
index 013f7e5..b5b4812 100644
--- a/security/keys/encrypted-keys/masterkey_trusted.c
+++ b/security/keys/encrypted-keys/masterkey_trusted.c
@@ -29,7 +29,7 @@
  * data, trusted key type data is not visible decrypted from userspace.
  */
 struct key *request_trusted_key(const char *trusted_desc,
-				u8 **master_key, size_t *master_keylen)
+				const u8 **master_key, size_t *master_keylen)
 {
 	struct trusted_key_payload *tpayload;
 	struct key *tkey;
@@ -39,7 +39,7 @@
 		goto error;
 
 	down_read(&tkey->sem);
-	tpayload = tkey->payload.data;
+	tpayload = tkey->payload.data[0];
 	*master_key = tpayload->key;
 	*master_keylen = tpayload->key_len;
 error:
diff --git a/security/keys/key.c b/security/keys/key.c
index aee2ec5..ab7997d 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -278,7 +278,7 @@
 
 	key->index_key.desc_len = desclen;
 	key->index_key.description = kmemdup(desc, desclen + 1, GFP_KERNEL);
-	if (!key->description)
+	if (!key->index_key.description)
 		goto no_memory_3;
 
 	atomic_set(&key->usage, 1);
@@ -554,7 +554,7 @@
 	if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
 		/* mark the key as being negatively instantiated */
 		atomic_inc(&key->user->nikeys);
-		key->type_data.reject_error = -error;
+		key->reject_error = -error;
 		smp_wmb();
 		set_bit(KEY_FLAG_NEGATIVE, &key->flags);
 		set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
@@ -1046,14 +1046,14 @@
 
 	ret = key_payload_reserve(key, prep->quotalen);
 	if (ret == 0) {
-		key->type_data.p[0] = prep->type_data[0];
-		key->type_data.p[1] = prep->type_data[1];
-		rcu_assign_keypointer(key, prep->payload[0]);
-		key->payload.data2[1] = prep->payload[1];
-		prep->type_data[0] = NULL;
-		prep->type_data[1] = NULL;
-		prep->payload[0] = NULL;
-		prep->payload[1] = NULL;
+		rcu_assign_keypointer(key, prep->payload.data[0]);
+		key->payload.data[1] = prep->payload.data[1];
+		key->payload.data[2] = prep->payload.data[2];
+		key->payload.data[3] = prep->payload.data[3];
+		prep->payload.data[0] = NULL;
+		prep->payload.data[1] = NULL;
+		prep->payload.data[2] = NULL;
+		prep->payload.data[3] = NULL;
 	}
 	pr_devel("<==%s() = %d\n", __func__, ret);
 	return ret;
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 0b9ec78..fb111ea 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -67,7 +67,6 @@
 	char type[32], *description;
 	void *payload;
 	long ret;
-	bool vm;
 
 	ret = -EINVAL;
 	if (plen > 1024 * 1024 - 1)
@@ -98,14 +97,12 @@
 	/* pull the payload in if one was supplied */
 	payload = NULL;
 
-	vm = false;
 	if (_payload) {
 		ret = -ENOMEM;
 		payload = kmalloc(plen, GFP_KERNEL | __GFP_NOWARN);
 		if (!payload) {
 			if (plen <= PAGE_SIZE)
 				goto error2;
-			vm = true;
 			payload = vmalloc(plen);
 			if (!payload)
 				goto error2;
@@ -138,10 +135,7 @@
 
 	key_ref_put(keyring_ref);
  error3:
-	if (!vm)
-		kfree(payload);
-	else
-		vfree(payload);
+	kvfree(payload);
  error2:
 	kfree(description);
  error:
@@ -1033,7 +1027,7 @@
 	if (!instkey)
 		goto error;
 
-	rka = instkey->payload.data;
+	rka = instkey->payload.data[0];
 	if (rka->target_key->serial != id)
 		goto error;
 
@@ -1200,7 +1194,7 @@
 	if (!instkey)
 		goto error;
 
-	rka = instkey->payload.data;
+	rka = instkey->payload.data[0];
 	if (rka->target_key->serial != id)
 		goto error;
 
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index d334370..f931ccf 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -118,7 +118,7 @@
 		if (!keyring_name_hash[bucket].next)
 			INIT_LIST_HEAD(&keyring_name_hash[bucket]);
 
-		list_add_tail(&keyring->type_data.link,
+		list_add_tail(&keyring->name_link,
 			      &keyring_name_hash[bucket]);
 
 		write_unlock(&keyring_name_lock);
@@ -387,9 +387,9 @@
 	if (keyring->description) {
 		write_lock(&keyring_name_lock);
 
-		if (keyring->type_data.link.next != NULL &&
-		    !list_empty(&keyring->type_data.link))
-			list_del(&keyring->type_data.link);
+		if (keyring->name_link.next != NULL &&
+		    !list_empty(&keyring->name_link))
+			list_del(&keyring->name_link);
 
 		write_unlock(&keyring_name_lock);
 	}
@@ -572,7 +572,7 @@
 		/* we set a different error code if we pass a negative key */
 		if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
 			smp_rmb();
-			ctx->result = ERR_PTR(key->type_data.reject_error);
+			ctx->result = ERR_PTR(key->reject_error);
 			kleave(" = %d [neg]", ctx->skipped_ret);
 			goto skipped;
 		}
@@ -990,7 +990,7 @@
 		 * that's readable and that hasn't been revoked */
 		list_for_each_entry(keyring,
 				    &keyring_name_hash[bucket],
-				    type_data.link
+				    name_link
 				    ) {
 			if (!kuid_has_mapping(current_user_ns(), keyring->user->uid))
 				continue;
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 43b4cdd..a3f85d2 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -457,7 +457,7 @@
 		down_read(&cred->request_key_auth->sem);
 
 		if (key_validate(ctx->cred->request_key_auth) == 0) {
-			rka = ctx->cred->request_key_auth->payload.data;
+			rka = ctx->cred->request_key_auth->payload.data[0];
 
 			ctx->cred = rka->cred;
 			key_ref = search_process_keyrings(ctx);
@@ -647,7 +647,7 @@
 			key_ref = ERR_PTR(-EKEYREVOKED);
 			key = NULL;
 		} else {
-			rka = ctx.cred->request_key_auth->payload.data;
+			rka = ctx.cred->request_key_auth->payload.data[0];
 			key = rka->dest_keyring;
 			__key_get(key);
 		}
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 486ef6f..95d5cfc 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -271,7 +271,7 @@
 			if (cred->request_key_auth) {
 				authkey = cred->request_key_auth;
 				down_read(&authkey->sem);
-				rka = authkey->payload.data;
+				rka = authkey->payload.data[0];
 				if (!test_bit(KEY_FLAG_REVOKED,
 					      &authkey->flags))
 					dest_keyring =
@@ -593,7 +593,7 @@
 		return -ERESTARTSYS;
 	if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
 		smp_rmb();
-		return key->type_data.reject_error;
+		return key->reject_error;
 	}
 	return key_validate(key);
 }
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index 5d672f7..4f0f112 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -59,7 +59,7 @@
 static int request_key_auth_instantiate(struct key *key,
 					struct key_preparsed_payload *prep)
 {
-	key->payload.data = (struct request_key_auth *)prep->data;
+	key->payload.data[0] = (struct request_key_auth *)prep->data;
 	return 0;
 }
 
@@ -69,7 +69,7 @@
 static void request_key_auth_describe(const struct key *key,
 				      struct seq_file *m)
 {
-	struct request_key_auth *rka = key->payload.data;
+	struct request_key_auth *rka = key->payload.data[0];
 
 	seq_puts(m, "key:");
 	seq_puts(m, key->description);
@@ -84,7 +84,7 @@
 static long request_key_auth_read(const struct key *key,
 				  char __user *buffer, size_t buflen)
 {
-	struct request_key_auth *rka = key->payload.data;
+	struct request_key_auth *rka = key->payload.data[0];
 	size_t datalen;
 	long ret;
 
@@ -110,7 +110,7 @@
  */
 static void request_key_auth_revoke(struct key *key)
 {
-	struct request_key_auth *rka = key->payload.data;
+	struct request_key_auth *rka = key->payload.data[0];
 
 	kenter("{%d}", key->serial);
 
@@ -125,7 +125,7 @@
  */
 static void request_key_auth_destroy(struct key *key)
 {
-	struct request_key_auth *rka = key->payload.data;
+	struct request_key_auth *rka = key->payload.data[0];
 
 	kenter("{%d}", key->serial);
 
@@ -179,7 +179,7 @@
 		if (test_bit(KEY_FLAG_REVOKED, &cred->request_key_auth->flags))
 			goto auth_key_revoked;
 
-		irka = cred->request_key_auth->payload.data;
+		irka = cred->request_key_auth->payload.data[0];
 		rka->cred = get_cred(irka->cred);
 		rka->pid = irka->pid;
 
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index d3633cf..903dace 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -1007,7 +1007,7 @@
  */
 static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
 {
-	struct trusted_key_payload *p = key->payload.data;
+	struct trusted_key_payload *p = key->payload.data[0];
 	struct trusted_key_payload *new_p;
 	struct trusted_key_options *new_o;
 	size_t datalen = prep->datalen;
@@ -1114,12 +1114,12 @@
  */
 static void trusted_destroy(struct key *key)
 {
-	struct trusted_key_payload *p = key->payload.data;
+	struct trusted_key_payload *p = key->payload.data[0];
 
 	if (!p)
 		return;
 	memset(p->key, 0, p->key_len);
-	kfree(key->payload.data);
+	kfree(key->payload.data[0]);
 }
 
 struct key_type key_type_trusted = {
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 36b47bb..28cb30f 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -74,7 +74,7 @@
 
 	/* attach the data */
 	prep->quotalen = datalen;
-	prep->payload[0] = upayload;
+	prep->payload.data[0] = upayload;
 	upayload->datalen = datalen;
 	memcpy(upayload->data, prep->data, datalen);
 	return 0;
@@ -86,7 +86,7 @@
  */
 void user_free_preparse(struct key_preparsed_payload *prep)
 {
-	kfree(prep->payload[0]);
+	kfree(prep->payload.data[0]);
 }
 EXPORT_SYMBOL_GPL(user_free_preparse);
 
@@ -120,7 +120,7 @@
 
 	if (ret == 0) {
 		/* attach the new data, displacing the old */
-		zap = key->payload.data;
+		zap = key->payload.data[0];
 		rcu_assign_keypointer(key, upayload);
 		key->expiry = 0;
 	}
@@ -140,7 +140,7 @@
  */
 void user_revoke(struct key *key)
 {
-	struct user_key_payload *upayload = key->payload.data;
+	struct user_key_payload *upayload = key->payload.data[0];
 
 	/* clear the quota */
 	key_payload_reserve(key, 0);
@@ -158,7 +158,7 @@
  */
 void user_destroy(struct key *key)
 {
-	struct user_key_payload *upayload = key->payload.data;
+	struct user_key_payload *upayload = key->payload.data[0];
 
 	kfree(upayload);
 }
@@ -183,10 +183,10 @@
  */
 long user_read(const struct key *key, char __user *buffer, size_t buflen)
 {
-	struct user_key_payload *upayload;
+	const struct user_key_payload *upayload;
 	long ret;
 
-	upayload = rcu_dereference_key(key);
+	upayload = user_key_payload(key);
 	ret = upayload->datalen;
 
 	/* we can return the data as is */