The branch main has been updated by glebius:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=3d2041c0353d3cc44bd2a6e37bf1c6e341d2b4db

commit 3d2041c0353d3cc44bd2a6e37bf1c6e341d2b4db
Author:     Gleb Smirnoff <gleb...@freebsd.org>
AuthorDate: 2022-08-11 16:19:37 +0000
Commit:     Gleb Smirnoff <gleb...@freebsd.org>
CommitDate: 2022-08-11 16:19:37 +0000

    raw ip: merge rip_output() into rip_send()
    
    While here, address the unlocked 'dst' read.  Solve that by storing
    a pointer either to the inpcb or to the sockaddr.  If we end up
    copying address out of the inpcb, that would be done under the read
    lock section.
    
    Reviewed by:            melifaro
    Differential revision:  https://reviews.freebsd.org/D36127
---
 sys/netinet/ip_var.h |  1 -
 sys/netinet/raw_ip.c | 97 ++++++++++++++++++++++------------------------------
 2 files changed, 40 insertions(+), 58 deletions(-)

diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index 4eaaef5c6991..92447c519cc3 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -236,7 +236,6 @@ void        ip_fillid(struct ip *);
 int    rip_ctloutput(struct socket *, struct sockopt *);
 void   rip_ctlinput(int, struct sockaddr *, void *);
 int    rip_input(struct mbuf **, int *, int);
-int    rip_output(struct mbuf *, struct socket *, ...);
 int    ipip_input(struct mbuf **, int *, int);
 int    rsvp_input(struct mbuf **, int *, int);
 int    ip_rsvp_init(struct socket *);
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index 0bd874c717e6..bda0138107ae 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -406,23 +406,50 @@ rip_input(struct mbuf **mp, int *offp, int proto)
  * Generate IP header and pass packet to ip_output.  Tack on options user may
  * have setup with control call.
  */
-int
-rip_output(struct mbuf *m, struct socket *so, ...)
+static int
+rip_send(struct socket *so, int pruflags, struct mbuf *m, struct sockaddr *nam,
+    struct mbuf *control, struct thread *td)
 {
        struct epoch_tracker et;
        struct ip *ip;
-       int error;
-       struct inpcb *inp = sotoinpcb(so);
-       va_list ap;
-       u_long dst;
-       int flags = ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0) |
-           IP_ALLOWBROADCAST;
-       int cnt, hlen;
+       struct inpcb *inp;
+       in_addr_t *dst;
+       int error, flags, cnt, hlen;
        u_char opttype, optlen, *cp;
 
-       va_start(ap, so);
-       dst = va_arg(ap, u_long);
-       va_end(ap);
+       inp = sotoinpcb(so);
+       KASSERT(inp != NULL, ("rip_send: inp == NULL"));
+
+       if (control != NULL) {
+               m_freem(control);
+               control = NULL;
+       }
+
+       if (so->so_state & SS_ISCONNECTED) {
+               if (nam) {
+                       error = EISCONN;
+                       m_freem(m);
+                       return (error);
+               }
+               dst = &inp->inp_faddr.s_addr;
+       } else {
+               if (nam == NULL)
+                       error = ENOTCONN;
+               else if (nam->sa_family != AF_INET)
+                       error = EAFNOSUPPORT;
+               else if (nam->sa_len != sizeof(struct sockaddr_in))
+                       error = EINVAL;
+               else
+                       error = 0;
+               if (error != 0) {
+                       m_freem(m);
+                       return (error);
+               }
+               dst = &((struct sockaddr_in *)nam)->sin_addr.s_addr;
+       }
+
+       flags = ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0) |
+           IP_ALLOWBROADCAST;
 
        /*
         * If the user handed us a complete IP packet, use it.  Otherwise,
@@ -447,7 +474,7 @@ rip_output(struct mbuf *m, struct socket *so, ...)
                ip->ip_p = inp->inp_ip_p;
                ip->ip_len = htons(m->m_pkthdr.len);
                ip->ip_src = inp->inp_laddr;
-               ip->ip_dst.s_addr = dst;
+               ip->ip_dst.s_addr = *dst;
 #ifdef ROUTE_MPATH
                if (CALC_FLOWID_OUTBOUND) {
                        uint32_t hash_type, hash_val;
@@ -971,50 +998,6 @@ rip_shutdown(struct socket *so)
        INP_WUNLOCK(inp);
        return (0);
 }
-
-static int
-rip_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
-    struct mbuf *control, struct thread *td)
-{
-       struct inpcb *inp;
-       u_long dst;
-       int error;
-
-       inp = sotoinpcb(so);
-       KASSERT(inp != NULL, ("rip_send: inp == NULL"));
-
-       if (control != NULL) {
-               m_freem(control);
-               control = NULL;
-       }
-
-       /*
-        * Note: 'dst' reads below are unlocked.
-        */
-       if (so->so_state & SS_ISCONNECTED) {
-               if (nam) {
-                       error = EISCONN;
-                       goto release;
-               }
-               dst = inp->inp_faddr.s_addr;    /* Unlocked read. */
-       } else {
-               error = 0;
-               if (nam == NULL)
-                       error = ENOTCONN;
-               else if (nam->sa_family != AF_INET)
-                       error = EAFNOSUPPORT;
-               else if (nam->sa_len != sizeof(struct sockaddr_in))
-                       error = EINVAL;
-               if (error != 0)
-                       goto release;
-               dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr;
-       }
-       return (rip_output(m, so, dst));
-
-release:
-       m_freem(m);
-       return (error);
-}
 #endif /* INET */
 
 static int

Reply via email to