kernel: fix crash in act_connmark in 3.9 and 3.10 (fixes #13916, #13876)
authorFelix Fietkau <nbd@openwrt.org>
Sun, 21 Jul 2013 13:53:54 +0000 (13:53 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sun, 21 Jul 2013 13:53:54 +0000 (13:53 +0000)
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
SVN-Revision: 37493

target/linux/generic/patches-3.10/621-sched_act_connmark.patch
target/linux/generic/patches-3.9/621-sched_act_connmark.patch

index 0393f1589331e4e3844113291beb855b7b6fe0f1..e6c050aaa27eb0be9632b98484f9028b749418a4 100644 (file)
@@ -1,6 +1,6 @@
 --- /dev/null
 +++ b/net/sched/act_connmark.c
-@@ -0,0 +1,137 @@
+@@ -0,0 +1,148 @@
 +/*
 + * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org>
 + *
 +      return TC_ACT_PIPE;
 +}
 +
-+static int tcf_connmark_init(struct nlattr *nla, struct nlattr *est,
-+                       struct tc_action *a, int ovr, int bind)
++static int tcf_connmark_init(struct net *net, struct nlattr *nla,
++                           struct nlattr *est, struct tc_action *a,
++                           int ovr, int bind)
 +{
 +      struct tcf_common *pc;
-+
-+      pc = tcf_hash_create(0, est, a, sizeof(*pc), bind,
-+                           &connmark_idx_gen, &connmark_hash_info);
-+      if (IS_ERR(pc))
-+          return PTR_ERR(pc);
-+
-+      tcf_hash_insert(pc, &connmark_hash_info);
-+
-+      return ACT_P_CREATED;
++      int ret = 0;
++
++      pc = tcf_hash_check(0, a, bind, &connmark_hash_info);
++      if (!pc) {
++              pc = tcf_hash_create(0, est, a, sizeof(*pc), bind,
++                                   &connmark_idx_gen, &connmark_hash_info);
++              if (IS_ERR(pc))
++                  return PTR_ERR(pc);
++
++              tcf_hash_insert(pc, &connmark_hash_info);
++              ret = ACT_P_CREATED;
++      } else {
++              if (!ovr) {
++                      tcf_hash_release(pc, bind, &connmark_hash_info);
++                      return -EEXIST;
++              }
++      }
++
++      return ret;
 +}
 +
 +static inline int tcf_connmark_cleanup(struct tc_action *a, int bind)
index 0393f1589331e4e3844113291beb855b7b6fe0f1..e6c050aaa27eb0be9632b98484f9028b749418a4 100644 (file)
@@ -1,6 +1,6 @@
 --- /dev/null
 +++ b/net/sched/act_connmark.c
-@@ -0,0 +1,137 @@
+@@ -0,0 +1,148 @@
 +/*
 + * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org>
 + *
 +      return TC_ACT_PIPE;
 +}
 +
-+static int tcf_connmark_init(struct nlattr *nla, struct nlattr *est,
-+                       struct tc_action *a, int ovr, int bind)
++static int tcf_connmark_init(struct net *net, struct nlattr *nla,
++                           struct nlattr *est, struct tc_action *a,
++                           int ovr, int bind)
 +{
 +      struct tcf_common *pc;
-+
-+      pc = tcf_hash_create(0, est, a, sizeof(*pc), bind,
-+                           &connmark_idx_gen, &connmark_hash_info);
-+      if (IS_ERR(pc))
-+          return PTR_ERR(pc);
-+
-+      tcf_hash_insert(pc, &connmark_hash_info);
-+
-+      return ACT_P_CREATED;
++      int ret = 0;
++
++      pc = tcf_hash_check(0, a, bind, &connmark_hash_info);
++      if (!pc) {
++              pc = tcf_hash_create(0, est, a, sizeof(*pc), bind,
++                                   &connmark_idx_gen, &connmark_hash_info);
++              if (IS_ERR(pc))
++                  return PTR_ERR(pc);
++
++              tcf_hash_insert(pc, &connmark_hash_info);
++              ret = ACT_P_CREATED;
++      } else {
++              if (!ovr) {
++                      tcf_hash_release(pc, bind, &connmark_hash_info);
++                      return -EEXIST;
++              }
++      }
++
++      return ret;
 +}
 +
 +static inline int tcf_connmark_cleanup(struct tc_action *a, int bind)