summary refs log tree commit diff
path: root/security/keys/keyring.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys/keyring.c')
-rw-r--r--security/keys/keyring.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 8c05ebd7203d..d80311e571c3 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -1063,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.
 	 */
@@ -1078,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);
@@ -1146,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);
@@ -1243,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: