net: Compute protocol sequence numbers and fragment IDs using MD5, CVE-2011-3188
[linux-flexiantxendom0-natty.git] / net / ipv4 / netfilter / nf_nat_proto_common.c
index 91537f1..f52d41e 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/ip.h>
 
 #include <linux/netfilter.h>
+#include <net/secure_seq.h>
 #include <net/netfilter/nf_nat.h>
 #include <net/netfilter/nf_nat_core.h>
 #include <net/netfilter/nf_nat_rule.h>
@@ -34,7 +35,7 @@ bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple,
 }
 EXPORT_SYMBOL_GPL(nf_nat_proto_in_range);
 
-bool nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
+void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
                               const struct nf_nat_range *range,
                               enum nf_nat_manip_type maniptype,
                               const struct nf_conn *ct,
@@ -53,7 +54,7 @@ bool nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
        if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
                /* If it's dst rewrite, can't change port */
                if (maniptype == IP_NAT_MANIP_DST)
-                       return false;
+                       return;
 
                if (ntohs(*portptr) < 1024) {
                        /* Loose convention: >> 512 is credential passing */
@@ -73,19 +74,23 @@ bool nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
                range_size = ntohs(range->max.all) - min + 1;
        }
 
-       off = *rover;
        if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
-               off = net_random();
+               off = secure_ipv4_port_ephemeral(tuple->src.u3.ip, tuple->dst.u3.ip,
+                                                maniptype == IP_NAT_MANIP_SRC
+                                                ? tuple->dst.u.all
+                                                : tuple->src.u.all);
+       else
+               off = *rover;
 
-       for (i = 0; i < range_size; i++, off++) {
+       for (i = 0; ; ++off) {
                *portptr = htons(min + off % range_size);
-               if (nf_nat_used_tuple(tuple, ct))
+               if (++i != range_size && nf_nat_used_tuple(tuple, ct))
                        continue;
                if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
                        *rover = off;
-               return true;
+               return;
        }
-       return false;
+       return;
 }
 EXPORT_SYMBOL_GPL(nf_nat_proto_unique_tuple);