netfilter: xt_CT: don't put back reference to timeout policy object
[cascardo/linux.git] / net / netfilter / xt_CT.c
index 43ddeee..a03924c 100644 (file)
@@ -171,6 +171,9 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
        if (timeout_ext == NULL)
                ret = -ENOMEM;
 
+       rcu_read_unlock();
+       return ret;
+
 err_put_timeout:
        __xt_ct_tg_timeout_put(timeout);
 out:
@@ -181,9 +184,23 @@ out:
 #endif
 }
 
+static u16 xt_ct_flags_to_dir(const struct xt_ct_target_info_v1 *info)
+{
+       switch (info->flags & (XT_CT_ZONE_DIR_ORIG |
+                              XT_CT_ZONE_DIR_REPL)) {
+       case XT_CT_ZONE_DIR_ORIG:
+               return NF_CT_ZONE_DIR_ORIG;
+       case XT_CT_ZONE_DIR_REPL:
+               return NF_CT_ZONE_DIR_REPL;
+       default:
+               return NF_CT_DEFAULT_ZONE_DIR;
+       }
+}
+
 static int xt_ct_tg_check(const struct xt_tgchk_param *par,
                          struct xt_ct_target_info_v1 *info)
 {
+       struct nf_conntrack_zone zone;
        struct nf_conn *ct;
        int ret = -EOPNOTSUPP;
 
@@ -193,7 +210,9 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
        }
 
 #ifndef CONFIG_NF_CONNTRACK_ZONES
-       if (info->zone)
+       if (info->zone || info->flags & (XT_CT_ZONE_DIR_ORIG |
+                                        XT_CT_ZONE_DIR_REPL |
+                                        XT_CT_ZONE_MARK))
                goto err1;
 #endif
 
@@ -201,7 +220,13 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
        if (ret < 0)
                goto err1;
 
-       ct = nf_ct_tmpl_alloc(par->net, info->zone, GFP_KERNEL);
+       memset(&zone, 0, sizeof(zone));
+       zone.id = info->zone;
+       zone.dir = xt_ct_flags_to_dir(info);
+       if (info->flags & XT_CT_ZONE_MARK)
+               zone.flags |= NF_CT_FLAG_MARK;
+
+       ct = nf_ct_tmpl_alloc(par->net, &zone, GFP_KERNEL);
        if (!ct) {
                ret = -ENOMEM;
                goto err2;
@@ -233,7 +258,7 @@ out:
        return 0;
 
 err3:
-       nf_conntrack_free(ct);
+       nf_ct_tmpl_free(ct);
 err2:
        nf_ct_l3proto_module_put(par->family);
 err1: