Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: sched: move block device tracking into tcf_block_get/put_ext()

Inserting the device to block xarray in qdisc_create() is not suitable
place to do this. As it requires use of tcf_block() callback, it causes
multiple issues. It is called for all qdisc types, which is incorrect.

So, instead, move it to more suitable place, which is tcf_block_get_ext()
and make sure it is only done for qdiscs that use block infrastructure
and also only for blocks which are shared.

Symmetrically, alter the cleanup path, move the xarray entry removal
into tcf_block_put_ext().

Fixes: 913b47d3424e ("net/sched: Introduce tc block netdev tracking infra")
Reported-by: Ido Schimmel <idosch@nvidia.com>
Closes: https://lore.kernel.org/all/ZY1hBb8GFwycfgvd@shredder/
Reported-by: Kui-Feng Lee <sinquersw@gmail.com>
Closes: https://lore.kernel.org/all/ce8d3e55-b8bc-409c-ace9-5cf1c4f7c88e@gmail.com/
Reported-and-tested-by: syzbot+84339b9e7330daae4d66@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/0000000000007c85f5060dcc3a28@google.com/
Reported-and-tested-by: syzbot+806b0572c8d06b66b234@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/00000000000082f2f2060dcc3a92@google.com/
Reported-and-tested-by: syzbot+0039110f932d438130f9@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/0000000000007fbc8c060dcc3a5c@google.com/
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Tested-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Victor Nogueira <victor@mojatatu.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Jiri Pirko and committed by
David S. Miller
94e2557d e63c1822

+14 -55
+14
net/sched/cls_api.c
··· 1428 1428 struct tcf_block_ext_info *ei, 1429 1429 struct netlink_ext_ack *extack) 1430 1430 { 1431 + struct net_device *dev = qdisc_dev(q); 1431 1432 struct net *net = qdisc_net(q); 1432 1433 struct tcf_block *block = NULL; 1433 1434 int err; ··· 1462 1461 if (err) 1463 1462 goto err_block_offload_bind; 1464 1463 1464 + if (tcf_block_shared(block)) { 1465 + err = xa_insert(&block->ports, dev->ifindex, dev, GFP_KERNEL); 1466 + if (err) { 1467 + NL_SET_ERR_MSG(extack, "block dev insert failed"); 1468 + goto err_dev_insert; 1469 + } 1470 + } 1471 + 1465 1472 *p_block = block; 1466 1473 return 0; 1467 1474 1475 + err_dev_insert: 1468 1476 err_block_offload_bind: 1469 1477 tcf_chain0_head_change_cb_del(block, ei); 1470 1478 err_chain0_head_change_cb_add: ··· 1512 1502 void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q, 1513 1503 struct tcf_block_ext_info *ei) 1514 1504 { 1505 + struct net_device *dev = qdisc_dev(q); 1506 + 1515 1507 if (!block) 1516 1508 return; 1509 + if (tcf_block_shared(block)) 1510 + xa_erase(&block->ports, dev->ifindex); 1517 1511 tcf_chain0_head_change_cb_del(block, ei); 1518 1512 tcf_block_owner_del(block, q, ei->binder_type); 1519 1513
-41
net/sched/sch_api.c
··· 1209 1209 return 0; 1210 1210 } 1211 1211 1212 - static int qdisc_block_add_dev(struct Qdisc *sch, struct net_device *dev, 1213 - struct netlink_ext_ack *extack) 1214 - { 1215 - const struct Qdisc_class_ops *cl_ops = sch->ops->cl_ops; 1216 - struct tcf_block *block; 1217 - int err; 1218 - 1219 - block = cl_ops->tcf_block(sch, TC_H_MIN_INGRESS, NULL); 1220 - if (block) { 1221 - err = xa_insert(&block->ports, dev->ifindex, dev, GFP_KERNEL); 1222 - if (err) { 1223 - NL_SET_ERR_MSG(extack, 1224 - "ingress block dev insert failed"); 1225 - return err; 1226 - } 1227 - } 1228 - 1229 - block = cl_ops->tcf_block(sch, TC_H_MIN_EGRESS, NULL); 1230 - if (block) { 1231 - err = xa_insert(&block->ports, dev->ifindex, dev, GFP_KERNEL); 1232 - if (err) { 1233 - NL_SET_ERR_MSG(extack, 1234 - "Egress block dev insert failed"); 1235 - goto err_out; 1236 - } 1237 - } 1238 - 1239 - return 0; 1240 - 1241 - err_out: 1242 - block = cl_ops->tcf_block(sch, TC_H_MIN_INGRESS, NULL); 1243 - if (block) 1244 - xa_erase(&block->ports, dev->ifindex); 1245 - 1246 - return err; 1247 - } 1248 - 1249 1212 static int qdisc_block_indexes_set(struct Qdisc *sch, struct nlattr **tca, 1250 1213 struct netlink_ext_ack *extack) 1251 1214 { ··· 1378 1415 1379 1416 qdisc_hash_add(sch, false); 1380 1417 trace_qdisc_create(ops, dev, parent); 1381 - 1382 - err = qdisc_block_add_dev(sch, dev, extack); 1383 - if (err) 1384 - goto err_out4; 1385 1418 1386 1419 return sch; 1387 1420
-14
net/sched/sch_generic.c
··· 1052 1052 { 1053 1053 const struct Qdisc_ops *ops = qdisc->ops; 1054 1054 struct net_device *dev = qdisc_dev(qdisc); 1055 - const struct Qdisc_class_ops *cops; 1056 - struct tcf_block *block; 1057 1055 1058 1056 #ifdef CONFIG_NET_SCHED 1059 1057 qdisc_hash_del(qdisc); ··· 1062 1064 1063 1065 qdisc_reset(qdisc); 1064 1066 1065 - cops = ops->cl_ops; 1066 - if (ops->ingress_block_get) { 1067 - block = cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL); 1068 - if (block) 1069 - xa_erase(&block->ports, dev->ifindex); 1070 - } 1071 - 1072 - if (ops->egress_block_get) { 1073 - block = cops->tcf_block(qdisc, TC_H_MIN_EGRESS, NULL); 1074 - if (block) 1075 - xa_erase(&block->ports, dev->ifindex); 1076 - } 1077 1067 1078 1068 if (ops->destroy) 1079 1069 ops->destroy(qdisc);