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