提交 5b5fa0f3 编写于 作者: P Pedro Tammela 提交者: Yongqiang Liu

net/sched: tcindex: update imperfect hash filters respecting rcu

mainline inclusion
from mainline-v6.2-rc7
commit ee059170
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I6OP9S
CVE: CVE-2023-1281

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ee059170b1f7e94e55fa6cadee544e176a6e59c2

---------------------------

The imperfect hash area can be updated while packets are traversing,
which will cause a use-after-free when 'tcf_exts_exec()' is called
with the destroyed tcf_ext.

CPU 0:               CPU 1:
tcindex_set_parms    tcindex_classify
tcindex_lookup
                     tcindex_lookup
tcf_exts_change
                     tcf_exts_exec [UAF]

Stop operating on the shared area directly, by using a local copy,
and update the filter with 'rcu_replace_pointer()'. Delete the old
filter version only after a rcu grace period elapsed.

Fixes: 9b0d4446 ("net: sched: avoid atomic swap in tcf_exts_change")
Reported-by: Nvalis <sec@valis.email>
Suggested-by: Nvalis <sec@valis.email>
Signed-off-by: NJamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: NPedro Tammela <pctammela@mojatatu.com>
Link: https://lore.kernel.org/r/20230209143739.279867-1-pctammela@mojatatu.comSigned-off-by: NJakub Kicinski <kuba@kernel.org>
Conflict:
	net/sched/cls_tcindex.c
Signed-off-by: NDong Chenchen <dongchenchen2@huawei.com>
Reviewed-by: NYue Haibing <yuehaibing@huawei.com>
Reviewed-by: NWang Weiyang <wangweiyang2@huawei.com>
Signed-off-by: NZhang Changzhong <zhangchangzhong@huawei.com>
上级 e476efc3
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/rcupdate.h>
#include <net/act_api.h> #include <net/act_api.h>
#include <net/netlink.h> #include <net/netlink.h>
#include <net/pkt_cls.h> #include <net/pkt_cls.h>
...@@ -309,6 +310,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, ...@@ -309,6 +310,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
struct tcf_result cr = {}; struct tcf_result cr = {};
int err, balloc = 0; int err, balloc = 0;
struct tcf_exts e; struct tcf_exts e;
bool update_h = false;
err = tcf_exts_init(&e, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); err = tcf_exts_init(&e, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
if (err < 0) if (err < 0)
...@@ -425,10 +427,13 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, ...@@ -425,10 +427,13 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
} }
} }
if (cp->perfect) if (cp->perfect) {
r = cp->perfect + handle; r = cp->perfect + handle;
else } else {
r = tcindex_lookup(cp, handle) ? : &new_filter_result; /* imperfect area is updated in-place using rcu */
update_h = !!tcindex_lookup(cp, handle);
r = &new_filter_result;
}
if (r == &new_filter_result) { if (r == &new_filter_result) {
f = kzalloc(sizeof(*f), GFP_KERNEL); f = kzalloc(sizeof(*f), GFP_KERNEL);
...@@ -462,7 +467,28 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, ...@@ -462,7 +467,28 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
rcu_assign_pointer(tp->root, cp); rcu_assign_pointer(tp->root, cp);
if (r == &new_filter_result) { if (update_h) {
struct tcindex_filter __rcu **fp;
struct tcindex_filter *cf;
f->result.res = r->res;
tcf_exts_change(&f->result.exts, &r->exts);
/* imperfect area bucket */
fp = cp->h + (handle % cp->hash);
/* lookup the filter, guaranteed to exist */
for (cf = rcu_dereference_bh_rtnl(*fp); cf;
fp = &cf->next, cf = rcu_dereference_bh_rtnl(*fp))
if (cf->key == handle)
break;
f->next = cf->next;
cf = rcu_replace_pointer(*fp, f, 1);
tcf_exts_get_net(&cf->result.exts);
tcf_queue_work(&cf->rwork, tcindex_destroy_fexts_work);
} else if (r == &new_filter_result) {
struct tcindex_filter *nfp; struct tcindex_filter *nfp;
struct tcindex_filter __rcu **fp; struct tcindex_filter __rcu **fp;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册