diff options
author | rwatson <rwatson@FreeBSD.org> | 2007-02-06 14:31:37 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2007-02-06 14:31:37 +0000 |
commit | a7eaaf4149d85508b0c5cfb739ffae169cdb3a5b (patch) | |
tree | 4e70b98d5f9ee6f150f53e68d8c2e4394de1b60c | |
parent | 19777f08023deb4d6171525896812b717dd9c968 (diff) | |
download | FreeBSD-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.c | 8 |
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); } |