diff options
-rw-r--r-- | fs/cifs/cifsacl.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index f4508ee4e80d..751d34bd825c 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -49,6 +49,20 @@ cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | |||
49 | { | 49 | { |
50 | char *payload; | 50 | char *payload; |
51 | 51 | ||
52 | /* | ||
53 | * If the payload is less than or equal to the size of a pointer, then | ||
54 | * an allocation here is wasteful. Just copy the data directly to the | ||
55 | * payload.value union member instead. | ||
56 | * | ||
57 | * With this however, you must check the datalen before trying to | ||
58 | * dereference payload.data! | ||
59 | */ | ||
60 | if (prep->datalen <= sizeof(void *)) { | ||
61 | key->payload.value = 0; | ||
62 | memcpy(&key->payload.value, prep->data, prep->datalen); | ||
63 | key->datalen = prep->datalen; | ||
64 | return 0; | ||
65 | } | ||
52 | payload = kmalloc(prep->datalen, GFP_KERNEL); | 66 | payload = kmalloc(prep->datalen, GFP_KERNEL); |
53 | if (!payload) | 67 | if (!payload) |
54 | return -ENOMEM; | 68 | return -ENOMEM; |
@@ -62,7 +76,8 @@ cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | |||
62 | static inline void | 76 | static inline void |
63 | cifs_idmap_key_destroy(struct key *key) | 77 | cifs_idmap_key_destroy(struct key *key) |
64 | { | 78 | { |
65 | kfree(key->payload.data); | 79 | if (key->datalen > sizeof(void *)) |
80 | kfree(key->payload.data); | ||
66 | } | 81 | } |
67 | 82 | ||
68 | static struct key_type cifs_idmap_key_type = { | 83 | static struct key_type cifs_idmap_key_type = { |
@@ -245,7 +260,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, | |||
245 | * probably a safe assumption but might be better to check based on | 260 | * probably a safe assumption but might be better to check based on |
246 | * sidtype. | 261 | * sidtype. |
247 | */ | 262 | */ |
248 | if (sidkey->datalen < sizeof(uid_t)) { | 263 | if (sidkey->datalen != sizeof(uid_t)) { |
249 | rc = -EIO; | 264 | rc = -EIO; |
250 | cFYI(1, "%s: Downcall contained malformed key " | 265 | cFYI(1, "%s: Downcall contained malformed key " |
251 | "(datalen=%hu)", __func__, sidkey->datalen); | 266 | "(datalen=%hu)", __func__, sidkey->datalen); |
@@ -253,9 +268,9 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, | |||
253 | } | 268 | } |
254 | 269 | ||
255 | if (sidtype == SIDOWNER) | 270 | if (sidtype == SIDOWNER) |
256 | fuid = *(uid_t *)sidkey->payload.value; | 271 | memcpy(&fuid, &sidkey->payload.value, sizeof(uid_t)); |
257 | else | 272 | else |
258 | fgid = *(gid_t *)sidkey->payload.value; | 273 | memcpy(&fgid, &sidkey->payload.value, sizeof(gid_t)); |
259 | 274 | ||
260 | out_key_put: | 275 | out_key_put: |
261 | key_put(sidkey); | 276 | key_put(sidkey); |