| .. | .. |
|---|
| 216 | 216 | case XFRM_MSG_GETSADINFO: |
|---|
| 217 | 217 | case XFRM_MSG_GETSPDINFO: |
|---|
| 218 | 218 | default: |
|---|
| 219 | | - WARN_ONCE(1, "unsupported nlmsg_type %d", nlh_src->nlmsg_type); |
|---|
| 219 | + pr_warn_once("unsupported nlmsg_type %d\n", nlh_src->nlmsg_type); |
|---|
| 220 | 220 | return ERR_PTR(-EOPNOTSUPP); |
|---|
| 221 | 221 | } |
|---|
| 222 | 222 | |
|---|
| .. | .. |
|---|
| 234 | 234 | case XFRMA_PAD: |
|---|
| 235 | 235 | /* Ignore */ |
|---|
| 236 | 236 | return 0; |
|---|
| 237 | + case XFRMA_UNSPEC: |
|---|
| 237 | 238 | case XFRMA_ALG_AUTH: |
|---|
| 238 | 239 | case XFRMA_ALG_CRYPT: |
|---|
| 239 | 240 | case XFRMA_ALG_COMP: |
|---|
| .. | .. |
|---|
| 276 | 277 | return xfrm_nla_cpy(dst, src, nla_len(src)); |
|---|
| 277 | 278 | default: |
|---|
| 278 | 279 | BUILD_BUG_ON(XFRMA_MAX != XFRMA_IF_ID); |
|---|
| 279 | | - WARN_ONCE(1, "unsupported nla_type %d", src->nla_type); |
|---|
| 280 | + pr_warn_once("unsupported nla_type %d\n", src->nla_type); |
|---|
| 280 | 281 | return -EOPNOTSUPP; |
|---|
| 281 | 282 | } |
|---|
| 282 | 283 | } |
|---|
| .. | .. |
|---|
| 297 | 298 | len = nlmsg_attrlen(nlh_src, xfrm_msg_min[type]); |
|---|
| 298 | 299 | |
|---|
| 299 | 300 | nla_for_each_attr(nla, attrs, len, remaining) { |
|---|
| 300 | | - int err = xfrm_xlate64_attr(dst, nla); |
|---|
| 301 | + int err; |
|---|
| 301 | 302 | |
|---|
| 303 | + switch (type) { |
|---|
| 304 | + case XFRM_MSG_NEWSPDINFO: |
|---|
| 305 | + err = xfrm_nla_cpy(dst, nla, nla_len(nla)); |
|---|
| 306 | + break; |
|---|
| 307 | + default: |
|---|
| 308 | + err = xfrm_xlate64_attr(dst, nla); |
|---|
| 309 | + break; |
|---|
| 310 | + } |
|---|
| 302 | 311 | if (err) |
|---|
| 303 | 312 | return err; |
|---|
| 304 | 313 | } |
|---|
| .. | .. |
|---|
| 314 | 323 | struct sk_buff *new = NULL; |
|---|
| 315 | 324 | int err; |
|---|
| 316 | 325 | |
|---|
| 317 | | - if (WARN_ON_ONCE(type >= ARRAY_SIZE(xfrm_msg_min))) |
|---|
| 326 | + if (type >= ARRAY_SIZE(xfrm_msg_min)) { |
|---|
| 327 | + pr_warn_once("unsupported nlmsg_type %d\n", nlh_src->nlmsg_type); |
|---|
| 318 | 328 | return -EOPNOTSUPP; |
|---|
| 329 | + } |
|---|
| 319 | 330 | |
|---|
| 320 | 331 | if (skb_shinfo(skb)->frag_list == NULL) { |
|---|
| 321 | 332 | new = alloc_skb(skb->len + skb_tailroom(skb), GFP_ATOMIC); |
|---|
| .. | .. |
|---|
| 338 | 349 | |
|---|
| 339 | 350 | /* Calculates len of translated 64-bit message. */ |
|---|
| 340 | 351 | static size_t xfrm_user_rcv_calculate_len64(const struct nlmsghdr *src, |
|---|
| 341 | | - struct nlattr *attrs[XFRMA_MAX+1]) |
|---|
| 352 | + struct nlattr *attrs[XFRMA_MAX + 1], |
|---|
| 353 | + int maxtype) |
|---|
| 342 | 354 | { |
|---|
| 343 | 355 | size_t len = nlmsg_len(src); |
|---|
| 344 | 356 | |
|---|
| .. | .. |
|---|
| 355 | 367 | case XFRM_MSG_POLEXPIRE: |
|---|
| 356 | 368 | len += 8; |
|---|
| 357 | 369 | break; |
|---|
| 370 | + case XFRM_MSG_NEWSPDINFO: |
|---|
| 371 | + /* attirbutes are xfrm_spdattr_type_t, not xfrm_attr_type_t */ |
|---|
| 372 | + return len; |
|---|
| 358 | 373 | default: |
|---|
| 359 | 374 | break; |
|---|
| 360 | 375 | } |
|---|
| 376 | + |
|---|
| 377 | + /* Unexpected for anything, but XFRM_MSG_NEWSPDINFO, please |
|---|
| 378 | + * correct both 64=>32-bit and 32=>64-bit translators to copy |
|---|
| 379 | + * new attributes. |
|---|
| 380 | + */ |
|---|
| 381 | + if (WARN_ON_ONCE(maxtype)) |
|---|
| 382 | + return len; |
|---|
| 361 | 383 | |
|---|
| 362 | 384 | if (attrs[XFRMA_SA]) |
|---|
| 363 | 385 | len += 4; |
|---|
| .. | .. |
|---|
| 377 | 399 | struct nlmsghdr *nlmsg = dst; |
|---|
| 378 | 400 | struct nlattr *nla; |
|---|
| 379 | 401 | |
|---|
| 402 | + /* xfrm_user_rcv_msg_compat() relies on fact that 32-bit messages |
|---|
| 403 | + * have the same len or shorted than 64-bit ones. |
|---|
| 404 | + * 32-bit translation that is bigger than 64-bit original is unexpected. |
|---|
| 405 | + */ |
|---|
| 380 | 406 | if (WARN_ON_ONCE(copy_len > payload)) |
|---|
| 381 | 407 | copy_len = payload; |
|---|
| 382 | 408 | |
|---|
| .. | .. |
|---|
| 387 | 413 | |
|---|
| 388 | 414 | memcpy(nla, src, nla_attr_size(copy_len)); |
|---|
| 389 | 415 | nla->nla_len = nla_attr_size(payload); |
|---|
| 390 | | - *pos += nla_attr_size(payload); |
|---|
| 416 | + *pos += nla_attr_size(copy_len); |
|---|
| 391 | 417 | nlmsg->nlmsg_len += nla->nla_len; |
|---|
| 392 | 418 | |
|---|
| 393 | 419 | memset(dst + *pos, 0, payload - copy_len); |
|---|
| .. | .. |
|---|
| 433 | 459 | |
|---|
| 434 | 460 | static int xfrm_xlate32(struct nlmsghdr *dst, const struct nlmsghdr *src, |
|---|
| 435 | 461 | struct nlattr *attrs[XFRMA_MAX+1], |
|---|
| 436 | | - size_t size, u8 type, struct netlink_ext_ack *extack) |
|---|
| 462 | + size_t size, u8 type, int maxtype, |
|---|
| 463 | + struct netlink_ext_ack *extack) |
|---|
| 437 | 464 | { |
|---|
| 438 | 465 | size_t pos; |
|---|
| 439 | 466 | int i; |
|---|
| .. | .. |
|---|
| 513 | 540 | } |
|---|
| 514 | 541 | pos = dst->nlmsg_len; |
|---|
| 515 | 542 | |
|---|
| 543 | + if (maxtype) { |
|---|
| 544 | + /* attirbutes are xfrm_spdattr_type_t, not xfrm_attr_type_t */ |
|---|
| 545 | + WARN_ON_ONCE(src->nlmsg_type != XFRM_MSG_NEWSPDINFO); |
|---|
| 546 | + |
|---|
| 547 | + for (i = 1; i <= maxtype; i++) { |
|---|
| 548 | + int err; |
|---|
| 549 | + |
|---|
| 550 | + if (!attrs[i]) |
|---|
| 551 | + continue; |
|---|
| 552 | + |
|---|
| 553 | + /* just copy - no need for translation */ |
|---|
| 554 | + err = xfrm_attr_cpy32(dst, &pos, attrs[i], size, |
|---|
| 555 | + nla_len(attrs[i]), nla_len(attrs[i])); |
|---|
| 556 | + if (err) |
|---|
| 557 | + return err; |
|---|
| 558 | + } |
|---|
| 559 | + return 0; |
|---|
| 560 | + } |
|---|
| 561 | + |
|---|
| 516 | 562 | for (i = 1; i < XFRMA_MAX + 1; i++) { |
|---|
| 517 | 563 | int err; |
|---|
| 518 | 564 | |
|---|
| .. | .. |
|---|
| 552 | 598 | (h32->nlmsg_flags & NLM_F_DUMP)) |
|---|
| 553 | 599 | return NULL; |
|---|
| 554 | 600 | |
|---|
| 555 | | - err = nlmsg_parse(h32, compat_msg_min[type], attrs, |
|---|
| 601 | + err = nlmsg_parse_deprecated(h32, compat_msg_min[type], attrs, |
|---|
| 556 | 602 | maxtype ? : XFRMA_MAX, policy ? : compat_policy, extack); |
|---|
| 557 | 603 | if (err < 0) |
|---|
| 558 | 604 | return ERR_PTR(err); |
|---|
| 559 | 605 | |
|---|
| 560 | | - len = xfrm_user_rcv_calculate_len64(h32, attrs); |
|---|
| 606 | + len = xfrm_user_rcv_calculate_len64(h32, attrs, maxtype); |
|---|
| 561 | 607 | /* The message doesn't need translation */ |
|---|
| 562 | 608 | if (len == nlmsg_len(h32)) |
|---|
| 563 | 609 | return NULL; |
|---|
| 564 | 610 | |
|---|
| 565 | 611 | len += NLMSG_HDRLEN; |
|---|
| 566 | | - h64 = kvmalloc(len, GFP_KERNEL | __GFP_ZERO); |
|---|
| 612 | + h64 = kvmalloc(len, GFP_KERNEL); |
|---|
| 567 | 613 | if (!h64) |
|---|
| 568 | 614 | return ERR_PTR(-ENOMEM); |
|---|
| 569 | 615 | |
|---|
| 570 | | - err = xfrm_xlate32(h64, h32, attrs, len, type, extack); |
|---|
| 616 | + err = xfrm_xlate32(h64, h32, attrs, len, type, maxtype, extack); |
|---|
| 571 | 617 | if (err < 0) { |
|---|
| 572 | 618 | kvfree(h64); |
|---|
| 573 | 619 | return ERR_PTR(err); |
|---|
| .. | .. |
|---|
| 585 | 631 | if (optlen < sizeof(*p)) |
|---|
| 586 | 632 | return -EINVAL; |
|---|
| 587 | 633 | |
|---|
| 588 | | - data64 = kmalloc(optlen + 4, GFP_USER | __GFP_NOWARN); |
|---|
| 634 | + data64 = kmalloc_track_caller(optlen + 4, GFP_USER | __GFP_NOWARN); |
|---|
| 589 | 635 | if (!data64) |
|---|
| 590 | 636 | return -ENOMEM; |
|---|
| 591 | 637 | |
|---|