Commit ec0acb09 authored by Xin Long's avatar Xin Long Committed by David S. Miller

net: sched: set xt_tgchk_param par.net properly in ipt_init_target

Now xt_tgchk_param par in ipt_init_target is a local varibale,
par.net is not initialized there. Later when xt_check_target
calls target's checkentry in which it may access par.net, it
would cause kernel panic.

Jaroslav found this panic when running:

  # ip link add TestIface type dummy
  # tc qd add dev TestIface ingress handle ffff:
  # tc filter add dev TestIface parent ffff: u32 match u32 0 0 \
    action xt -j CONNMARK --set-mark 4

This patch is to pass net param into ipt_init_target and set
par.net with it properly in there.

v1->v2:
  As Wang Cong pointed, I missed ipt_net_id != xt_net_id, so fix
  it by also passing net_id to __tcf_ipt_init.
v2->v3:
  Missed the fixes tag, so add it.

Fixes: ecb2421b ("netfilter: add and use nf_ct_netns_get/put")
Reported-by: default avatarJaroslav Aster <jaster@redhat.com>
Signed-off-by: default avatarXin Long <lucien.xin@gmail.com>
Acked-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8e6f1521
...@@ -36,8 +36,8 @@ static struct tc_action_ops act_ipt_ops; ...@@ -36,8 +36,8 @@ static struct tc_action_ops act_ipt_ops;
static unsigned int xt_net_id; static unsigned int xt_net_id;
static struct tc_action_ops act_xt_ops; static struct tc_action_ops act_xt_ops;
static int ipt_init_target(struct xt_entry_target *t, char *table, static int ipt_init_target(struct net *net, struct xt_entry_target *t,
unsigned int hook) char *table, unsigned int hook)
{ {
struct xt_tgchk_param par; struct xt_tgchk_param par;
struct xt_target *target; struct xt_target *target;
...@@ -49,6 +49,7 @@ static int ipt_init_target(struct xt_entry_target *t, char *table, ...@@ -49,6 +49,7 @@ static int ipt_init_target(struct xt_entry_target *t, char *table,
return PTR_ERR(target); return PTR_ERR(target);
t->u.kernel.target = target; t->u.kernel.target = target;
par.net = net;
par.table = table; par.table = table;
par.entryinfo = NULL; par.entryinfo = NULL;
par.target = target; par.target = target;
...@@ -91,10 +92,11 @@ static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = { ...@@ -91,10 +92,11 @@ static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = {
[TCA_IPT_TARG] = { .len = sizeof(struct xt_entry_target) }, [TCA_IPT_TARG] = { .len = sizeof(struct xt_entry_target) },
}; };
static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, struct nlattr *est, struct tc_action **a,
const struct tc_action_ops *ops, int ovr, int bind) const struct tc_action_ops *ops, int ovr, int bind)
{ {
struct tc_action_net *tn = net_generic(net, id);
struct nlattr *tb[TCA_IPT_MAX + 1]; struct nlattr *tb[TCA_IPT_MAX + 1];
struct tcf_ipt *ipt; struct tcf_ipt *ipt;
struct xt_entry_target *td, *t; struct xt_entry_target *td, *t;
...@@ -159,7 +161,7 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, ...@@ -159,7 +161,7 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
if (unlikely(!t)) if (unlikely(!t))
goto err2; goto err2;
err = ipt_init_target(t, tname, hook); err = ipt_init_target(net, t, tname, hook);
if (err < 0) if (err < 0)
goto err3; goto err3;
...@@ -193,18 +195,16 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, ...@@ -193,18 +195,16 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, int ovr, struct nlattr *est, struct tc_action **a, int ovr,
int bind) int bind)
{ {
struct tc_action_net *tn = net_generic(net, ipt_net_id); return __tcf_ipt_init(net, ipt_net_id, nla, est, a, &act_ipt_ops, ovr,
bind);
return __tcf_ipt_init(tn, nla, est, a, &act_ipt_ops, ovr, bind);
} }
static int tcf_xt_init(struct net *net, struct nlattr *nla, static int tcf_xt_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **a, int ovr, struct nlattr *est, struct tc_action **a, int ovr,
int bind) int bind)
{ {
struct tc_action_net *tn = net_generic(net, xt_net_id); return __tcf_ipt_init(net, xt_net_id, nla, est, a, &act_xt_ops, ovr,
bind);
return __tcf_ipt_init(tn, nla, est, a, &act_xt_ops, ovr, bind);
} }
static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a, static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment