diff options
author | Jeff Layton <jlayton@redhat.com> | 2012-12-03 06:05:31 -0500 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-12-08 23:04:37 -0500 |
commit | 1f6306806c1494bea51b93f96e105e93a96e3c22 (patch) | |
tree | 8cbd03168fa91915bcf144e8b56dccf53b78acc2 /fs/cifs/cifsacl.c | |
parent | 7ee0b4c635c091eb3c805977ba886bae2fd33f0c (diff) |
cifs: deal with id_to_sid embedded sid reply corner case
A SID could potentially be embedded inside of payload.value if there are
no subauthorities, and the arch has 8 byte pointers. Allow for that
possibility there.
While we're at it, rephrase the "embedding" check in terms of
key->payload to allow for the possibility that the union might change
size in the future.
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/cifs/cifsacl.c')
-rw-r--r-- | fs/cifs/cifsacl.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 08b4d5022686..8dd9212ffef5 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -57,7 +57,7 @@ cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | |||
57 | * With this however, you must check the datalen before trying to | 57 | * With this however, you must check the datalen before trying to |
58 | * dereference payload.data! | 58 | * dereference payload.data! |
59 | */ | 59 | */ |
60 | if (prep->datalen <= sizeof(void *)) { | 60 | if (prep->datalen <= sizeof(key->payload)) { |
61 | key->payload.value = 0; | 61 | key->payload.value = 0; |
62 | memcpy(&key->payload.value, prep->data, prep->datalen); | 62 | memcpy(&key->payload.value, prep->data, prep->datalen); |
63 | key->datalen = prep->datalen; | 63 | key->datalen = prep->datalen; |
@@ -76,7 +76,7 @@ cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | |||
76 | static inline void | 76 | static inline void |
77 | cifs_idmap_key_destroy(struct key *key) | 77 | cifs_idmap_key_destroy(struct key *key) |
78 | { | 78 | { |
79 | if (key->datalen > sizeof(void *)) | 79 | if (key->datalen > sizeof(key->payload)) |
80 | kfree(key->payload.data); | 80 | kfree(key->payload.data); |
81 | } | 81 | } |
82 | 82 | ||
@@ -216,7 +216,15 @@ id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid) | |||
216 | goto invalidate_key; | 216 | goto invalidate_key; |
217 | } | 217 | } |
218 | 218 | ||
219 | ksid = (struct cifs_sid *)sidkey->payload.data; | 219 | /* |
220 | * A sid is usually too large to be embedded in payload.value, but if | ||
221 | * there are no subauthorities and the host has 8-byte pointers, then | ||
222 | * it could be. | ||
223 | */ | ||
224 | ksid = sidkey->datalen <= sizeof(sidkey->payload) ? | ||
225 | (struct cifs_sid *)&sidkey->payload.value : | ||
226 | (struct cifs_sid *)sidkey->payload.data; | ||
227 | |||
220 | ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32)); | 228 | ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32)); |
221 | if (ksid_size > sidkey->datalen) { | 229 | if (ksid_size > sidkey->datalen) { |
222 | rc = -EIO; | 230 | rc = -EIO; |
@@ -224,6 +232,7 @@ id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid) | |||
224 | "ksid_size=%u)", __func__, sidkey->datalen, ksid_size); | 232 | "ksid_size=%u)", __func__, sidkey->datalen, ksid_size); |
225 | goto invalidate_key; | 233 | goto invalidate_key; |
226 | } | 234 | } |
235 | |||
227 | cifs_copy_sid(ssid, ksid); | 236 | cifs_copy_sid(ssid, ksid); |
228 | out_key_put: | 237 | out_key_put: |
229 | key_put(sidkey); | 238 | key_put(sidkey); |