Fix race condition on the rawcb list shared by rtsock and keysock

keysock now protects itself by its own mutex, which means that
the rawcb list is protected by two different mutexes (keysock's one
and softnet_lock for rtsock), of course it's useless.

Fix the situation by having a discrete rawcb list for each.
This commit is contained in:
ozaki-r 2017-09-25 01:56:22 +00:00
parent 1a3d098173
commit 475ed81624
5 changed files with 37 additions and 30 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: raw_cb.c,v 1.23 2017/07/27 09:53:57 ozaki-r Exp $ */
/* $NetBSD: raw_cb.c,v 1.24 2017/09/25 01:56:22 ozaki-r Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: raw_cb.c,v 1.23 2017/07/27 09:53:57 ozaki-r Exp $");
__KERNEL_RCSID(0, "$NetBSD: raw_cb.c,v 1.24 2017/09/25 01:56:22 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -57,8 +57,6 @@ __KERNEL_RCSID(0, "$NetBSD: raw_cb.c,v 1.23 2017/07/27 09:53:57 ozaki-r Exp $");
* redo address binding to allow wildcards
*/
struct rawcbhead rawcb = LIST_HEAD_INITIALIZER(rawcb);
static u_long raw_sendspace = RAWSNDQ;
static u_long raw_recvspace = RAWRCVQ;
@ -66,7 +64,7 @@ static u_long raw_recvspace = RAWRCVQ;
* Allocate a nominal amount of buffer space for the socket.
*/
int
raw_attach(struct socket *so, int proto)
raw_attach(struct socket *so, int proto, struct rawcbhead *rawcbhead)
{
struct rawcb *rp;
int error;
@ -87,7 +85,7 @@ raw_attach(struct socket *so, int proto)
rp->rcb_socket = so;
rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family;
rp->rcb_proto.sp_protocol = proto;
LIST_INSERT_HEAD(&rawcb, rp, rcb_list);
LIST_INSERT_HEAD(rawcbhead, rp, rcb_list);
KASSERT(solocked(so));
return 0;

View File

@ -1,4 +1,4 @@
/* $NetBSD: raw_cb.h,v 1.27 2017/04/11 13:55:54 roy Exp $ */
/* $NetBSD: raw_cb.h,v 1.28 2017/09/25 01:56:22 ozaki-r Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
@ -60,13 +60,11 @@ struct rawcb {
#define RAWRCVQ 8192
LIST_HEAD(rawcbhead, rawcb);
extern struct rawcbhead rawcb; /* head of list */
int raw_attach(struct socket *, int);
int raw_attach(struct socket *, int, struct rawcbhead *);
void *raw_ctlinput(int, const struct sockaddr *, void *);
void raw_detach(struct socket *);
void raw_disconnect(struct rawcb *);
void raw_init(void);
void raw_input(struct mbuf *, ...);
int raw_usrreq(struct socket *,
int, struct mbuf *, struct mbuf *, struct mbuf *, struct lwp *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: raw_usrreq.c,v 1.56 2017/04/11 13:55:54 roy Exp $ */
/* $NetBSD: raw_usrreq.c,v 1.57 2017/09/25 01:56:22 ozaki-r Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: raw_usrreq.c,v 1.56 2017/04/11 13:55:54 roy Exp $");
__KERNEL_RCSID(0, "$NetBSD: raw_usrreq.c,v 1.57 2017/09/25 01:56:22 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/mbuf.h>
@ -54,12 +54,6 @@ __KERNEL_RCSID(0, "$NetBSD: raw_usrreq.c,v 1.56 2017/04/11 13:55:54 roy Exp $");
#include <net/netisr.h>
#include <net/raw_cb.h>
void
raw_init(void)
{
LIST_INIT(&rawcb);
}
static inline int
equal(const struct sockaddr *a1, const struct sockaddr *a2)
{
@ -79,6 +73,7 @@ raw_input(struct mbuf *m0, ...)
va_list ap;
struct sockproto *proto;
struct sockaddr *src, *dst;
struct rawcbhead *rawcbhead;
KASSERT(mutex_owned(softnet_lock));
@ -86,10 +81,11 @@ raw_input(struct mbuf *m0, ...)
proto = va_arg(ap, struct sockproto *);
src = va_arg(ap, struct sockaddr *);
dst = va_arg(ap, struct sockaddr *);
rawcbhead = va_arg(ap, struct rawcbhead *);
va_end(ap);
last = NULL;
LIST_FOREACH(rp, &rawcb, rcb_list) {
LIST_FOREACH(rp, rawcbhead, rcb_list) {
if (rp->rcb_proto.sp_family != proto->sp_family)
continue;
if (rp->rcb_proto.sp_protocol &&

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtsock.c,v 1.227 2017/07/01 16:59:12 christos Exp $ */
/* $NetBSD: rtsock.c,v 1.228 2017/09/25 01:56:22 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.227 2017/07/01 16:59:12 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.228 2017/09/25 01:56:22 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@ -239,6 +239,13 @@ COMPATNAME(route_filter)(struct mbuf *m, struct sockproto *proto,
return 0;
}
static void
rt_pr_init(void)
{
LIST_INIT(&rt_rawcb);
}
static int
COMPATNAME(route_attach)(struct socket *so, int proto)
{
@ -253,7 +260,7 @@ COMPATNAME(route_attach)(struct socket *so, int proto)
so->so_pcb = rp;
s = splsoftnet();
if ((error = raw_attach(so, proto)) == 0) {
if ((error = raw_attach(so, proto, &rt_rawcb)) == 0) {
rt_adjustcount(rp->rcb_proto.sp_protocol, 1);
rp->rcb_laddr = &COMPATNAME(route_info).ri_src;
rp->rcb_faddr = &COMPATNAME(route_info).ri_dst;
@ -1045,7 +1052,7 @@ flush:
proto.sp_protocol = family;
if (m)
raw_input(m, &proto, &COMPATNAME(route_info).ri_src,
&COMPATNAME(route_info).ri_dst);
&COMPATNAME(route_info).ri_dst, &rt_rawcb);
if (rp)
rp->rcb_proto.sp_family = PF_XROUTE;
}
@ -2027,7 +2034,7 @@ COMPATNAME(route_intr)(void *cookie)
if (m == NULL)
break;
proto.sp_protocol = M_GETCTX(m, uintptr_t);
raw_input(m, &proto, &ri->ri_src, &ri->ri_dst);
raw_input(m, &proto, &ri->ri_src, &ri->ri_dst, &rt_rawcb);
}
KERNEL_UNLOCK_ONE(NULL);
mutex_exit(softnet_lock);
@ -2116,7 +2123,7 @@ static const struct protosw COMPATNAME(route_protosw)[] = {
.pr_ctlinput = raw_ctlinput,
.pr_ctloutput = route_ctloutput,
.pr_usrreqs = &route_usrreqs,
.pr_init = raw_init,
.pr_init = rt_pr_init,
},
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: keysock.c,v 1.60 2017/08/08 10:41:33 ozaki-r Exp $ */
/* $NetBSD: keysock.c,v 1.61 2017/09/25 01:56:22 ozaki-r Exp $ */
/* $FreeBSD: src/sys/netipsec/keysock.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $ */
/* $KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $ */
@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: keysock.c,v 1.60 2017/08/08 10:41:33 ozaki-r Exp $");
__KERNEL_RCSID(0, "$NetBSD: keysock.c,v 1.61 2017/09/25 01:56:22 ozaki-r Exp $");
/* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
@ -84,6 +84,7 @@ static int key_sendup0(struct rawcb *, struct mbuf *, int, int);
int key_registered_sb_max = (2048 * MHLEN); /* XXX arbitrary */
static kmutex_t *key_so_mtx;
static struct rawcbhead key_rawcb;
void
key_init_so(void)
@ -92,6 +93,13 @@ key_init_so(void)
key_so_mtx = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
}
static void
key_pr_init(void)
{
LIST_INIT(&key_rawcb);
}
/*
* key_output()
*/
@ -352,7 +360,7 @@ _key_sendup_mbuf(struct socket *so, struct mbuf *m,
PFKEY_STATINC(PFKEY_STAT_IN_MSGTYPE + msg->sadb_msg_type);
}
LIST_FOREACH(rp, &rawcb, rcb_list)
LIST_FOREACH(rp, &key_rawcb, rcb_list)
{
struct socket * kso = rp->rcb_socket;
if (rp->rcb_proto.sp_family != PF_KEY)
@ -469,7 +477,7 @@ key_attach(struct socket *so, int proto)
so->so_lock = key_so_mtx;
solock(so);
error = raw_attach(so, proto);
error = raw_attach(so, proto, &key_rawcb);
if (error) {
PFKEY_STATINC(PFKEY_STAT_SOCKERR);
kmem_free(kp, sizeof(*kp));
@ -753,7 +761,7 @@ static const struct protosw keysw[] = {
.pr_flags = PR_ATOMIC|PR_ADDR,
.pr_ctlinput = raw_ctlinput,
.pr_usrreqs = &key_usrreqs,
.pr_init = raw_init,
.pr_init = key_pr_init,
}
};