summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2007-02-06 14:31:37 +0000
committerrwatson <rwatson@FreeBSD.org>2007-02-06 14:31:37 +0000
commita7eaaf4149d85508b0c5cfb739ffae169cdb3a5b (patch)
tree4e70b98d5f9ee6f150f53e68d8c2e4394de1b60c
parent19777f08023deb4d6171525896812b717dd9c968 (diff)
downloadFreeBSD-src-a7eaaf4149d85508b0c5cfb739ffae169cdb3a5b.zip
FreeBSD-src-a7eaaf4149d85508b0c5cfb739ffae169cdb3a5b.tar.gz
Push UNIX domain socket locking further into uipc_ctloutput() in order to
avoid holding the UNIX domain socket subsystem lock over soooptcopyin() and sooptcopyout(). This problem was introduced when LOCAL_CREDS, and LOCAL_CONNWAIT support were added. Reviewed by: mdodd
-rw-r--r--sys/kern/uipc_usrreq.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index ded4214..eabe2ff 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -854,12 +854,12 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
unp = sotounpcb(so);
KASSERT(unp != NULL, ("uipc_ctloutput: unp == NULL"));
- UNP_LOCK();
error = 0;
switch (sopt->sopt_dir) {
case SOPT_GET:
switch (sopt->sopt_name) {
case LOCAL_PEERCRED:
+ UNP_LOCK();
if (unp->unp_flags & UNP_HAVEPC)
xu = unp->unp_peercred;
else {
@@ -868,14 +868,17 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
else
error = EINVAL;
}
+ UNP_UNLOCK();
if (error == 0)
error = sooptcopyout(sopt, &xu, sizeof(xu));
break;
case LOCAL_CREDS:
+ /* Unocked read. */
optval = unp->unp_flags & UNP_WANTCRED ? 1 : 0;
error = sooptcopyout(sopt, &optval, sizeof(optval));
break;
case LOCAL_CONNWAIT:
+ /* Unocked read. */
optval = unp->unp_flags & UNP_CONNWAIT ? 1 : 0;
error = sooptcopyout(sopt, &optval, sizeof(optval));
break;
@@ -899,6 +902,7 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
else \
unp->unp_flags &= ~bit;
+ UNP_LOCK();
switch (sopt->sopt_name) {
case LOCAL_CREDS:
OPTSET(UNP_WANTCRED);
@@ -909,6 +913,7 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
default:
break;
}
+ UNP_UNLOCK();
break;
#undef OPTSET
default:
@@ -920,7 +925,6 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
error = EOPNOTSUPP;
break;
}
- UNP_UNLOCK();
return (error);
}
OpenPOWER on IntegriCloud