]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
authorDavid S. Miller <davem@davemloft.net>
Thu, 25 Apr 2013 04:53:40 +0000 (00:53 -0400)
committerDavid S. Miller <davem@davemloft.net>
Thu, 25 Apr 2013 04:53:40 +0000 (00:53 -0400)
Pablo Neira Ayuso says:

====================
The following patchset contains fixes for recently applied
Netfilter/IPVS updates to the net-next tree, most relevantly
they are:

* Fix sparse warnings introduced in the RCU conversion, from
  Julian Anastasov.

* Fix wrong endianness in the size field of IPVS sync messages,
  from Simon Horman.

* Fix missing if checking in nf_xfrm_me_harder, from Dan Carpenter.

* Fix off by one access in the IPVS SCTP tracking code, again from
  Dan Carpenter.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ip_vs.h
include/uapi/linux/ip_vs.h
net/netfilter/ipvs/ip_vs_conn.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/ipvs/ip_vs_lblc.c
net/netfilter/ipvs/ip_vs_lblcr.c
net/netfilter/ipvs/ip_vs_pe_sip.c
net/netfilter/ipvs/ip_vs_proto_sctp.c
net/netfilter/ipvs/ip_vs_sync.c
net/netfilter/nf_nat_core.c

index f9f5b057b480fbacf7a43801aa9a2e81a1605728..4c062ccff9aa4cfa65ba9ecbbc22435c393d6620 100644 (file)
@@ -678,7 +678,7 @@ struct ip_vs_service_user_kern {
        u16                     af;
        u16                     protocol;
        union nf_inet_addr      addr;           /* virtual ip address */
-       u16                     port;
+       __be16                  port;
        u32                     fwmark;         /* firwall mark of service */
 
        /* virtual service options */
@@ -686,14 +686,14 @@ struct ip_vs_service_user_kern {
        char                    *pe_name;
        unsigned int            flags;          /* virtual service flags */
        unsigned int            timeout;        /* persistent timeout in sec */
-       u32                     netmask;        /* persistent netmask */
+       __be32                  netmask;        /* persistent netmask or plen */
 };
 
 
 struct ip_vs_dest_user_kern {
        /* destination server address */
        union nf_inet_addr      addr;
-       u16                     port;
+       __be16                  port;
 
        /* real server options */
        unsigned int            conn_flags;     /* connection flags */
@@ -721,7 +721,7 @@ struct ip_vs_service {
        __u32                   fwmark;   /* firewall mark of the service */
        unsigned int            flags;    /* service status flags */
        unsigned int            timeout;  /* persistent timeout in ticks */
-       __be32                  netmask;  /* grouping granularity */
+       __be32                  netmask;  /* grouping granularity, mask/plen */
        struct net              *net;
 
        struct list_head        destinations;  /* real server d-linked list */
index 8a2d438dc4999bfbb35b52a60325affdae7d9347..a24537725e805643c1ce4df1796d21d34efc9432 100644 (file)
@@ -280,8 +280,8 @@ struct ip_vs_daemon_user {
 #define IPVS_GENL_VERSION      0x1
 
 struct ip_vs_flags {
-       __be32 flags;
-       __be32 mask;
+       __u32 flags;
+       __u32 mask;
 };
 
 /* Generic Netlink command attributes */
index de6475894a39e10b04c7892fe53960a92b8ac1b4..a083bda322b6058cf0ba6b65b604bb046c8a79fd 100644 (file)
@@ -966,7 +966,6 @@ static void *ip_vs_conn_array(struct seq_file *seq, loff_t pos)
        struct ip_vs_iter_state *iter = seq->private;
 
        for (idx = 0; idx < ip_vs_conn_tab_size; idx++) {
-               rcu_read_lock();
                hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[idx], c_list) {
                        /* __ip_vs_conn_get() is not needed by
                         * ip_vs_conn_seq_show and ip_vs_conn_sync_seq_show
@@ -977,16 +976,19 @@ static void *ip_vs_conn_array(struct seq_file *seq, loff_t pos)
                        }
                }
                rcu_read_unlock();
+               rcu_read_lock();
        }
 
        return NULL;
 }
 
 static void *ip_vs_conn_seq_start(struct seq_file *seq, loff_t *pos)
+       __acquires(RCU)
 {
        struct ip_vs_iter_state *iter = seq->private;
 
        iter->l = NULL;
+       rcu_read_lock();
        return *pos ? ip_vs_conn_array(seq, *pos - 1) :SEQ_START_TOKEN;
 }
 
@@ -1006,28 +1008,24 @@ static void *ip_vs_conn_seq_next(struct seq_file *seq, void *v, loff_t *pos)
        e = rcu_dereference(hlist_next_rcu(&cp->c_list));
        if (e)
                return hlist_entry(e, struct ip_vs_conn, c_list);
-       rcu_read_unlock();
 
        idx = l - ip_vs_conn_tab;
        while (++idx < ip_vs_conn_tab_size) {
-               rcu_read_lock();
                hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[idx], c_list) {
                        iter->l = &ip_vs_conn_tab[idx];
                        return cp;
                }
                rcu_read_unlock();
+               rcu_read_lock();
        }
        iter->l = NULL;
        return NULL;
 }
 
 static void ip_vs_conn_seq_stop(struct seq_file *seq, void *v)
+       __releases(RCU)
 {
-       struct ip_vs_iter_state *iter = seq->private;
-       struct hlist_head *l = iter->l;
-
-       if (l)
-               rcu_read_unlock();
+       rcu_read_unlock();
 }
 
 static int ip_vs_conn_seq_show(struct seq_file *seq, void *v)
index f26fe3353a306bcee128dbad2c3619be9d3dbd73..085b5880ab0de4aa90819d9729a13ff5b635cc15 100644 (file)
@@ -235,7 +235,8 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
        /* Mask saddr with the netmask to adjust template granularity */
 #ifdef CONFIG_IP_VS_IPV6
        if (svc->af == AF_INET6)
-               ipv6_addr_prefix(&snet.in6, &iph->saddr.in6, svc->netmask);
+               ipv6_addr_prefix(&snet.in6, &iph->saddr.in6,
+                                (__force __u32) svc->netmask);
        else
 #endif
                snet.ip = iph->saddr.ip & svc->netmask;
@@ -583,9 +584,9 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 #ifdef CONFIG_IP_VS_IPV6
        if (svc->af == AF_INET6) {
                if (!skb->dev) {
-                       struct net *net = dev_net(skb_dst(skb)->dev);
+                       struct net *net_ = dev_net(skb_dst(skb)->dev);
 
-                       skb->dev = net->loopback_dev;
+                       skb->dev = net_->loopback_dev;
                }
                icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
        } else
index 9e4074c26dc29c8abc6439ea6baf3a219968d91c..5b142fb164801bee9ab126d00fa3e485cdf96c60 100644 (file)
@@ -1164,9 +1164,13 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u,
        }
 
 #ifdef CONFIG_IP_VS_IPV6
-       if (u->af == AF_INET6 && (u->netmask < 1 || u->netmask > 128)) {
-               ret = -EINVAL;
-               goto out_err;
+       if (u->af == AF_INET6) {
+               __u32 plen = (__force __u32) u->netmask;
+
+               if (plen < 1 || plen > 128) {
+                       ret = -EINVAL;
+                       goto out_err;
+               }
        }
 #endif
 
@@ -1277,9 +1281,13 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
        }
 
 #ifdef CONFIG_IP_VS_IPV6
-       if (u->af == AF_INET6 && (u->netmask < 1 || u->netmask > 128)) {
-               ret = -EINVAL;
-               goto out;
+       if (u->af == AF_INET6) {
+               __u32 plen = (__force __u32) u->netmask;
+
+               if (plen < 1 || plen > 128) {
+                       ret = -EINVAL;
+                       goto out;
+               }
        }
 #endif
 
@@ -1460,8 +1468,11 @@ void ip_vs_service_net_cleanup(struct net *net)
 static inline void
 ip_vs_forget_dev(struct ip_vs_dest *dest, struct net_device *dev)
 {
+       struct ip_vs_dest_dst *dest_dst;
+
        spin_lock_bh(&dest->dst_lock);
-       if (dest->dest_dst && dest->dest_dst->dst_cache->dev == dev) {
+       dest_dst = rcu_dereference_protected(dest->dest_dst, 1);
+       if (dest_dst && dest_dst->dst_cache->dev == dev) {
                IP_VS_DBG_BUF(3, "Reset dev:%s dest %s:%u ,dest->refcnt=%d\n",
                              dev->name,
                              IP_VS_DBG_ADDR(dest->af, &dest->addr),
@@ -1934,8 +1945,8 @@ static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos)
 }
 
 static void *ip_vs_info_seq_start(struct seq_file *seq, loff_t *pos)
+       __acquires(RCU)
 {
-
        rcu_read_lock();
        return *pos ? ip_vs_info_array(seq, *pos - 1) : SEQ_START_TOKEN;
 }
@@ -1990,6 +2001,7 @@ static void *ip_vs_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 }
 
 static void ip_vs_info_seq_stop(struct seq_file *seq, void *v)
+       __releases(RCU)
 {
        rcu_read_unlock();
 }
@@ -2134,7 +2146,7 @@ static int ip_vs_stats_percpu_show(struct seq_file *seq, void *v)
 {
        struct net *net = seq_file_single_net(seq);
        struct ip_vs_stats *tot_stats = &net_ipvs(net)->tot_stats;
-       struct ip_vs_cpu_stats *cpustats = tot_stats->cpustats;
+       struct ip_vs_cpu_stats __percpu *cpustats = tot_stats->cpustats;
        struct ip_vs_stats_user rates;
        int i;
 
@@ -2871,6 +2883,7 @@ static int ip_vs_genl_fill_service(struct sk_buff *skb,
                                   struct ip_vs_service *svc)
 {
        struct ip_vs_scheduler *sched;
+       struct ip_vs_pe *pe;
        struct nlattr *nl_service;
        struct ip_vs_flags flags = { .flags = svc->flags,
                                     .mask = ~0 };
@@ -2887,17 +2900,17 @@ static int ip_vs_genl_fill_service(struct sk_buff *skb,
        } else {
                if (nla_put_u16(skb, IPVS_SVC_ATTR_PROTOCOL, svc->protocol) ||
                    nla_put(skb, IPVS_SVC_ATTR_ADDR, sizeof(svc->addr), &svc->addr) ||
-                   nla_put_u16(skb, IPVS_SVC_ATTR_PORT, svc->port))
+                   nla_put_be16(skb, IPVS_SVC_ATTR_PORT, svc->port))
                        goto nla_put_failure;
        }
 
        sched = rcu_dereference_protected(svc->scheduler, 1);
+       pe = rcu_dereference_protected(svc->pe, 1);
        if (nla_put_string(skb, IPVS_SVC_ATTR_SCHED_NAME, sched->name) ||
-           (svc->pe &&
-            nla_put_string(skb, IPVS_SVC_ATTR_PE_NAME, svc->pe->name)) ||
+           (pe && nla_put_string(skb, IPVS_SVC_ATTR_PE_NAME, pe->name)) ||
            nla_put(skb, IPVS_SVC_ATTR_FLAGS, sizeof(flags), &flags) ||
            nla_put_u32(skb, IPVS_SVC_ATTR_TIMEOUT, svc->timeout / HZ) ||
-           nla_put_u32(skb, IPVS_SVC_ATTR_NETMASK, svc->netmask))
+           nla_put_be32(skb, IPVS_SVC_ATTR_NETMASK, svc->netmask))
                goto nla_put_failure;
        if (ip_vs_genl_fill_stats(skb, IPVS_SVC_ATTR_STATS, &svc->stats))
                goto nla_put_failure;
@@ -3010,7 +3023,7 @@ static int ip_vs_genl_parse_service(struct net *net,
        } else {
                usvc->protocol = nla_get_u16(nla_protocol);
                nla_memcpy(&usvc->addr, nla_addr, sizeof(usvc->addr));
-               usvc->port = nla_get_u16(nla_port);
+               usvc->port = nla_get_be16(nla_port);
                usvc->fwmark = 0;
        }
 
@@ -3050,7 +3063,7 @@ static int ip_vs_genl_parse_service(struct net *net,
                usvc->sched_name = nla_data(nla_sched);
                usvc->pe_name = nla_pe ? nla_data(nla_pe) : NULL;
                usvc->timeout = nla_get_u32(nla_timeout);
-               usvc->netmask = nla_get_u32(nla_netmask);
+               usvc->netmask = nla_get_be32(nla_netmask);
        }
 
        return 0;
@@ -3076,7 +3089,7 @@ static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest)
                return -EMSGSIZE;
 
        if (nla_put(skb, IPVS_DEST_ATTR_ADDR, sizeof(dest->addr), &dest->addr) ||
-           nla_put_u16(skb, IPVS_DEST_ATTR_PORT, dest->port) ||
+           nla_put_be16(skb, IPVS_DEST_ATTR_PORT, dest->port) ||
            nla_put_u32(skb, IPVS_DEST_ATTR_FWD_METHOD,
                        (atomic_read(&dest->conn_flags) &
                         IP_VS_CONN_F_FWD_MASK)) ||
@@ -3185,7 +3198,7 @@ static int ip_vs_genl_parse_dest(struct ip_vs_dest_user_kern *udest,
        memset(udest, 0, sizeof(*udest));
 
        nla_memcpy(&udest->addr, nla_addr, sizeof(udest->addr));
-       udest->port = nla_get_u16(nla_port);
+       udest->port = nla_get_be16(nla_port);
 
        /* If a full entry was requested, check for the additional fields */
        if (full_entry) {
@@ -3210,8 +3223,8 @@ static int ip_vs_genl_parse_dest(struct ip_vs_dest_user_kern *udest,
        return 0;
 }
 
-static int ip_vs_genl_fill_daemon(struct sk_buff *skb, __be32 state,
-                                 const char *mcast_ifn, __be32 syncid)
+static int ip_vs_genl_fill_daemon(struct sk_buff *skb, __u32 state,
+                                 const char *mcast_ifn, __u32 syncid)
 {
        struct nlattr *nl_daemon;
 
@@ -3232,8 +3245,8 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
-static int ip_vs_genl_dump_daemon(struct sk_buff *skb, __be32 state,
-                                 const char *mcast_ifn, __be32 syncid,
+static int ip_vs_genl_dump_daemon(struct sk_buff *skb, __u32 state,
+                                 const char *mcast_ifn, __u32 syncid,
                                  struct netlink_callback *cb)
 {
        void *hdr;
index b2cc2528a4df28db84160bfb002e4cb5838767c9..5ea26bd87743aea6591ff0d1005489b7de06f059 100644 (file)
@@ -104,7 +104,7 @@ struct ip_vs_lblc_entry {
  */
 struct ip_vs_lblc_table {
        struct rcu_head         rcu_head;
-       struct hlist_head __rcu bucket[IP_VS_LBLC_TAB_SIZE];  /* hash bucket */
+       struct hlist_head       bucket[IP_VS_LBLC_TAB_SIZE];  /* hash bucket */
        struct timer_list       periodic_timer; /* collect stale entries */
        atomic_t                entries;        /* number of entries */
        int                     max_size;       /* maximum size of entries */
index feb9656eac58675ea9a755f151bbf5b766c72bc5..50123c2ab4847e204b41ebca06a93bc04f228f69 100644 (file)
@@ -284,7 +284,7 @@ struct ip_vs_lblcr_entry {
  */
 struct ip_vs_lblcr_table {
        struct rcu_head         rcu_head;
-       struct hlist_head __rcu bucket[IP_VS_LBLCR_TAB_SIZE];  /* hash bucket */
+       struct hlist_head       bucket[IP_VS_LBLCR_TAB_SIZE];  /* hash bucket */
        atomic_t                entries;        /* number of entries */
        int                     max_size;       /* maximum size of entries */
        struct timer_list       periodic_timer; /* collect stale entries */
index 00cc0241ed87860b84722f20af7236428639b001..9a8f4213e8a69af3c05176c203f1bbde62434b2c 100644 (file)
@@ -13,7 +13,8 @@ static const char *ip_vs_dbg_callid(char *buf, size_t buf_len,
                                    const char *callid, size_t callid_len,
                                    int *idx)
 {
-       size_t len = min(min(callid_len, (size_t)64), buf_len - *idx - 1);
+       size_t max_len = 64;
+       size_t len = min3(max_len, callid_len, buf_len - *idx - 1);
        memcpy(buf + *idx, callid, len);
        buf[*idx+len] = '\0';
        *idx += len + 1;
index 6e14a7b5602f00d64b4b4e5b4d5e9853760832d4..86464881cd20b99d17c371a5bbccfe2efd9b6497 100644 (file)
@@ -208,7 +208,7 @@ enum ipvs_sctp_event_t {
        IP_VS_SCTP_EVE_LAST
 };
 
-static enum ipvs_sctp_event_t sctp_events[255] = {
+static enum ipvs_sctp_event_t sctp_events[256] = {
        IP_VS_SCTP_EVE_DATA_CLI,
        IP_VS_SCTP_EVE_INIT_CLI,
        IP_VS_SCTP_EVE_INIT_ACK_CLI,
index 8e57077e55401907271fbb7349f5d88d153b57bc..f6046d9af8d3262024b1a5c57c4840d976b14e01 100644 (file)
@@ -246,7 +246,7 @@ struct ip_vs_sync_thread_data {
 struct ip_vs_sync_mesg_v0 {
        __u8                    nr_conns;
        __u8                    syncid;
-       __u16                   size;
+       __be16                  size;
 
        /* ip_vs_sync_conn entries start here */
 };
@@ -255,7 +255,7 @@ struct ip_vs_sync_mesg_v0 {
 struct ip_vs_sync_mesg {
        __u8                    reserved;       /* must be zero */
        __u8                    syncid;
-       __u16                   size;
+       __be16                  size;
        __u8                    nr_conns;
        __s8                    version;        /* SYNC_PROTO_VER  */
        __u16                   spare;
@@ -335,7 +335,7 @@ ip_vs_sync_buff_create(struct netns_ipvs *ipvs)
        sb->mesg->reserved = 0;  /* old nr_conns i.e. must be zero now */
        sb->mesg->version = SYNC_PROTO_VER;
        sb->mesg->syncid = ipvs->master_syncid;
-       sb->mesg->size = sizeof(struct ip_vs_sync_mesg);
+       sb->mesg->size = htons(sizeof(struct ip_vs_sync_mesg));
        sb->mesg->nr_conns = 0;
        sb->mesg->spare = 0;
        sb->head = (unsigned char *)sb->mesg + sizeof(struct ip_vs_sync_mesg);
@@ -418,7 +418,7 @@ ip_vs_sync_buff_create_v0(struct netns_ipvs *ipvs)
        mesg = (struct ip_vs_sync_mesg_v0 *)sb->mesg;
        mesg->nr_conns = 0;
        mesg->syncid = ipvs->master_syncid;
-       mesg->size = sizeof(struct ip_vs_sync_mesg_v0);
+       mesg->size = htons(sizeof(struct ip_vs_sync_mesg_v0));
        sb->head = (unsigned char *)mesg + sizeof(struct ip_vs_sync_mesg_v0);
        sb->end = (unsigned char *)mesg + ipvs->send_mesg_maxlen;
        sb->firstuse = jiffies;
@@ -582,7 +582,7 @@ static void ip_vs_sync_conn_v0(struct net *net, struct ip_vs_conn *cp,
        }
 
        m->nr_conns++;
-       m->size += len;
+       m->size = htons(ntohs(m->size) + len);
        buff->head += len;
 
        /* check if there is a space for next one */
@@ -693,7 +693,7 @@ sloop:
 
        p = buff->head;
        buff->head += pad + len;
-       m->size += pad + len;
+       m->size = htons(ntohs(m->size) + pad + len);
        /* Add ev. padding from prev. sync_conn */
        while (pad--)
                *(p++) = 0;
@@ -1175,10 +1175,8 @@ static void ip_vs_process_message(struct net *net, __u8 *buffer,
                IP_VS_DBG(2, "BACKUP, message header too short\n");
                return;
        }
-       /* Convert size back to host byte order */
-       m2->size = ntohs(m2->size);
 
-       if (buflen != m2->size) {
+       if (buflen != ntohs(m2->size)) {
                IP_VS_DBG(2, "BACKUP, bogus message size\n");
                return;
        }
@@ -1544,10 +1542,7 @@ ip_vs_send_sync_msg(struct socket *sock, struct ip_vs_sync_mesg *msg)
        int msize;
        int ret;
 
-       msize = msg->size;
-
-       /* Put size in network byte order */
-       msg->size = htons(msg->size);
+       msize = ntohs(msg->size);
 
        ret = ip_vs_send_async(sock, (char *)msg, msize);
        if (ret >= 0 || ret == -EAGAIN)
index 2e469ca2ca553acd9076c0ee3b9c35fc3b561262..038eee5c8f8548787bff468c40256d52bb6655fd 100644 (file)
@@ -90,6 +90,7 @@ int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family)
        int err;
 
        err = xfrm_decode_session(skb, &fl, family);
+       if (err < 0)
                return err;
 
        dst = skb_dst(skb);