diff options
author | Jeff Layton <jlayton@redhat.com> | 2012-12-03 06:05:30 -0500 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-12-08 23:04:32 -0500 |
commit | 2ae03025d520de581fd1c58e98bbf3045c0f4695 (patch) | |
tree | 4795149c42b5ecdddd4540dd97c0972522183ea5 /fs | |
parent | 41a9f1f6b38664fc08431674d87871a57d763be1 (diff) |
cifs: extra sanity checking for cifs.idmap keys
Now that we aren't so rigid about the length of the key being passed
in, we need to be a bit more rigorous about checking the length of
the actual data against the claimed length (a'la num_subauths field).
Check for the case where userspace sends us a seemingly valid key
with a num_subauths field that goes beyond the end of the array. If
that happens, return -EIO and invalidate the key.
Also change the other places where we check for malformed keys in this
code to invalidate the key as well.
Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifsacl.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 751d34bd825c..b0b114acdece 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -191,6 +191,8 @@ id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid) | |||
191 | { | 191 | { |
192 | int rc; | 192 | int rc; |
193 | struct key *sidkey; | 193 | struct key *sidkey; |
194 | struct cifs_sid *ksid; | ||
195 | unsigned int ksid_size; | ||
194 | char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */ | 196 | char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */ |
195 | const struct cred *saved_cred; | 197 | const struct cred *saved_cred; |
196 | 198 | ||
@@ -211,14 +213,27 @@ id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid) | |||
211 | rc = -EIO; | 213 | rc = -EIO; |
212 | cFYI(1, "%s: Downcall contained malformed key " | 214 | cFYI(1, "%s: Downcall contained malformed key " |
213 | "(datalen=%hu)", __func__, sidkey->datalen); | 215 | "(datalen=%hu)", __func__, sidkey->datalen); |
214 | goto out_key_put; | 216 | goto invalidate_key; |
215 | } | 217 | } |
216 | cifs_copy_sid(ssid, (struct cifs_sid *)sidkey->payload.data); | 218 | |
219 | ksid = (struct cifs_sid *)sidkey->payload.data; | ||
220 | ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32)); | ||
221 | if (ksid_size > sidkey->datalen) { | ||
222 | rc = -EIO; | ||
223 | cFYI(1, "%s: Downcall contained malformed key (datalen=%hu, " | ||
224 | "ksid_size=%u)", __func__, sidkey->datalen, ksid_size); | ||
225 | goto invalidate_key; | ||
226 | } | ||
227 | cifs_copy_sid(ssid, ksid); | ||
217 | out_key_put: | 228 | out_key_put: |
218 | key_put(sidkey); | 229 | key_put(sidkey); |
219 | out_revert_creds: | 230 | out_revert_creds: |
220 | revert_creds(saved_cred); | 231 | revert_creds(saved_cred); |
221 | return rc; | 232 | return rc; |
233 | |||
234 | invalidate_key: | ||
235 | key_invalidate(sidkey); | ||
236 | goto out_key_put; | ||
222 | } | 237 | } |
223 | 238 | ||
224 | static int | 239 | static int |
@@ -264,6 +279,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, | |||
264 | rc = -EIO; | 279 | rc = -EIO; |
265 | cFYI(1, "%s: Downcall contained malformed key " | 280 | cFYI(1, "%s: Downcall contained malformed key " |
266 | "(datalen=%hu)", __func__, sidkey->datalen); | 281 | "(datalen=%hu)", __func__, sidkey->datalen); |
282 | key_invalidate(sidkey); | ||
267 | goto out_key_put; | 283 | goto out_key_put; |
268 | } | 284 | } |
269 | 285 | ||