These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / net / netfilter / xt_CT.c
index 75747ae..e7ac07e 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,10 +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_tuple t;
+       struct nf_conntrack_zone zone;
        struct nf_conn *ct;
        int ret = -EOPNOTSUPP;
 
@@ -194,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
 
@@ -202,11 +220,17 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
        if (ret < 0)
                goto err1;
 
-       memset(&t, 0, sizeof(t));
-       ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL);
-       ret = PTR_ERR(ct);
-       if (IS_ERR(ct))
+       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;
+       }
 
        ret = 0;
        if ((info->ct_events || info->exp_events) &&
@@ -227,14 +251,14 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
                if (ret < 0)
                        goto err3;
        }
-
-       nf_conntrack_tmpl_insert(par->net, ct);
+       __set_bit(IPS_CONFIRMED_BIT, &ct->status);
+       nf_conntrack_get(&ct->ct_general);
 out:
        info->ct = ct;
        return 0;
 
 err3:
-       nf_conntrack_free(ct);
+       nf_ct_tmpl_free(ct);
 err2:
        nf_ct_l3proto_module_put(par->family);
 err1:
@@ -297,8 +321,10 @@ static void xt_ct_destroy_timeout(struct nf_conn *ct)
 
        if (timeout_put) {
                timeout_ext = nf_ct_timeout_find(ct);
-               if (timeout_ext)
+               if (timeout_ext) {
                        timeout_put(timeout_ext->timeout);
+                       RCU_INIT_POINTER(timeout_ext->timeout, NULL);
+               }
        }
        rcu_read_unlock();
 #endif