From 475ed81624b663728fa836e0d942639e6fa532f4 Mon Sep 17 00:00:00 2001 From: ozaki-r Date: Mon, 25 Sep 2017 01:56:22 +0000 Subject: [PATCH] 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. --- sys/net/raw_cb.c | 10 ++++------ sys/net/raw_cb.h | 6 ++---- sys/net/raw_usrreq.c | 14 +++++--------- sys/net/rtsock.c | 19 +++++++++++++------ sys/netipsec/keysock.c | 18 +++++++++++++----- 5 files changed, 37 insertions(+), 30 deletions(-) diff --git a/sys/net/raw_cb.c b/sys/net/raw_cb.c index 82d0087bb68e..f9543d4e1229 100644 --- a/sys/net/raw_cb.c +++ b/sys/net/raw_cb.c @@ -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 -__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 #include @@ -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; diff --git a/sys/net/raw_cb.h b/sys/net/raw_cb.h index 42a559adb625..ed2af8b88022 100644 --- a/sys/net/raw_cb.h +++ b/sys/net/raw_cb.h @@ -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 *); diff --git a/sys/net/raw_usrreq.c b/sys/net/raw_usrreq.c index 00deadc6c8da..d832058c8289 100644 --- a/sys/net/raw_usrreq.c +++ b/sys/net/raw_usrreq.c @@ -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 -__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 #include @@ -54,12 +54,6 @@ __KERNEL_RCSID(0, "$NetBSD: raw_usrreq.c,v 1.56 2017/04/11 13:55:54 roy Exp $"); #include #include -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 && diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index be73ae2ba93c..63e171066525 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -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 -__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, }, }; diff --git a/sys/netipsec/keysock.c b/sys/netipsec/keysock.c index ed13b83b70bd..05700781a1b7 100644 --- a/sys/netipsec/keysock.c +++ b/sys/netipsec/keysock.c @@ -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 -__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, } };