[Midnightbsd-cvs] src: ip_output.c: Add a missing check for errors.

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sat May 17 14:00:37 EDT 2008


Log Message:
-----------
Add a missing check for errors.

Modified Files:
--------------
    src/sys/netinet:
        ip_output.c (r1.1.1.2 -> r1.2)

-------------- next part --------------
Index: ip_output.c
===================================================================
RCS file: /home/cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/netinet/ip_output.c -L sys/netinet/ip_output.c -u -r1.1.1.2 -r1.2
--- sys/netinet/ip_output.c
+++ sys/netinet/ip_output.c
@@ -1148,15 +1148,29 @@
 
 /*
  * IP socket option processing.
+ *
+ * There are two versions of this call in order to work around a race
+ * condition in TCP in FreeBSD 6.x.  In the TCP implementation, so->so_pcb
+ * can become NULL if the pcb or pcbinfo lock isn't held.  However, when
+ * entering ip_ctloutput(), neither lock is held, and finding the pointer to
+ * either lock requires follow so->so_pcb, which may be NULL.
+ * ip_ctloutput_pcbinfo() accepts the pcbinfo pointer so that the lock can be
+ * safely acquired.  This is not required in FreeBSD 7.x because the
+ * invariants on so->so_pcb are much stronger, so it cannot become NULL
+ * while the socket is in use.
  */
 int
-ip_ctloutput(so, sopt)
+ip_ctloutput_pcbinfo(so, sopt, pcbinfo)
 	struct socket *so;
 	struct sockopt *sopt;
+	struct inpcbinfo *pcbinfo;
 {
 	struct	inpcb *inp = sotoinpcb(so);
 	int	error, optval;
 
+	if (pcbinfo == NULL)
+		pcbinfo = inp->inp_pcbinfo;
+
 	error = optval = 0;
 	if (sopt->sopt_level != IPPROTO_IP) {
 		return (EINVAL);
@@ -1183,6 +1197,10 @@
 			m->m_len = sopt->sopt_valsize;
 			error = sooptcopyin(sopt, mtod(m, char *), m->m_len,
 					    m->m_len);
+			if (error) {
+				m_free(m);
+				break;
+			}
 			INP_LOCK(inp);
 			error = ip_pcbopts(inp, sopt->sopt_name, m);
 			INP_UNLOCK(inp);
@@ -1261,6 +1279,7 @@
 				OPTSET(INP_DONTFRAG);
 				break;
 			}
+			INP_UNLOCK(inp);
 			break;
 #undef OPTSET
 
@@ -1455,6 +1474,15 @@
 	return (error);
 }
 
+int
+ip_ctloutput(so, sopt)
+	struct socket *so;
+	struct sockopt *sopt;
+{
+
+	return (ip_ctloutput_pcbinfo(so, sopt, NULL));
+}
+
 /*
  * Set up IP options in pcb for insertion in output packets.
  * Store in mbuf with pointer in pcbopt, adding pseudo-option


More information about the Midnightbsd-cvs mailing list