Author: tuexen
Date: Sat Mar  2 14:15:33 2019
New Revision: 344723
URL: https://svnweb.freebsd.org/changeset/base/344723

Log:
  Handle the case when calling the IPPROTO_SCTP level socket option
  SCTP_STATUS on an association with no primary path (early state).
  
  This issue was found by running syzkaller.
  
  MFC after:            3 days

Modified:
  head/sys/netinet/sctp_usrreq.c

Modified: head/sys/netinet/sctp_usrreq.c
==============================================================================
--- head/sys/netinet/sctp_usrreq.c      Sat Mar  2 13:16:01 2019        
(r344722)
+++ head/sys/netinet/sctp_usrreq.c      Sat Mar  2 14:15:33 2019        
(r344723)
@@ -2644,42 +2644,47 @@ flags_out:
                        sstat->sstat_instrms = stcb->asoc.streamincnt;
                        sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
                        sstat->sstat_fragmentation_point = 
sctp_get_frag_point(stcb, &stcb->asoc);
-                       memcpy(&sstat->sstat_primary.spinfo_address,
-                           &stcb->asoc.primary_destination->ro._l_addr,
-                           ((struct sockaddr 
*)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
                        net = stcb->asoc.primary_destination;
-                       ((struct sockaddr_in 
*)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
-                       /*
-                        * Again the user can get info from sctp_constants.h
-                        * for what the state of the network is.
-                        */
-                       if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
-                               /* It's unconfirmed */
-                               sstat->sstat_primary.spinfo_state = 
SCTP_UNCONFIRMED;
-                       } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
-                               /* It's active */
-                               sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
-                       } else {
-                               /* It's inactive */
-                               sstat->sstat_primary.spinfo_state = 
SCTP_INACTIVE;
-                       }
-                       sstat->sstat_primary.spinfo_cwnd = net->cwnd;
-                       sstat->sstat_primary.spinfo_srtt = net->lastsa >> 
SCTP_RTT_SHIFT;
-                       sstat->sstat_primary.spinfo_rto = net->RTO;
-                       sstat->sstat_primary.spinfo_mtu = net->mtu;
-                       switch 
(stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) {
+                       if (net != NULL) {
+                               memcpy(&sstat->sstat_primary.spinfo_address,
+                                   &stcb->asoc.primary_destination->ro._l_addr,
+                                   ((struct sockaddr 
*)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
+                               ((struct sockaddr_in 
*)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
+                               /*
+                                * Again the user can get info from
+                                * sctp_constants.h for what the state of
+                                * the network is.
+                                */
+                               if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
+                                       /* It's unconfirmed */
+                                       sstat->sstat_primary.spinfo_state = 
SCTP_UNCONFIRMED;
+                               } else if (net->dest_state & 
SCTP_ADDR_REACHABLE) {
+                                       /* It's active */
+                                       sstat->sstat_primary.spinfo_state = 
SCTP_ACTIVE;
+                               } else {
+                                       /* It's inactive */
+                                       sstat->sstat_primary.spinfo_state = 
SCTP_INACTIVE;
+                               }
+                               sstat->sstat_primary.spinfo_cwnd = net->cwnd;
+                               sstat->sstat_primary.spinfo_srtt = net->lastsa 
>> SCTP_RTT_SHIFT;
+                               sstat->sstat_primary.spinfo_rto = net->RTO;
+                               sstat->sstat_primary.spinfo_mtu = net->mtu;
+                               switch 
(stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) {
 #if defined(INET)
-                       case AF_INET:
-                               sstat->sstat_primary.spinfo_mtu -= 
SCTP_MIN_V4_OVERHEAD;
-                               break;
+                               case AF_INET:
+                                       sstat->sstat_primary.spinfo_mtu -= 
SCTP_MIN_V4_OVERHEAD;
+                                       break;
 #endif
 #if defined(INET6)
-                       case AF_INET6:
-                               sstat->sstat_primary.spinfo_mtu -= 
SCTP_MIN_OVERHEAD;
-                               break;
+                               case AF_INET6:
+                                       sstat->sstat_primary.spinfo_mtu -= 
SCTP_MIN_OVERHEAD;
+                                       break;
 #endif
-                       default:
-                               break;
+                               default:
+                                       break;
+                               }
+                       } else {
+                               memset(&sstat->sstat_primary, 0, sizeof(struct 
sctp_paddrinfo));
                        }
                        sstat->sstat_primary.spinfo_assoc_id = 
sctp_get_associd(stcb);
                        SCTP_TCB_UNLOCK(stcb);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to