diff options
author | David Howells <dhowells@redhat.com> | 2016-04-12 14:54:58 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2016-04-12 14:54:58 -0400 |
commit | 898de7d0f298e53568891f0ec3547b14fe8bb5d5 (patch) | |
tree | 90fb64dc5d8158417b7de658d8b0016d54264056 /security | |
parent | 93da17b18539cb021f1075f8620ee8f6da9b42aa (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.c | 42 |
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 | */ |
97 | int user_update(struct key *key, struct key_preparsed_payload *prep) | 97 | int 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 | |||
134 | error: | ||
135 | return ret; | 116 | return ret; |
136 | } | 117 | } |
137 | |||
138 | EXPORT_SYMBOL_GPL(user_update); | 118 | EXPORT_SYMBOL_GPL(user_update); |
139 | 119 | ||
140 | /* | 120 | /* |