Hi,
The call to in_pcballoc() in user request attach is handled in three
different ways. Use the same code in udp_usrreq() and rip_usrreq()
and rip6_usrreq(). Also put an splsoftassert() into in_pcballoc()
for safety.
If I understand the code correctly, this also fixes a pcb and socket
leak in udp_usrreq() in case soreserve() fails.
ok?
bluhm
Index: netinet/in_pcb.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.131
diff -u -p -r1.131 in_pcb.c
--- netinet/in_pcb.c 5 Feb 2013 19:09:52 -0000 1.131
+++ netinet/in_pcb.c 27 Mar 2013 16:35:19 -0000
@@ -177,6 +177,8 @@ in_pcballoc(struct socket *so, struct in
struct inpcb *inp;
int s;
+ splsoftassert(IPL_SOFTNET);
+
if (inpcb_pool_initialized == 0) {
pool_init(&inpcb_pool, sizeof(struct inpcb), 0, 0, 0,
"inpcbpl", NULL);
Index: netinet/raw_ip.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/raw_ip.c,v
retrieving revision 1.62
diff -u -p -r1.62 raw_ip.c
--- netinet/raw_ip.c 21 Oct 2012 13:06:03 -0000 1.62
+++ netinet/raw_ip.c 27 Mar 2013 17:37:29 -0000
@@ -396,8 +396,9 @@ int
rip_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
struct mbuf *control, struct proc *p)
{
- int error = 0;
struct inpcb *inp = sotoinpcb(so);
+ int error = 0;
+ int s;
#ifdef MROUTING
extern struct socket *ip_mrouter;
#endif
@@ -419,9 +420,13 @@ rip_usrreq(struct socket *so, int req, s
error = EACCES;
break;
}
+ s = splsoftnet();
if ((error = soreserve(so, rip_sendspace, rip_recvspace)) ||
- (error = in_pcballoc(so, &rawcbtable)))
+ (error = in_pcballoc(so, &rawcbtable))) {
+ splx(s);
break;
+ }
+ splx(s);
inp = (struct inpcb *)so->so_pcb;
inp->inp_ip.ip_p = (long)nam;
break;
Index: netinet/udp_usrreq.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.154
diff -u -p -r1.154 udp_usrreq.c
--- netinet/udp_usrreq.c 14 Mar 2013 11:18:37 -0000 1.154
+++ netinet/udp_usrreq.c 27 Mar 2013 18:17:47 -0000
@@ -1151,13 +1151,12 @@ udp_usrreq(struct socket *so, int req, s
break;
}
s = splsoftnet();
- error = in_pcballoc(so, &udbtable);
- splx(s);
- if (error)
- break;
- error = soreserve(so, udp_sendspace, udp_recvspace);
- if (error)
+ if ((error = soreserve(so, udp_sendspace, udp_recvspace)) ||
+ (error = in_pcballoc(so, &udbtable))) {
+ splx(s);
break;
+ }
+ splx(s);
#ifdef INET6
if (((struct inpcb *)so->so_pcb)->inp_flags & INP_IPV6)
((struct inpcb *) so->so_pcb)->inp_ipv6.ip6_hlim =
Index: netinet6/raw_ip6.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/raw_ip6.c,v
retrieving revision 1.47
diff -u -p -r1.47 raw_ip6.c
--- netinet6/raw_ip6.c 14 Mar 2013 11:18:37 -0000 1.47
+++ netinet6/raw_ip6.c 27 Mar 2013 17:37:43 -0000
@@ -595,8 +595,8 @@ rip6_usrreq(struct socket *so, int req,
struct mbuf *control, struct proc *p)
{
struct in6pcb *in6p = sotoin6pcb(so);
- int s;
int error = 0;
+ int s;
int priv;
priv = 0;
@@ -616,12 +616,8 @@ rip6_usrreq(struct socket *so, int req,
break;
}
s = splsoftnet();
- if ((error = soreserve(so, rip6_sendspace, rip6_recvspace)) !=
0) {
- splx(s);
- break;
- }
- if ((error = in_pcballoc(so, &rawin6pcbtable)) != 0)
- {
+ if ((error = soreserve(so, rip6_sendspace, rip6_recvspace)) ||
+ (error = in_pcballoc(so, &rawin6pcbtable))) {
splx(s);
break;
}