Commit 898de7d0 authored by David Howells's avatar David Howells
Browse files

KEYS: user_update should use copy of payload made during preparsing



The payload preparsing routine for user keys makes a copy of the payload
provided by the caller and stashes it in the key_preparsed_payload struct for
->instantiate() or ->update() to use.  However, ->update() takes another copy
of this to attach to the keyring.  ->update() should be using this directly
and clearing the pointer in the preparse data.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 93da17b1
Loading
Loading
Loading
Loading
+11 −31
Original line number Original line Diff line number Diff line
@@ -96,45 +96,25 @@ EXPORT_SYMBOL_GPL(user_free_preparse);
 */
 */
int user_update(struct key *key, struct key_preparsed_payload *prep)
int user_update(struct key *key, struct key_preparsed_payload *prep)
{
{
	struct user_key_payload *upayload, *zap;
	struct user_key_payload *zap = NULL;
	size_t datalen = prep->datalen;
	int ret;
	int ret;


	ret = -EINVAL;
	if (datalen <= 0 || datalen > 32767 || !prep->data)
		goto error;

	/* construct a replacement payload */
	ret = -ENOMEM;
	upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL);
	if (!upayload)
		goto error;

	upayload->datalen = datalen;
	memcpy(upayload->data, prep->data, datalen);

	/* check the quota and attach the new data */
	/* check the quota and attach the new data */
	zap = upayload;
	ret = key_payload_reserve(key, prep->datalen);

	if (ret < 0)
	ret = key_payload_reserve(key, datalen);
		return ret;


	if (ret == 0) {
	/* attach the new data, displacing the old */
	/* attach the new data, displacing the old */
	key->expiry = prep->expiry;
	if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags))
	if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags))
			zap = key->payload.data[0];
		zap = rcu_dereference_key(key);
		else
	rcu_assign_keypointer(key, prep->payload.data[0]);
			zap = NULL;
	prep->payload.data[0] = NULL;
		rcu_assign_keypointer(key, upayload);
		key->expiry = 0;
	}


	if (zap)
	if (zap)
		kfree_rcu(zap, rcu);
		kfree_rcu(zap, rcu);

error:
	return ret;
	return ret;
}
}

EXPORT_SYMBOL_GPL(user_update);
EXPORT_SYMBOL_GPL(user_update);


/*
/*