143 lines
4.3 KiB
Diff
143 lines
4.3 KiB
Diff
|
From 3fe083491bf6c688d34c6e300f14d775a5b8a443 Mon Sep 17 00:00:00 2001
|
||
|
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||
|
Date: Mon, 24 Apr 2017 16:26:00 +0200
|
||
|
Subject: [PATCH 2/2] net sched actions: allocate act cookie early
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1682368
|
||
|
|
||
|
Policing filters do not use the TCA_ACT_* enum and the tb[]
|
||
|
nlattr array in tcf_action_init_1() doesn't get filled for
|
||
|
them so we should not try to look for a TCA_ACT_COOKIE
|
||
|
attribute in the then uninitialized array.
|
||
|
The error handling in cookie allocation then calls
|
||
|
tcf_hash_release() leading to invalid memory access later
|
||
|
on.
|
||
|
Additionally, if cookie allocation fails after an already
|
||
|
existing non-policing filter has successfully been changed,
|
||
|
tcf_action_release() should not be called, also we would
|
||
|
have to roll back the changes in the error handling, so
|
||
|
instead we now allocate the cookie early and assign it on
|
||
|
success at the end.
|
||
|
|
||
|
CVE-2017-7979
|
||
|
Fixes: 1045ba77a596 ("net sched actions: Add support for user cookies")
|
||
|
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||
|
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
|
||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||
|
(cherry picked from commit e0535ce58b92d7baf0b33284a6c4f8f0338f943e)
|
||
|
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
|
||
|
Acked-by: Kamal Mostafa <kamal@canonical.com>
|
||
|
Acked-by: Seth Forshee <seth.forshee@canonical.com>
|
||
|
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
|
||
|
|
||
|
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
|
||
|
---
|
||
|
net/sched/act_api.c | 55 +++++++++++++++++++++++++++++++----------------------
|
||
|
1 file changed, 32 insertions(+), 23 deletions(-)
|
||
|
|
||
|
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
|
||
|
index e336f30..bdbc7a9 100644
|
||
|
--- a/net/sched/act_api.c
|
||
|
+++ b/net/sched/act_api.c
|
||
|
@@ -532,20 +532,20 @@ int tcf_action_dump(struct sk_buff *skb, struct list_head *actions,
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
-static int nla_memdup_cookie(struct tc_action *a, struct nlattr **tb)
|
||
|
+static struct tc_cookie *nla_memdup_cookie(struct nlattr **tb)
|
||
|
{
|
||
|
- a->act_cookie = kzalloc(sizeof(*a->act_cookie), GFP_KERNEL);
|
||
|
- if (!a->act_cookie)
|
||
|
- return -ENOMEM;
|
||
|
+ struct tc_cookie *c = kzalloc(sizeof(*c), GFP_KERNEL);
|
||
|
+ if (!c)
|
||
|
+ return NULL;
|
||
|
|
||
|
- a->act_cookie->data = nla_memdup(tb[TCA_ACT_COOKIE], GFP_KERNEL);
|
||
|
- if (!a->act_cookie->data) {
|
||
|
- kfree(a->act_cookie);
|
||
|
- return -ENOMEM;
|
||
|
+ c->data = nla_memdup(tb[TCA_ACT_COOKIE], GFP_KERNEL);
|
||
|
+ if (!c->data) {
|
||
|
+ kfree(c);
|
||
|
+ return NULL;
|
||
|
}
|
||
|
- a->act_cookie->len = nla_len(tb[TCA_ACT_COOKIE]);
|
||
|
+ c->len = nla_len(tb[TCA_ACT_COOKIE]);
|
||
|
|
||
|
- return 0;
|
||
|
+ return c;
|
||
|
}
|
||
|
|
||
|
struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
|
||
|
@@ -554,6 +554,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
|
||
|
{
|
||
|
struct tc_action *a;
|
||
|
struct tc_action_ops *a_o;
|
||
|
+ struct tc_cookie *cookie = NULL;
|
||
|
char act_name[IFNAMSIZ];
|
||
|
struct nlattr *tb[TCA_ACT_MAX + 1];
|
||
|
struct nlattr *kind;
|
||
|
@@ -569,6 +570,18 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
|
||
|
goto err_out;
|
||
|
if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ)
|
||
|
goto err_out;
|
||
|
+ if (tb[TCA_ACT_COOKIE]) {
|
||
|
+ int cklen = nla_len(tb[TCA_ACT_COOKIE]);
|
||
|
+
|
||
|
+ if (cklen > TC_COOKIE_MAX_SIZE)
|
||
|
+ goto err_out;
|
||
|
+
|
||
|
+ cookie = nla_memdup_cookie(tb);
|
||
|
+ if (!cookie) {
|
||
|
+ err = -ENOMEM;
|
||
|
+ goto err_out;
|
||
|
+ }
|
||
|
+ }
|
||
|
} else {
|
||
|
err = -EINVAL;
|
||
|
if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ)
|
||
|
@@ -607,20 +620,12 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
|
||
|
if (err < 0)
|
||
|
goto err_mod;
|
||
|
|
||
|
- if (tb[TCA_ACT_COOKIE]) {
|
||
|
- int cklen = nla_len(tb[TCA_ACT_COOKIE]);
|
||
|
-
|
||
|
- if (cklen > TC_COOKIE_MAX_SIZE) {
|
||
|
- err = -EINVAL;
|
||
|
- tcf_hash_release(a, bind);
|
||
|
- goto err_mod;
|
||
|
- }
|
||
|
-
|
||
|
- if (nla_memdup_cookie(a, tb) < 0) {
|
||
|
- err = -ENOMEM;
|
||
|
- tcf_hash_release(a, bind);
|
||
|
- goto err_mod;
|
||
|
+ if (name == NULL && tb[TCA_ACT_COOKIE]) {
|
||
|
+ if (a->act_cookie) {
|
||
|
+ kfree(a->act_cookie->data);
|
||
|
+ kfree(a->act_cookie);
|
||
|
}
|
||
|
+ a->act_cookie = cookie;
|
||
|
}
|
||
|
|
||
|
/* module count goes up only when brand new policy is created
|
||
|
@@ -635,6 +640,10 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
|
||
|
err_mod:
|
||
|
module_put(a_o->owner);
|
||
|
err_out:
|
||
|
+ if (cookie) {
|
||
|
+ kfree(cookie->data);
|
||
|
+ kfree(cookie);
|
||
|
+ }
|
||
|
return ERR_PTR(err);
|
||
|
}
|
||
|
|
||
|
--
|
||
|
2.1.4
|
||
|
|