| From 30f52768930ecb6e92a3507a4e427ebda3de110c Mon Sep 17 00:00:00 2001 |
| From: Cong Wang <xiyou.wangcong@gmail.com> |
| Date: Fri, 13 Mar 2020 22:29:54 -0700 |
| Subject: [PATCH] net_sched: cls_route: remove the right filter from hashtable |
| |
| commit ef299cc3fa1a9e1288665a9fdc8bff55629fd359 upstream. |
| |
| route4_change() allocates a new filter and copies values from |
| the old one. After the new filter is inserted into the hash |
| table, the old filter should be removed and freed, as the final |
| step of the update. |
| |
| However, the current code mistakenly removes the new one. This |
| looks apparently wrong to me, and it causes double "free" and |
| use-after-free too, as reported by syzbot. |
| |
| Reported-and-tested-by: syzbot+f9b32aaacd60305d9687@syzkaller.appspotmail.com |
| Reported-and-tested-by: syzbot+2f8c233f131943d6056d@syzkaller.appspotmail.com |
| Reported-and-tested-by: syzbot+9c2df9fd5e9445b74e01@syzkaller.appspotmail.com |
| Fixes: 1109c00547fc ("net: sched: RCU cls_route") |
| Cc: Jamal Hadi Salim <jhs@mojatatu.com> |
| Cc: Jiri Pirko <jiri@resnulli.us> |
| Cc: John Fastabend <john.fastabend@gmail.com> |
| Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c |
| index 6f8786b06bde..5efa3e7ace15 100644 |
| --- a/net/sched/cls_route.c |
| +++ b/net/sched/cls_route.c |
| @@ -534,8 +534,8 @@ static int route4_change(struct net *net, struct sk_buff *in_skb, |
| fp = &b->ht[h]; |
| for (pfp = rtnl_dereference(*fp); pfp; |
| fp = &pfp->next, pfp = rtnl_dereference(*fp)) { |
| - if (pfp == f) { |
| - *fp = f->next; |
| + if (pfp == fold) { |
| + rcu_assign_pointer(*fp, fold->next); |
| break; |
| } |
| } |
| -- |
| 2.7.4 |
| |