In /sys/net/if_ethersubr.c, in ether_output_frame, there is a return for an error case that fails to call splx to release the splimp taken above. (see the included patch) Fix: eh = mtod(m, struct ether_header *); save_eh = *eh; m_adj(m, ETHER_HDR_LEN); if (ether_ipfw_chk(&m, ifp, &rule, eh, 0) == 0) { if (m) { + splx(s); m_freem(m); return ENOBUFS; /* pkt dropped */ } else return 0; /* consumed e.g. in a pipe */ }--z7FiWVEWta3CTInMNGP2zmqHrcezNqMCmRp5MQegiPg8oxGn Content-Type: text/plain; name="file.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="file.diff" Index: if_ethersubr.c =================================================================== RCS file: /cvs/src/sys/net/if_ethersubr.c,v retrieving revision 1.70.2.30.1000.3 diff -U10 -r1.70.2.30.1000.3 if_ethersubr.c --- if_ethersubr.c 21 Jun 2003 20:47:55 -0000 1.70.2.30.1000.3 +++ if_ethersubr.c 14 Oct 2003 02:13:58 -0000 @@ -410,20 +410,21 @@ no_bridge: s = splimp(); if (IPFW_LOADED && ether_ipfw != 0) { struct ether_header save_eh, *eh;
Responsible Changed From-To: freebsd-bugs->freebsd-net Over to freebsd-net for review.
Responsible Changed From-To: freebsd-net->rwatson Grab ownership of this PR.
On Mon, 3 Jan 2005, Robert Watson wrote: > Synopsis: [patch] Missing splx in ether_output_frame (-stable) Sorry about the long time it's taken for someone to pick up this PR! Your description of the problem sounds convincing, but the patch omits to call splx(s) in a couple of additional cases. Could you try the attached patch? Thanks! cvs diff: Diffing . Index: if_ethersubr.c =================================================================== RCS file: /home/ncvs/src/sys/net/if_ethersubr.c,v retrieving revision 1.70.2.36 diff -u -r1.70.2.36 if_ethersubr.c --- if_ethersubr.c 3 Mar 2004 12:35:16 -0000 1.70.2.36 +++ if_ethersubr.c 3 Jan 2005 12:28:18 -0000 @@ -414,6 +414,7 @@ save_eh = *eh; m_adj(m, ETHER_HDR_LEN); if (ether_ipfw_chk(&m, ifp, &rule, eh, 0) == 0) { + splx(s); if (m) { m_freem(m); return EACCES; /* pkt dropped */ @@ -427,8 +428,10 @@ m->m_pkthdr.len += ETHER_HDR_LEN ; } else { M_PREPEND(m, ETHER_HDR_LEN, M_DONTWAIT); - if (m == NULL) /* nope... */ + if (m == NULL) { /* nope... */ + splx(s); return ENOBUFS; + } bcopy(&save_eh, mtod(m, struct ether_header *), ETHER_HDR_LEN); }
State Changed From-To: open->closed Committed as if_ethersubr.c:1.70.2.37; no feedback from submitter but believed to fix the reported problem.