diff --git a/kernel/system_certificates.S b/kernel/system_certificates.S
index 552d47b2d463f10305668c47dfb5db7aa59c3d3a..4aef390671cbb9653fc5c64342f656694585f56c 100644
--- a/kernel/system_certificates.S
+++ b/kernel/system_certificates.S
@@ -1,12 +1,10 @@
 #include <linux/export.h>
 #include <linux/init.h>
 
-#define GLOBAL(name)	\
-	.globl VMLINUX_SYMBOL(name);	\
-	VMLINUX_SYMBOL(name):
-
 	__INITRODATA
 
-GLOBAL(system_certificate_list)
+	.globl VMLINUX_SYMBOL(system_certificate_list)
+VMLINUX_SYMBOL(system_certificate_list):
 	.incbin "kernel/x509_certificate_list"
-GLOBAL(system_certificate_list_end)
+	.globl VMLINUX_SYMBOL(system_certificate_list_end)
+VMLINUX_SYMBOL(system_certificate_list_end):
diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index 53d8748c95642e7adaea1f5aece6660212ad8556..a4f3f8c48d6e3f0aa8c5d7d21f900f425d517c71 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -38,7 +38,7 @@ config PERSISTENT_KEYRINGS
 	  removed if they expire (a default timeout is set upon creation).
 
 config BIG_KEYS
-	tristate "Large payload keys"
+	bool "Large payload keys"
 	depends on KEYS
 	depends on TMPFS
 	help
diff --git a/security/keys/big_key.c b/security/keys/big_key.c
index 5f9defc4a807268544cf9378d27f453f5a43d82a..2cf5e62d67afdf849c6208d55adb79cc5db7b2a4 100644
--- a/security/keys/big_key.c
+++ b/security/keys/big_key.c
@@ -71,8 +71,10 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
 		 * TODO: Encrypt the stored data with a temporary key.
 		 */
 		file = shmem_file_setup("", datalen, 0);
-		if (IS_ERR(file))
+		if (IS_ERR(file)) {
+			ret = PTR_ERR(file);
 			goto err_quota;
+		}
 
 		written = kernel_write(file, prep->data, prep->datalen, 0);
 		if (written != datalen) {
diff --git a/security/keys/key.c b/security/keys/key.c
index d331ea9ef380562d177c6c037d1493680ed48782..55d110f0acedc96d17bcc5f5903aaa743ed6cb32 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -557,9 +557,10 @@ int key_reject_and_link(struct key *key,
 	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;
+		smp_wmb();
 		set_bit(KEY_FLAG_NEGATIVE, &key->flags);
 		set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
-		key->type_data.reject_error = -error;
 		now = current_kernel_time();
 		key->expiry = now.tv_sec + timeout;
 		key_schedule_gc(key->expiry + key_gc_delay);
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 9b6f6e09b50ccdb82b55d88b493c41fd9920c66a..d80311e571c345a16142fb4fbe2255e234d6a6db 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -551,6 +551,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data)
 	if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) {
 		/* 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);
 			kleave(" = %d [neg]", ctx->skipped_ret);
 			goto skipped;
@@ -1062,12 +1063,6 @@ int __key_link_begin(struct key *keyring,
 	if (index_key->type == &key_type_keyring)
 		down_write(&keyring_serialise_link_sem);
 
-	/* check that we aren't going to overrun the user's quota */
-	ret = key_payload_reserve(keyring,
-				  keyring->datalen + KEYQUOTA_LINK_BYTES);
-	if (ret < 0)
-		goto error_sem;
-
 	/* Create an edit script that will insert/replace the key in the
 	 * keyring tree.
 	 */
@@ -1077,17 +1072,25 @@ int __key_link_begin(struct key *keyring,
 				  NULL);
 	if (IS_ERR(edit)) {
 		ret = PTR_ERR(edit);
-		goto error_quota;
+		goto error_sem;
+	}
+
+	/* If we're not replacing a link in-place then we're going to need some
+	 * extra quota.
+	 */
+	if (!edit->dead_leaf) {
+		ret = key_payload_reserve(keyring,
+					  keyring->datalen + KEYQUOTA_LINK_BYTES);
+		if (ret < 0)
+			goto error_cancel;
 	}
 
 	*_edit = edit;
 	kleave(" = 0");
 	return 0;
 
-error_quota:
-	/* undo the quota changes */
-	key_payload_reserve(keyring,
-			    keyring->datalen - KEYQUOTA_LINK_BYTES);
+error_cancel:
+	assoc_array_cancel_edit(edit);
 error_sem:
 	if (index_key->type == &key_type_keyring)
 		up_write(&keyring_serialise_link_sem);
@@ -1145,7 +1148,7 @@ void __key_link_end(struct key *keyring,
 	if (index_key->type == &key_type_keyring)
 		up_write(&keyring_serialise_link_sem);
 
-	if (edit) {
+	if (edit && !edit->dead_leaf) {
 		key_payload_reserve(keyring,
 				    keyring->datalen - KEYQUOTA_LINK_BYTES);
 		assoc_array_cancel_edit(edit);
@@ -1242,6 +1245,7 @@ int key_unlink(struct key *keyring, struct key *key)
 		goto error;
 
 	assoc_array_apply_edit(edit);
+	key_payload_reserve(keyring, keyring->datalen - KEYQUOTA_LINK_BYTES);
 	ret = 0;
 
 error:
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index df94827103d0c12001b970697ab7b6de16882283..381411941cc1abbc48a699b1c2c38042f1a05711 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -596,8 +596,10 @@ int wait_for_key_construction(struct key *key, bool intr)
 			  intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
 	if (ret < 0)
 		return ret;
-	if (test_bit(KEY_FLAG_NEGATIVE, &key->flags))
+	if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
+		smp_rmb();
 		return key->type_data.reject_error;
+	}
 	return key_validate(key);
 }
 EXPORT_SYMBOL(wait_for_key_construction);