summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-04-12 14:54:58 -0400
committerDavid Howells <dhowells@redhat.com>2016-04-12 14:54:58 -0400
commit898de7d0f298e53568891f0ec3547b14fe8bb5d5 (patch)
tree90fb64dc5d8158417b7de658d8b0016d54264056 /security
parent93da17b18539cb021f1075f8620ee8f6da9b42aa (diff)
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: David Howells <dhowells@redhat.com>
Diffstat (limited to 'security')
-rw-r--r--security/keys/user_defined.c42
1 files changed, 11 insertions, 31 deletions
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 8705d79b2c6f..66b1840b4110 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -96,45 +96,25 @@ EXPORT_SYMBOL_GPL(user_free_preparse);
96 */ 96 */
97int user_update(struct key *key, struct key_preparsed_payload *prep) 97int user_update(struct key *key, struct key_preparsed_payload *prep)
98{ 98{
99 struct user_key_payload *upayload, *zap; 99 struct user_key_payload *zap = NULL;
100 size_t datalen = prep->datalen;
101 int ret; 100 int ret;
102 101
103 ret = -EINVAL;
104 if (datalen <= 0 || datalen > 32767 || !prep->data)
105 goto error;
106
107 /* construct a replacement payload */
108 ret = -ENOMEM;
109 upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL);
110 if (!upayload)
111 goto error;
112
113 upayload->datalen = datalen;
114 memcpy(upayload->data, prep->data, datalen);
115
116 /* check the quota and attach the new data */ 102 /* check the quota and attach the new data */
117 zap = upayload; 103 ret = key_payload_reserve(key, prep->datalen);
118 104 if (ret < 0)
119 ret = key_payload_reserve(key, datalen); 105 return ret;
120 106
121 if (ret == 0) { 107 /* attach the new data, displacing the old */
122 /* attach the new data, displacing the old */ 108 key->expiry = prep->expiry;
123 if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags)) 109 if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags))
124 zap = key->payload.data[0]; 110 zap = rcu_dereference_key(key);
125 else 111 rcu_assign_keypointer(key, prep->payload.data[0]);
126 zap = NULL; 112 prep->payload.data[0] = NULL;
127 rcu_assign_keypointer(key, upayload);
128 key->expiry = 0;
129 }
130 113
131 if (zap) 114 if (zap)
132 kfree_rcu(zap, rcu); 115 kfree_rcu(zap, rcu);
133
134error:
135 return ret; 116 return ret;
136} 117}
137
138EXPORT_SYMBOL_GPL(user_update); 118EXPORT_SYMBOL_GPL(user_update);
139 119
140/* 120/*