diff options
Diffstat (limited to 'drivers/uwb/wlp/messages.c')
-rw-r--r-- | drivers/uwb/wlp/messages.c | 107 |
1 files changed, 62 insertions, 45 deletions
diff --git a/drivers/uwb/wlp/messages.c b/drivers/uwb/wlp/messages.c index aa42fcee4c4f..3a8e033dce21 100644 --- a/drivers/uwb/wlp/messages.c +++ b/drivers/uwb/wlp/messages.c | |||
@@ -24,6 +24,7 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/wlp.h> | 26 | #include <linux/wlp.h> |
27 | #include <linux/slab.h> | ||
27 | 28 | ||
28 | #include "wlp-internal.h" | 29 | #include "wlp-internal.h" |
29 | 30 | ||
@@ -259,6 +260,63 @@ out: | |||
259 | } | 260 | } |
260 | 261 | ||
261 | 262 | ||
263 | static ssize_t wlp_get_attribute(struct wlp *wlp, u16 type_code, | ||
264 | struct wlp_attr_hdr *attr_hdr, void *value, ssize_t value_len, | ||
265 | ssize_t buflen) | ||
266 | { | ||
267 | struct device *dev = &wlp->rc->uwb_dev.dev; | ||
268 | ssize_t attr_len = sizeof(*attr_hdr) + value_len; | ||
269 | if (buflen < 0) | ||
270 | return -EINVAL; | ||
271 | if (buflen < attr_len) { | ||
272 | dev_err(dev, "WLP: Not enough space in buffer to parse" | ||
273 | " attribute field. Need %d, received %zu\n", | ||
274 | (int)attr_len, buflen); | ||
275 | return -EIO; | ||
276 | } | ||
277 | if (wlp_check_attr_hdr(wlp, attr_hdr, type_code, value_len) < 0) { | ||
278 | dev_err(dev, "WLP: Header verification failed. \n"); | ||
279 | return -EINVAL; | ||
280 | } | ||
281 | memcpy(value, (void *)attr_hdr + sizeof(*attr_hdr), value_len); | ||
282 | return attr_len; | ||
283 | } | ||
284 | |||
285 | static ssize_t wlp_vget_attribute(struct wlp *wlp, u16 type_code, | ||
286 | struct wlp_attr_hdr *attr_hdr, void *value, ssize_t max_value_len, | ||
287 | ssize_t buflen) | ||
288 | { | ||
289 | struct device *dev = &wlp->rc->uwb_dev.dev; | ||
290 | size_t len; | ||
291 | if (buflen < 0) | ||
292 | return -EINVAL; | ||
293 | if (buflen < sizeof(*attr_hdr)) { | ||
294 | dev_err(dev, "WLP: Not enough space in buffer to parse" | ||
295 | " header.\n"); | ||
296 | return -EIO; | ||
297 | } | ||
298 | if (le16_to_cpu(attr_hdr->type) != type_code) { | ||
299 | dev_err(dev, "WLP: Unexpected attribute type. Got %u, " | ||
300 | "expected %u.\n", le16_to_cpu(attr_hdr->type), | ||
301 | type_code); | ||
302 | return -EINVAL; | ||
303 | } | ||
304 | len = le16_to_cpu(attr_hdr->length); | ||
305 | if (len > max_value_len) { | ||
306 | dev_err(dev, "WLP: Attribute larger than maximum " | ||
307 | "allowed. Received %zu, max is %d.\n", len, | ||
308 | (int)max_value_len); | ||
309 | return -EFBIG; | ||
310 | } | ||
311 | if (buflen < sizeof(*attr_hdr) + len) { | ||
312 | dev_err(dev, "WLP: Not enough space in buffer to parse " | ||
313 | "variable data.\n"); | ||
314 | return -EIO; | ||
315 | } | ||
316 | memcpy(value, (void *)attr_hdr + sizeof(*attr_hdr), len); | ||
317 | return sizeof(*attr_hdr) + len; | ||
318 | } | ||
319 | |||
262 | /** | 320 | /** |
263 | * Get value of attribute from fixed size attribute field. | 321 | * Get value of attribute from fixed size attribute field. |
264 | * | 322 | * |
@@ -274,22 +332,8 @@ out: | |||
274 | ssize_t wlp_get_##name(struct wlp *wlp, struct wlp_attr_##name *attr, \ | 332 | ssize_t wlp_get_##name(struct wlp *wlp, struct wlp_attr_##name *attr, \ |
275 | type *value, ssize_t buflen) \ | 333 | type *value, ssize_t buflen) \ |
276 | { \ | 334 | { \ |
277 | struct device *dev = &wlp->rc->uwb_dev.dev; \ | 335 | return wlp_get_attribute(wlp, (type_code), &attr->hdr, \ |
278 | if (buflen < 0) \ | 336 | value, sizeof(*value), buflen); \ |
279 | return -EINVAL; \ | ||
280 | if (buflen < sizeof(*attr)) { \ | ||
281 | dev_err(dev, "WLP: Not enough space in buffer to parse" \ | ||
282 | " attribute field. Need %d, received %zu\n", \ | ||
283 | (int)sizeof(*attr), buflen); \ | ||
284 | return -EIO; \ | ||
285 | } \ | ||
286 | if (wlp_check_attr_hdr(wlp, &attr->hdr, type_code, \ | ||
287 | sizeof(attr->name)) < 0) { \ | ||
288 | dev_err(dev, "WLP: Header verification failed. \n"); \ | ||
289 | return -EINVAL; \ | ||
290 | } \ | ||
291 | *value = attr->name; \ | ||
292 | return sizeof(*attr); \ | ||
293 | } | 337 | } |
294 | 338 | ||
295 | #define wlp_get_sparse(type, type_code, name) \ | 339 | #define wlp_get_sparse(type, type_code, name) \ |
@@ -313,35 +357,8 @@ static ssize_t wlp_get_##name(struct wlp *wlp, \ | |||
313 | struct wlp_attr_##name *attr, \ | 357 | struct wlp_attr_##name *attr, \ |
314 | type_val *value, ssize_t buflen) \ | 358 | type_val *value, ssize_t buflen) \ |
315 | { \ | 359 | { \ |
316 | struct device *dev = &wlp->rc->uwb_dev.dev; \ | 360 | return wlp_vget_attribute(wlp, (type_code), &attr->hdr, \ |
317 | size_t len; \ | 361 | value, (max), buflen); \ |
318 | if (buflen < 0) \ | ||
319 | return -EINVAL; \ | ||
320 | if (buflen < sizeof(*attr)) { \ | ||
321 | dev_err(dev, "WLP: Not enough space in buffer to parse" \ | ||
322 | " header.\n"); \ | ||
323 | return -EIO; \ | ||
324 | } \ | ||
325 | if (le16_to_cpu(attr->hdr.type) != type_code) { \ | ||
326 | dev_err(dev, "WLP: Unexpected attribute type. Got %u, " \ | ||
327 | "expected %u.\n", le16_to_cpu(attr->hdr.type), \ | ||
328 | type_code); \ | ||
329 | return -EINVAL; \ | ||
330 | } \ | ||
331 | len = le16_to_cpu(attr->hdr.length); \ | ||
332 | if (len > max) { \ | ||
333 | dev_err(dev, "WLP: Attribute larger than maximum " \ | ||
334 | "allowed. Received %zu, max is %d.\n", len, \ | ||
335 | (int)max); \ | ||
336 | return -EFBIG; \ | ||
337 | } \ | ||
338 | if (buflen < sizeof(*attr) + len) { \ | ||
339 | dev_err(dev, "WLP: Not enough space in buffer to parse "\ | ||
340 | "variable data.\n"); \ | ||
341 | return -EIO; \ | ||
342 | } \ | ||
343 | memcpy(value, (void *) attr + sizeof(*attr), len); \ | ||
344 | return sizeof(*attr) + len; \ | ||
345 | } | 362 | } |
346 | 363 | ||
347 | wlp_get(u8, WLP_ATTR_WLP_VER, version) | 364 | wlp_get(u8, WLP_ATTR_WLP_VER, version) |