Skip to content

Commit ab5b526

Browse files
jpirkoJakub Kicinski
authored andcommitted
net: genetlink: always allocate separate attrs for dumpit ops
Individual dumpit ops (start, dumpit, done) are locked by genl_lock if !family->parallel_ops. However, multiple genl_family_rcv_msg_dumpit() calls may in in flight in parallel. Each has a separate struct genl_dumpit_info allocated but they share the same family->attrbuf. Fix this by allocating separate memory for attrs for dumpit ops, for non-parallel_ops (for parallel_ops it is done already). Reported-by: syzbot+495688b736534bb6c6ad@syzkaller.appspotmail.com Reported-by: syzbot+ff59dc711f2cff879a05@syzkaller.appspotmail.com Reported-by: syzbot+dbe02e13bcce52bcf182@syzkaller.appspotmail.com Reported-by: syzbot+9cb7edb2906ea1e83006@syzkaller.appspotmail.com Fixes: bf813b0 ("net: genetlink: parse attrs and store in contect info struct during dumpit") Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
1 parent 48423dd commit ab5b526

File tree

1 file changed

+17
-11
lines changed

1 file changed

+17
-11
lines changed

net/netlink/genetlink.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -474,15 +474,16 @@ genl_family_rcv_msg_attrs_parse(const struct genl_family *family,
474474
struct netlink_ext_ack *extack,
475475
const struct genl_ops *ops,
476476
int hdrlen,
477-
enum genl_validate_flags no_strict_flag)
477+
enum genl_validate_flags no_strict_flag,
478+
bool parallel)
478479
{
479480
enum netlink_validation validate = ops->validate & no_strict_flag ?
480481
NL_VALIDATE_LIBERAL :
481482
NL_VALIDATE_STRICT;
482483
struct nlattr **attrbuf;
483484
int err;
484485

485-
if (family->maxattr && family->parallel_ops) {
486+
if (parallel) {
486487
attrbuf = kmalloc_array(family->maxattr + 1,
487488
sizeof(struct nlattr *), GFP_KERNEL);
488489
if (!attrbuf)
@@ -493,17 +494,18 @@ genl_family_rcv_msg_attrs_parse(const struct genl_family *family,
493494

494495
err = __nlmsg_parse(nlh, hdrlen, attrbuf, family->maxattr,
495496
family->policy, validate, extack);
496-
if (err && family->maxattr && family->parallel_ops) {
497+
if (err && parallel) {
497498
kfree(attrbuf);
498499
return ERR_PTR(err);
499500
}
500501
return attrbuf;
501502
}
502503

503504
static void genl_family_rcv_msg_attrs_free(const struct genl_family *family,
504-
struct nlattr **attrbuf)
505+
struct nlattr **attrbuf,
506+
bool parallel)
505507
{
506-
if (family->maxattr && family->parallel_ops)
508+
if (parallel)
507509
kfree(attrbuf);
508510
}
509511

@@ -542,7 +544,7 @@ static int genl_lock_done(struct netlink_callback *cb)
542544
rc = ops->done(cb);
543545
genl_unlock();
544546
}
545-
genl_family_rcv_msg_attrs_free(info->family, info->attrs);
547+
genl_family_rcv_msg_attrs_free(info->family, info->attrs, true);
546548
genl_dumpit_info_free(info);
547549
return rc;
548550
}
@@ -555,7 +557,7 @@ static int genl_parallel_done(struct netlink_callback *cb)
555557

556558
if (ops->done)
557559
rc = ops->done(cb);
558-
genl_family_rcv_msg_attrs_free(info->family, info->attrs);
560+
genl_family_rcv_msg_attrs_free(info->family, info->attrs, true);
559561
genl_dumpit_info_free(info);
560562
return rc;
561563
}
@@ -585,15 +587,16 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
585587

586588
attrs = genl_family_rcv_msg_attrs_parse(family, nlh, extack,
587589
ops, hdrlen,
588-
GENL_DONT_VALIDATE_DUMP_STRICT);
590+
GENL_DONT_VALIDATE_DUMP_STRICT,
591+
true);
589592
if (IS_ERR(attrs))
590593
return PTR_ERR(attrs);
591594

592595
no_attrs:
593596
/* Allocate dumpit info. It is going to be freed by done() callback. */
594597
info = genl_dumpit_info_alloc();
595598
if (!info) {
596-
genl_family_rcv_msg_attrs_free(family, attrs);
599+
genl_family_rcv_msg_attrs_free(family, attrs, true);
597600
return -ENOMEM;
598601
}
599602

@@ -645,7 +648,9 @@ static int genl_family_rcv_msg_doit(const struct genl_family *family,
645648

646649
attrbuf = genl_family_rcv_msg_attrs_parse(family, nlh, extack,
647650
ops, hdrlen,
648-
GENL_DONT_VALIDATE_STRICT);
651+
GENL_DONT_VALIDATE_STRICT,
652+
family->maxattr &&
653+
family->parallel_ops);
649654
if (IS_ERR(attrbuf))
650655
return PTR_ERR(attrbuf);
651656

@@ -671,7 +676,8 @@ static int genl_family_rcv_msg_doit(const struct genl_family *family,
671676
family->post_doit(ops, skb, &info);
672677

673678
out:
674-
genl_family_rcv_msg_attrs_free(family, attrbuf);
679+
genl_family_rcv_msg_attrs_free(family, attrbuf,
680+
family->maxattr && family->parallel_ops);
675681

676682
return err;
677683
}

0 commit comments

Comments
 (0)