KEYS: user_update should use copy of payload made during preparsing
authorDavid Howells <dhowells@redhat.com>
Tue, 12 Apr 2016 18:54:58 +0000 (19:54 +0100)
committerDavid Howells <dhowells@redhat.com>
Tue, 12 Apr 2016 18:54:58 +0000 (19:54 +0100)
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: David Howells <dhowells@redhat.com>
security/keys/user_defined.c

index 8705d79..66b1840 100644 (file)
@@ -96,45 +96,25 @@ EXPORT_SYMBOL_GPL(user_free_preparse);
  */
 int user_update(struct key *key, struct key_preparsed_payload *prep)
 {
-       struct user_key_payload *upayload, *zap;
-       size_t datalen = prep->datalen;
+       struct user_key_payload *zap = NULL;
        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 */
-       zap = upayload;
-
-       ret = key_payload_reserve(key, datalen);
-
-       if (ret == 0) {
-               /* attach the new data, displacing the old */
-               if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags))
-                       zap = key->payload.data[0];
-               else
-                       zap = NULL;
-               rcu_assign_keypointer(key, upayload);
-               key->expiry = 0;
-       }
+       ret = key_payload_reserve(key, prep->datalen);
+       if (ret < 0)
+               return ret;
+
+       /* attach the new data, displacing the old */
+       key->expiry = prep->expiry;
+       if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags))
+               zap = rcu_dereference_key(key);
+       rcu_assign_keypointer(key, prep->payload.data[0]);
+       prep->payload.data[0] = NULL;
 
        if (zap)
                kfree_rcu(zap, rcu);
-
-error:
        return ret;
 }
-
 EXPORT_SYMBOL_GPL(user_update);
 
 /*