mirror of
https://github.com/torvalds/linux.git
synced 2026-09-12 20:53:03 +02:00
net/sched: cls_route: Fix in-place replace
Building on the previous patch, route4_set_parms rejects a duplicate by
scanning the destination chain for nhandle, but the scan doesn't exclude
the older version it is replacing, so an in-place replace will match
the older version's handle and fail.
Fix this by passing the older filter as a parameter to route4_set_parms
(replacing "new") and skipping it in the scan.
Excluding the older version is not enough on its own. nhandle is built
out of TCA_ROUTE4_TO, TCA_ROUTE4_FROM and TCA_ROUTE4_IIF alone, while the
0x7F00 bits, which only tell apart filters sharing one key, are folded in
on the create path. Letting the replace through would therefore rename
the filter it replaces: replacing handle 0x10101 stored it back as
0x10001, and a sibling at 0x10201 could then no longer be replaced at
all, since its own nhandle collided with the renamed filter.
tc filter add ... handle 0x10101 route from 1 to 1 classid 1:1
tc filter add ... handle 0x10201 route from 1 to 1 classid 1:2
tc filter replace ... handle 0x10101 route from 1 to 1 classid 1:9
... fh 0x00010001 flowid 1:9 to 1 from 1
... fh 0x00010201 flowid 1:2 to 1 from 1
tc filter replace ... handle 0x10201 route from 1 to 1 classid 1:8
Error: Handle 10001 is already in use.
So carry those bits over when the key the request builds is the key the
older filter already has. An in-place replace then keeps the handle
userspace named the filter by, while a request that does change the key
still renames it, as it did before.
Fixes: 1da177e4c3 ("Linux-2.6.12-rc2")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260829205422.854785-1-victor%40mojatatu.com
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Victor Nogueira <victor@mojatatu.com>
Link: https://patch.msgid.link/20260907192133.2639067-4-victor@mojatatu.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
b74a8455a2
commit
41e85e54e5
|
|
@ -393,8 +393,9 @@ static const struct nla_policy route4_policy[TCA_ROUTE4_MAX + 1] = {
|
|||
static int route4_set_parms(struct net *net, struct tcf_proto *tp,
|
||||
unsigned long base, struct route4_filter *f,
|
||||
u32 handle, struct route4_head *head,
|
||||
struct nlattr **tb, struct nlattr *est, int new,
|
||||
u32 flags, struct netlink_ext_ack *extack)
|
||||
struct nlattr **tb, struct nlattr *est,
|
||||
struct route4_filter *fold, u32 flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
u32 id = 0, to = 0, nhandle = 0x8000;
|
||||
struct route4_filter *fp;
|
||||
|
|
@ -407,7 +408,7 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
|
|||
return err;
|
||||
|
||||
if (tb[TCA_ROUTE4_TO]) {
|
||||
if (new && handle & 0x8000) {
|
||||
if (!fold && handle & 0x8000) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid handle");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -430,14 +431,14 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
|
|||
} else
|
||||
nhandle |= 0xFFFF << 16;
|
||||
|
||||
if (handle && new) {
|
||||
if (handle && (!fold || nhandle == (handle & ~0x7F00)))
|
||||
nhandle |= handle & 0x7F00;
|
||||
if (nhandle != handle) {
|
||||
NL_SET_ERR_MSG_FMT(extack,
|
||||
"Handle mismatch constructed: %x (expected: %x)",
|
||||
handle, nhandle);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (handle && !fold && nhandle != handle) {
|
||||
NL_SET_ERR_MSG_FMT(extack,
|
||||
"Handle mismatch constructed: %x (expected: %x)",
|
||||
handle, nhandle);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!nhandle) {
|
||||
|
|
@ -460,7 +461,7 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
|
|||
for (fp = rtnl_dereference(b->ht[h2]);
|
||||
fp;
|
||||
fp = rtnl_dereference(fp->next))
|
||||
if (fp->handle == nhandle) {
|
||||
if (fp != fold && fp->handle == nhandle) {
|
||||
NL_SET_ERR_MSG_FMT(extack,
|
||||
"Handle %x is already in use",
|
||||
nhandle);
|
||||
|
|
@ -502,7 +503,6 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
|
|||
struct nlattr *tb[TCA_ROUTE4_MAX + 1];
|
||||
unsigned int h;
|
||||
int err;
|
||||
bool new = true;
|
||||
|
||||
if (!handle) {
|
||||
NL_SET_ERR_MSG(extack, "Creating with handle of 0 is invalid");
|
||||
|
|
@ -539,11 +539,10 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
|
|||
|
||||
f->tp = fold->tp;
|
||||
f->bkt = fold->bkt;
|
||||
new = false;
|
||||
}
|
||||
|
||||
err = route4_set_parms(net, tp, base, f, handle, head, tb,
|
||||
tca[TCA_RATE], new, flags, extack);
|
||||
tca[TCA_RATE], fold, flags, extack);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user