Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Don't use a single global variable to store source route...



details:   https://anonhg.NetBSD.org/src/rev/da9940317176
branches:  trunk
changeset: 822674:da9940317176
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Fri Mar 31 06:49:44 2017 +0000

description:
Don't use a single global variable to store source route information for multiple incoming packets

It's not MP-safe. So use a m_tag to store the information instead.

Pointed out by knakahara@
The fix is from OpenBSD (originally fixed in FreeBSD)

diffstat:

 sys/netinet/ip_icmp.c   |   6 +-
 sys/netinet/ip_input.c  |  82 ++++++++++++++++++++++++++++--------------------
 sys/netinet/ip_var.h    |   4 +-
 sys/netinet/tcp_input.c |   8 ++--
 sys/sys/mbuf.h          |   3 +-
 5 files changed, 59 insertions(+), 44 deletions(-)

diffs (273 lines):

diff -r fb68e684d926 -r da9940317176 sys/netinet/ip_icmp.c
--- a/sys/netinet/ip_icmp.c     Fri Mar 31 06:42:19 2017 +0000
+++ b/sys/netinet/ip_icmp.c     Fri Mar 31 06:49:44 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_icmp.c,v 1.160 2017/03/06 07:31:15 ozaki-r Exp $    */
+/*     $NetBSD: ip_icmp.c,v 1.161 2017/03/31 06:49:44 ozaki-r Exp $    */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -94,7 +94,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_icmp.c,v 1.160 2017/03/06 07:31:15 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_icmp.c,v 1.161 2017/03/31 06:49:44 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ipsec.h"
@@ -888,7 +888,7 @@
                 * add on any record-route or timestamp options.
                 */
                cp = (u_char *) (ip + 1);
-               if ((opts = ip_srcroute()) == NULL &&
+               if ((opts = ip_srcroute(m)) == NULL &&
                    (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) {
                        MCLAIM(opts, m->m_owner);
                        opts->m_len = sizeof(struct in_addr);
diff -r fb68e684d926 -r da9940317176 sys/netinet/ip_input.c
--- a/sys/netinet/ip_input.c    Fri Mar 31 06:42:19 2017 +0000
+++ b/sys/netinet/ip_input.c    Fri Mar 31 06:49:44 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_input.c,v 1.353 2017/03/31 06:42:19 ozaki-r Exp $   */
+/*     $NetBSD: ip_input.c,v 1.354 2017/03/31 06:49:44 ozaki-r Exp $   */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.353 2017/03/31 06:42:19 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.354 2017/03/31 06:49:44 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -253,25 +253,23 @@
 #endif /* INET_CSUM_COUNTERS */
 
 /*
- * We need to save the IP options in case a protocol wants to respond
+ * Used to save the IP options in case a protocol wants to respond
  * to an incoming packet over the same route if the packet got here
  * using IP source routing.  This allows connection establishment and
  * maintenance when the remote end is on a network that is not known
  * to us.
  */
-
-static int     ip_nhops = 0;
-
-static struct ip_srcrt {
-       struct  in_addr dst;                    /* final destination */
-       char    nop;                            /* one NOP to align */
-       char    srcopt[IPOPT_OFFSET + 1];       /* OPTVAL, OLEN and OFFSET */
-       struct  in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)];
-} ip_srcrt;
+struct ip_srcrt {
+       int             isr_nhops;                 /* number of hops */
+       struct in_addr  isr_dst;                   /* final destination */
+       char            isr_nop;                   /* one NOP to align */
+       char            isr_hdr[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN & OFFSET */
+       struct in_addr  isr_routes[MAX_IPOPTLEN/sizeof(struct in_addr)];
+};
 
 static int ip_drainwanted;
 
-static void save_rte(u_char *, struct in_addr);
+static void save_rte(struct mbuf *, u_char *, struct in_addr);
 
 #ifdef MBUFTRACE
 struct mowner ip_rx_mowner = MOWNER_INIT("internet", "rx");
@@ -664,7 +662,6 @@
         * error was detected (causing an icmp message
         * to be sent and the original packet to be freed).
         */
-       ip_nhops = 0;           /* for source routed packets */
        if (hlen > sizeof (struct ip) && ip_dooptions(m)) {
                m = NULL;
                goto out;
@@ -987,7 +984,7 @@
                                /*
                                 * End of source route.  Should be for us.
                                 */
-                               save_rte(cp, ip->ip_src);
+                               save_rte(m, cp, ip->ip_src);
                                break;
                        }
                        /*
@@ -1226,16 +1223,25 @@
  * up later by ip_srcroute if the receiver is interested.
  */
 static void
-save_rte(u_char *option, struct in_addr dst)
+save_rte(struct mbuf *m, u_char *option, struct in_addr dst)
 {
+       struct ip_srcrt *isr;
+       struct m_tag *mtag;
        unsigned olen;
 
        olen = option[IPOPT_OLEN];
-       if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))
+       if (olen > sizeof(isr->isr_hdr) + sizeof(isr->isr_routes))
+               return;
+
+       mtag = m_tag_get(PACKET_TAG_SRCROUTE, sizeof(*isr), M_NOWAIT);
+       if (mtag == NULL)
                return;
-       memcpy((void *)ip_srcrt.srcopt, (void *)option, olen);
-       ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
-       ip_srcrt.dst = dst;
+       isr = (struct ip_srcrt *)(mtag + 1);
+
+       memcpy(isr->isr_hdr, option, olen);
+       isr->isr_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
+       isr->isr_dst = dst;
+       m_tag_prepend(m, mtag);
 }
 
 /*
@@ -1244,36 +1250,43 @@
  * The first hop is placed before the options, will be removed later.
  */
 struct mbuf *
-ip_srcroute(void)
+ip_srcroute(struct mbuf *m0)
 {
        struct in_addr *p, *q;
        struct mbuf *m;
+       struct ip_srcrt *isr;
+       struct m_tag *mtag;
 
-       if (ip_nhops == 0)
+       mtag = m_tag_find(m0, PACKET_TAG_SRCROUTE, NULL);
+       if (mtag == NULL)
                return NULL;
+       isr = (struct ip_srcrt *)(mtag + 1);
+
+       if (isr->isr_nhops == 0)
+               return NULL;
+
        m = m_get(M_DONTWAIT, MT_SOOPTS);
-       if (m == 0)
+       if (m == NULL)
                return NULL;
 
        MCLAIM(m, &inetdomain.dom_mowner);
-#define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt))
+#define OPTSIZ (sizeof(isr->isr_nop) + sizeof(isr->isr_hdr))
 
-       /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */
-       m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) +
-           OPTSIZ;
+       /* length is (nhops+1)*sizeof(addr) + sizeof(nop + header) */
+       m->m_len = (isr->isr_nhops + 1) * sizeof(struct in_addr) + OPTSIZ;
 
        /*
         * First save first hop for return route
         */
-       p = &ip_srcrt.route[ip_nhops - 1];
+       p = &(isr->isr_routes[isr->isr_nhops - 1]);
        *(mtod(m, struct in_addr *)) = *p--;
 
        /*
         * Copy option fields and padding (nop) to mbuf.
         */
-       ip_srcrt.nop = IPOPT_NOP;
-       ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF;
-       memmove(mtod(m, char *) + sizeof(struct in_addr), &ip_srcrt.nop,
+       isr->isr_nop = IPOPT_NOP;
+       isr->isr_hdr[IPOPT_OFFSET] = IPOPT_MINOFF;
+       memmove(mtod(m, char *) + sizeof(struct in_addr), &isr->isr_nop,
            OPTSIZ);
        q = (struct in_addr *)(mtod(m, char *) +
            sizeof(struct in_addr) + OPTSIZ);
@@ -1282,14 +1295,15 @@
         * Record return path as an IP source route,
         * reversing the path (pointers are now aligned).
         */
-       while (p >= ip_srcrt.route) {
+       while (p >= isr->isr_routes) {
                *q++ = *p--;
        }
        /*
         * Last hop goes to final destination.
         */
-       *q = ip_srcrt.dst;
-       return (m);
+       *q = isr->isr_dst;
+       m_tag_delete(m0, mtag);
+       return m;
 }
 
 const int inetctlerrmap[PRC_NCMDS] = {
diff -r fb68e684d926 -r da9940317176 sys/netinet/ip_var.h
--- a/sys/netinet/ip_var.h      Fri Mar 31 06:42:19 2017 +0000
+++ b/sys/netinet/ip_var.h      Fri Mar 31 06:49:44 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_var.h,v 1.118 2017/03/03 07:13:06 ozaki-r Exp $     */
+/*     $NetBSD: ip_var.h,v 1.119 2017/03/31 06:49:44 ozaki-r Exp $     */
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -226,7 +226,7 @@
 void    ip_slowtimo(void);
 void    ip_fasttimo(void);
 struct mbuf *
-        ip_srcroute(void);
+        ip_srcroute(struct mbuf *);
 int     ip_sysctl(int *, u_int, void *, size_t *, void *, size_t);
 void    ip_statinc(u_int);
 void *  rip_ctlinput(int, const struct sockaddr *, void *);
diff -r fb68e684d926 -r da9940317176 sys/netinet/tcp_input.c
--- a/sys/netinet/tcp_input.c   Fri Mar 31 06:42:19 2017 +0000
+++ b/sys/netinet/tcp_input.c   Fri Mar 31 06:49:44 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_input.c,v 1.355 2017/03/03 07:13:06 ozaki-r Exp $  */
+/*     $NetBSD: tcp_input.c,v 1.356 2017/03/31 06:49:44 ozaki-r Exp $  */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -148,7 +148,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.355 2017/03/03 07:13:06 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.356 2017/03/31 06:49:44 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -4004,7 +4004,7 @@
                if (inp) {
                        inp->inp_laddr = ((struct sockaddr_in *)dst)->sin_addr;
                        inp->inp_lport = ((struct sockaddr_in *)dst)->sin_port;
-                       inp->inp_options = ip_srcroute();
+                       inp->inp_options = ip_srcroute(m);
                        in_pcbstate(inp, INP_BOUND);
                        if (inp->inp_options == NULL) {
                                inp->inp_options = sc->sc_ipopts;
@@ -4341,7 +4341,7 @@
                /*
                 * Remember the IP options, if any.
                 */
-               ipopts = ip_srcroute();
+               ipopts = ip_srcroute(m);
                break;
 #endif
        default:
diff -r fb68e684d926 -r da9940317176 sys/sys/mbuf.h
--- a/sys/sys/mbuf.h    Fri Mar 31 06:42:19 2017 +0000
+++ b/sys/sys/mbuf.h    Fri Mar 31 06:49:44 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mbuf.h,v 1.168 2017/02/07 02:36:48 ozaki-r Exp $       */
+/*     $NetBSD: mbuf.h,v 1.169 2017/03/31 06:49:44 ozaki-r Exp $       */
 
 /*-
  * Copyright (c) 1996, 1997, 1999, 2001, 2007 The NetBSD Foundation, Inc.
@@ -922,6 +922,7 @@
                                                    */
 
 #define        PACKET_TAG_MPLS                         29 /* Indicate it's for MPLS */
+#define        PACKET_TAG_SRCROUTE                     30 /* IPv4 source routing */
 
 /*
  * Return the number of bytes in the mbuf chain, m.



Home | Main Index | Thread Index | Old Index