genetlink: clean up family attributes allocations

genl_family_rcv_msg_attrs_parse() and genl_family_rcv_msg_attrs_free()
take a boolean parameter to determine whether allocate/free the family
attrs. This is unnecessary as we can just check family->parallel_ops.
More importantly, callers would not need to worry about pairing these
parameters correctly after this patch.

And this fixes a memory leak, as after commit c36f05559104
("genetlink: fix memory leaks in genl_family_rcv_msg_dumpit()")
we call genl_family_rcv_msg_attrs_parse() for both parallel and
non-parallel cases.

Fixes: c36f05559104 ("genetlink: fix memory leaks in genl_family_rcv_msg_dumpit()")
Reported-by: Ido Schimmel <idosch@idosch.org>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Tested-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Cong Wang and committed by David S. Miller b65ce380 18dbd4cd

+12 -16
+12 -16
net/netlink/genetlink.c
··· 474 474 struct netlink_ext_ack *extack, 475 475 const struct genl_ops *ops, 476 476 int hdrlen, 477 - enum genl_validate_flags no_strict_flag, 478 - bool parallel) 477 + enum genl_validate_flags no_strict_flag) 479 478 { 480 479 enum netlink_validation validate = ops->validate & no_strict_flag ? 481 480 NL_VALIDATE_LIBERAL : ··· 485 486 if (!family->maxattr) 486 487 return NULL; 487 488 488 - if (parallel) { 489 + if (family->parallel_ops) { 489 490 attrbuf = kmalloc_array(family->maxattr + 1, 490 491 sizeof(struct nlattr *), GFP_KERNEL); 491 492 if (!attrbuf) ··· 497 498 err = __nlmsg_parse(nlh, hdrlen, attrbuf, family->maxattr, 498 499 family->policy, validate, extack); 499 500 if (err) { 500 - if (parallel) 501 + if (family->parallel_ops) 501 502 kfree(attrbuf); 502 503 return ERR_PTR(err); 503 504 } ··· 505 506 } 506 507 507 508 static void genl_family_rcv_msg_attrs_free(const struct genl_family *family, 508 - struct nlattr **attrbuf, 509 - bool parallel) 509 + struct nlattr **attrbuf) 510 510 { 511 - if (parallel) 511 + if (family->parallel_ops) 512 512 kfree(attrbuf); 513 513 } 514 514 ··· 535 537 536 538 attrs = genl_family_rcv_msg_attrs_parse(ctx->family, ctx->nlh, ctx->extack, 537 539 ops, ctx->hdrlen, 538 - GENL_DONT_VALIDATE_DUMP_STRICT, 539 - true); 540 + GENL_DONT_VALIDATE_DUMP_STRICT); 540 541 if (IS_ERR(attrs)) 541 542 return PTR_ERR(attrs); 542 543 543 544 no_attrs: 544 545 info = genl_dumpit_info_alloc(); 545 546 if (!info) { 546 - kfree(attrs); 547 + genl_family_rcv_msg_attrs_free(ctx->family, attrs); 547 548 return -ENOMEM; 548 549 } 549 550 info->family = ctx->family; ··· 559 562 } 560 563 561 564 if (rc) { 562 - kfree(attrs); 565 + genl_family_rcv_msg_attrs_free(info->family, info->attrs); 563 566 genl_dumpit_info_free(info); 564 567 cb->data = NULL; 565 568 } ··· 588 591 rc = ops->done(cb); 589 592 genl_unlock(); 590 593 } 591 - genl_family_rcv_msg_attrs_free(info->family, info->attrs, false); 594 + genl_family_rcv_msg_attrs_free(info->family, info->attrs); 592 595 genl_dumpit_info_free(info); 593 596 return rc; 594 597 } ··· 601 604 602 605 if (ops->done) 603 606 rc = ops->done(cb); 604 - genl_family_rcv_msg_attrs_free(info->family, info->attrs, true); 607 + genl_family_rcv_msg_attrs_free(info->family, info->attrs); 605 608 genl_dumpit_info_free(info); 606 609 return rc; 607 610 } ··· 668 671 669 672 attrbuf = genl_family_rcv_msg_attrs_parse(family, nlh, extack, 670 673 ops, hdrlen, 671 - GENL_DONT_VALIDATE_STRICT, 672 - family->parallel_ops); 674 + GENL_DONT_VALIDATE_STRICT); 673 675 if (IS_ERR(attrbuf)) 674 676 return PTR_ERR(attrbuf); 675 677 ··· 694 698 family->post_doit(ops, skb, &info); 695 699 696 700 out: 697 - genl_family_rcv_msg_attrs_free(family, attrbuf, family->parallel_ops); 701 + genl_family_rcv_msg_attrs_free(family, attrbuf); 698 702 699 703 return err; 700 704 }