1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 1982, 1986, 1989, 1991, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
1995-05-11 00:13:26 +00:00
|
|
|
* From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
|
|
|
|
2003-06-11 00:56:59 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
2002-07-31 03:03:22 +00:00
|
|
|
#include "opt_mac.h"
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/param.h>
|
2001-05-01 08:13:21 +00:00
|
|
|
#include <sys/domain.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/fcntl.h>
|
1997-11-23 10:43:49 +00:00
|
|
|
#include <sys/malloc.h> /* XXX must be before <sys/file.h> */
|
1997-02-24 20:30:58 +00:00
|
|
|
#include <sys/file.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/filedesc.h>
|
|
|
|
#include <sys/jail.h>
|
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/lock.h>
|
2002-08-01 01:18:42 +00:00
|
|
|
#include <sys/mac.h>
|
1997-02-24 20:30:58 +00:00
|
|
|
#include <sys/mbuf.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/mutex.h>
|
1997-02-24 20:30:58 +00:00
|
|
|
#include <sys/namei.h>
|
|
|
|
#include <sys/proc.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/protosw.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/resourcevar.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/socketvar.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/signalvar.h>
|
1997-02-24 20:30:58 +00:00
|
|
|
#include <sys/stat.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/sx.h>
|
1997-02-24 20:30:58 +00:00
|
|
|
#include <sys/sysctl.h>
|
2002-04-30 01:54:54 +00:00
|
|
|
#include <sys/systm.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/un.h>
|
1998-05-15 20:11:40 +00:00
|
|
|
#include <sys/unpcb.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/vnode.h>
|
|
|
|
|
2002-03-20 04:11:52 +00:00
|
|
|
#include <vm/uma.h>
|
1998-05-15 20:11:40 +00:00
|
|
|
|
2002-03-20 04:11:52 +00:00
|
|
|
static uma_zone_t unp_zone;
|
1998-05-15 20:11:40 +00:00
|
|
|
static unp_gen_t unp_gencnt;
|
|
|
|
static u_int unp_count;
|
|
|
|
|
|
|
|
static struct unp_head unp_shead, unp_dhead;
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Unix communications domain.
|
|
|
|
*
|
|
|
|
* TODO:
|
|
|
|
* SEQPACKET, RDM
|
|
|
|
* rethink name space problems
|
|
|
|
* need a proper out-of-band
|
1998-05-15 20:11:40 +00:00
|
|
|
* lock pushdown
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2004-06-04 04:07:08 +00:00
|
|
|
static const struct sockaddr sun_noname = { sizeof(sun_noname), AF_LOCAL };
|
1995-12-14 09:55:16 +00:00
|
|
|
static ino_t unp_ino; /* prototype for fake inode numbers */
|
|
|
|
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
static struct mtx unp_mtx;
|
|
|
|
#define UNP_LOCK_INIT() \
|
|
|
|
mtx_init(&unp_mtx, "unp", NULL, MTX_DEF)
|
|
|
|
#define UNP_LOCK() mtx_lock(&unp_mtx)
|
|
|
|
#define UNP_UNLOCK() mtx_unlock(&unp_mtx)
|
|
|
|
#define UNP_LOCK_ASSERT() mtx_assert(&unp_mtx, MA_OWNED)
|
|
|
|
|
2002-03-19 21:25:46 +00:00
|
|
|
static int unp_attach(struct socket *);
|
|
|
|
static void unp_detach(struct unpcb *);
|
|
|
|
static int unp_bind(struct unpcb *,struct sockaddr *, struct thread *);
|
2002-03-24 05:09:11 +00:00
|
|
|
static int unp_connect(struct socket *,struct sockaddr *, struct thread *);
|
2004-03-31 01:41:30 +00:00
|
|
|
static int unp_connect2(struct socket *so, struct socket *so2);
|
2002-03-19 21:25:46 +00:00
|
|
|
static void unp_disconnect(struct unpcb *);
|
|
|
|
static void unp_shutdown(struct unpcb *);
|
|
|
|
static void unp_drop(struct unpcb *, int);
|
|
|
|
static void unp_gc(void);
|
|
|
|
static void unp_scan(struct mbuf *, void (*)(struct file *));
|
|
|
|
static void unp_mark(struct file *);
|
|
|
|
static void unp_discard(struct file *);
|
|
|
|
static void unp_freerights(struct file **, int);
|
|
|
|
static int unp_internalize(struct mbuf **, struct thread *);
|
|
|
|
static int unp_listen(struct unpcb *, struct thread *);
|
1995-12-14 09:55:16 +00:00
|
|
|
|
1997-04-27 20:01:29 +00:00
|
|
|
static int
|
|
|
|
uipc_abort(struct socket *so)
|
|
|
|
{
|
|
|
|
struct unpcb *unp = sotounpcb(so);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp == NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EINVAL);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK();
|
1997-04-27 20:01:29 +00:00
|
|
|
unp_drop(unp, ECONNABORTED);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
unp_detach(unp); /* NB: unlocks */
|
2004-06-12 20:47:32 +00:00
|
|
|
SOCK_LOCK(so);
|
2002-02-25 00:03:34 +00:00
|
|
|
sotryfree(so);
|
2004-01-11 19:48:19 +00:00
|
|
|
return (0);
|
1997-04-27 20:01:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1997-08-16 19:16:27 +00:00
|
|
|
uipc_accept(struct socket *so, struct sockaddr **nam)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
struct unpcb *unp = sotounpcb(so);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
const struct sockaddr *sa;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp == NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EINVAL);
|
1997-04-27 20:01:29 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Pass back name of connected socket,
|
|
|
|
* if it was bound and we are still connected
|
|
|
|
* (our peer may have closed already!).
|
|
|
|
*/
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
*nam = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK);
|
|
|
|
UNP_LOCK();
|
|
|
|
if (unp->unp_conn != NULL && unp->unp_conn->unp_addr != NULL)
|
|
|
|
sa = (struct sockaddr *) unp->unp_conn->unp_addr;
|
|
|
|
else
|
|
|
|
sa = &sun_noname;
|
|
|
|
bcopy(sa, *nam, sa->sa_len);
|
|
|
|
UNP_UNLOCK();
|
2004-01-11 19:48:19 +00:00
|
|
|
return (0);
|
1997-04-27 20:01:29 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1997-04-27 20:01:29 +00:00
|
|
|
static int
|
2001-09-12 08:38:13 +00:00
|
|
|
uipc_attach(struct socket *so, int proto, struct thread *td)
|
1997-04-27 20:01:29 +00:00
|
|
|
{
|
|
|
|
struct unpcb *unp = sotounpcb(so);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp != NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EISCONN);
|
|
|
|
return (unp_attach(so));
|
1997-04-27 20:01:29 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1997-04-27 20:01:29 +00:00
|
|
|
static int
|
2001-09-12 08:38:13 +00:00
|
|
|
uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
|
1997-04-27 20:01:29 +00:00
|
|
|
{
|
|
|
|
struct unpcb *unp = sotounpcb(so);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp == NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EINVAL);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2004-01-11 19:48:19 +00:00
|
|
|
return (unp_bind(unp, nam, td));
|
1997-04-27 20:01:29 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1997-04-27 20:01:29 +00:00
|
|
|
static int
|
2001-09-12 08:38:13 +00:00
|
|
|
uipc_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
|
1997-04-27 20:01:29 +00:00
|
|
|
{
|
|
|
|
struct unpcb *unp = sotounpcb(so);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp == NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EINVAL);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK();
|
|
|
|
error = unp_connect(so, nam, curthread);
|
|
|
|
UNP_UNLOCK();
|
|
|
|
return (error);
|
1997-04-27 20:01:29 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2004-03-31 01:41:30 +00:00
|
|
|
int
|
1997-04-27 20:01:29 +00:00
|
|
|
uipc_connect2(struct socket *so1, struct socket *so2)
|
|
|
|
{
|
|
|
|
struct unpcb *unp = sotounpcb(so1);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp == NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EINVAL);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK();
|
|
|
|
error = unp_connect2(so1, so2);
|
|
|
|
UNP_UNLOCK();
|
|
|
|
return (error);
|
1997-04-27 20:01:29 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1997-04-27 20:01:29 +00:00
|
|
|
/* control is EOPNOTSUPP */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1997-04-27 20:01:29 +00:00
|
|
|
static int
|
|
|
|
uipc_detach(struct socket *so)
|
|
|
|
{
|
|
|
|
struct unpcb *unp = sotounpcb(so);
|
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp == NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EINVAL);
|
1997-04-27 20:01:29 +00:00
|
|
|
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK();
|
|
|
|
unp_detach(unp); /* NB: unlocks unp */
|
2004-01-11 19:48:19 +00:00
|
|
|
return (0);
|
1997-04-27 20:01:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
uipc_disconnect(struct socket *so)
|
|
|
|
{
|
|
|
|
struct unpcb *unp = sotounpcb(so);
|
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp == NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EINVAL);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK();
|
1997-04-27 20:01:29 +00:00
|
|
|
unp_disconnect(unp);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_UNLOCK();
|
2004-01-11 19:48:19 +00:00
|
|
|
return (0);
|
1997-04-27 20:01:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-09-12 08:38:13 +00:00
|
|
|
uipc_listen(struct socket *so, struct thread *td)
|
1997-04-27 20:01:29 +00:00
|
|
|
{
|
|
|
|
struct unpcb *unp = sotounpcb(so);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
int error;
|
1997-04-27 20:01:29 +00:00
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp == NULL || unp->unp_vnode == NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EINVAL);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK();
|
|
|
|
error = unp_listen(unp, td);
|
|
|
|
UNP_UNLOCK();
|
|
|
|
return (error);
|
1997-04-27 20:01:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1997-08-16 19:16:27 +00:00
|
|
|
uipc_peeraddr(struct socket *so, struct sockaddr **nam)
|
1997-04-27 20:01:29 +00:00
|
|
|
{
|
|
|
|
struct unpcb *unp = sotounpcb(so);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
const struct sockaddr *sa;
|
1997-04-27 20:01:29 +00:00
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp == NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EINVAL);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
*nam = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK);
|
|
|
|
UNP_LOCK();
|
|
|
|
if (unp->unp_conn != NULL && unp->unp_conn->unp_addr!= NULL)
|
|
|
|
sa = (struct sockaddr *) unp->unp_conn->unp_addr;
|
2003-01-22 18:03:06 +00:00
|
|
|
else {
|
|
|
|
/*
|
|
|
|
* XXX: It seems that this test always fails even when
|
|
|
|
* connection is established. So, this else clause is
|
|
|
|
* added as workaround to return PF_LOCAL sockaddr.
|
|
|
|
*/
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
sa = &sun_noname;
|
2003-01-22 18:03:06 +00:00
|
|
|
}
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
bcopy(sa, *nam, sa->sa_len);
|
|
|
|
UNP_UNLOCK();
|
2004-01-11 19:48:19 +00:00
|
|
|
return (0);
|
1997-04-27 20:01:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
uipc_rcvd(struct socket *so, int flags)
|
|
|
|
{
|
|
|
|
struct unpcb *unp = sotounpcb(so);
|
|
|
|
struct socket *so2;
|
2000-08-29 11:28:06 +00:00
|
|
|
u_long newhiwat;
|
1997-04-27 20:01:29 +00:00
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp == NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EINVAL);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK();
|
1997-04-27 20:01:29 +00:00
|
|
|
switch (so->so_type) {
|
|
|
|
case SOCK_DGRAM:
|
|
|
|
panic("uipc_rcvd DGRAM?");
|
|
|
|
/*NOTREACHED*/
|
|
|
|
|
|
|
|
case SOCK_STREAM:
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp->unp_conn == NULL)
|
1997-04-27 20:01:29 +00:00
|
|
|
break;
|
|
|
|
so2 = unp->unp_conn->unp_socket;
|
|
|
|
/*
|
|
|
|
* Adjust backpressure on sender
|
|
|
|
* and wakeup any waiting to write.
|
|
|
|
*/
|
1999-09-17 21:38:24 +00:00
|
|
|
so2->so_snd.sb_mbmax += unp->unp_mbcnt - so->so_rcv.sb_mbcnt;
|
|
|
|
unp->unp_mbcnt = so->so_rcv.sb_mbcnt;
|
2000-08-29 11:28:06 +00:00
|
|
|
newhiwat = so2->so_snd.sb_hiwat + unp->unp_cc -
|
|
|
|
so->so_rcv.sb_cc;
|
2000-09-05 22:11:13 +00:00
|
|
|
(void)chgsbsize(so2->so_cred->cr_uidinfo, &so2->so_snd.sb_hiwat,
|
2000-08-29 11:28:06 +00:00
|
|
|
newhiwat, RLIM_INFINITY);
|
1999-09-17 21:38:24 +00:00
|
|
|
unp->unp_cc = so->so_rcv.sb_cc;
|
1997-04-27 20:01:29 +00:00
|
|
|
sowwakeup(so2);
|
1994-05-24 10:09:53 +00:00
|
|
|
break;
|
|
|
|
|
1997-04-27 20:01:29 +00:00
|
|
|
default:
|
|
|
|
panic("uipc_rcvd unknown socktype");
|
|
|
|
}
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_UNLOCK();
|
2004-01-11 19:48:19 +00:00
|
|
|
return (0);
|
1997-04-27 20:01:29 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1997-04-27 20:01:29 +00:00
|
|
|
/* pru_rcvoob is EOPNOTSUPP */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1997-04-27 20:01:29 +00:00
|
|
|
static int
|
1997-08-16 19:16:27 +00:00
|
|
|
uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
2001-09-12 08:38:13 +00:00
|
|
|
struct mbuf *control, struct thread *td)
|
1997-04-27 20:01:29 +00:00
|
|
|
{
|
|
|
|
int error = 0;
|
|
|
|
struct unpcb *unp = sotounpcb(so);
|
|
|
|
struct socket *so2;
|
2000-08-29 11:28:06 +00:00
|
|
|
u_long newhiwat;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp == NULL) {
|
1997-04-27 20:01:29 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto release;
|
|
|
|
}
|
|
|
|
if (flags & PRUS_OOB) {
|
|
|
|
error = EOPNOTSUPP;
|
|
|
|
goto release;
|
|
|
|
}
|
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (control != NULL && (error = unp_internalize(&control, td)))
|
1997-04-27 20:01:29 +00:00
|
|
|
goto release;
|
|
|
|
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK();
|
1997-04-27 20:01:29 +00:00
|
|
|
switch (so->so_type) {
|
2004-01-11 19:48:19 +00:00
|
|
|
case SOCK_DGRAM:
|
1997-04-27 20:01:29 +00:00
|
|
|
{
|
2004-06-04 04:07:08 +00:00
|
|
|
const struct sockaddr *from;
|
1995-05-30 08:16:23 +00:00
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (nam != NULL) {
|
|
|
|
if (unp->unp_conn != NULL) {
|
1997-04-27 20:01:29 +00:00
|
|
|
error = EISCONN;
|
|
|
|
break;
|
|
|
|
}
|
2001-09-12 08:38:13 +00:00
|
|
|
error = unp_connect(so, nam, td);
|
1997-04-27 20:01:29 +00:00
|
|
|
if (error)
|
|
|
|
break;
|
|
|
|
} else {
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp->unp_conn == NULL) {
|
1997-04-27 20:01:29 +00:00
|
|
|
error = ENOTCONN;
|
1994-05-24 10:09:53 +00:00
|
|
|
break;
|
|
|
|
}
|
1997-04-27 20:01:29 +00:00
|
|
|
}
|
|
|
|
so2 = unp->unp_conn->unp_socket;
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp->unp_addr != NULL)
|
1997-08-16 19:16:27 +00:00
|
|
|
from = (struct sockaddr *)unp->unp_addr;
|
1997-04-27 20:01:29 +00:00
|
|
|
else
|
|
|
|
from = &sun_noname;
|
|
|
|
if (sbappendaddr(&so2->so_rcv, from, m, control)) {
|
1994-05-24 10:09:53 +00:00
|
|
|
sorwakeup(so2);
|
2004-03-30 02:16:25 +00:00
|
|
|
m = NULL;
|
|
|
|
control = NULL;
|
2004-01-11 19:48:19 +00:00
|
|
|
} else {
|
1997-04-27 20:01:29 +00:00
|
|
|
error = ENOBUFS;
|
2004-01-11 19:48:19 +00:00
|
|
|
}
|
2004-03-30 02:16:25 +00:00
|
|
|
if (nam != NULL)
|
1997-04-27 20:01:29 +00:00
|
|
|
unp_disconnect(unp);
|
|
|
|
break;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1997-04-27 20:01:29 +00:00
|
|
|
case SOCK_STREAM:
|
|
|
|
/* Connect if not connected yet. */
|
1995-02-07 02:01:16 +00:00
|
|
|
/*
|
1997-04-27 20:01:29 +00:00
|
|
|
* Note: A better implementation would complain
|
|
|
|
* if not equal to the peer's address.
|
1995-02-07 02:01:16 +00:00
|
|
|
*/
|
1997-04-27 20:01:29 +00:00
|
|
|
if ((so->so_state & SS_ISCONNECTED) == 0) {
|
2004-03-30 02:16:25 +00:00
|
|
|
if (nam != NULL) {
|
2001-09-12 08:38:13 +00:00
|
|
|
error = unp_connect(so, nam, td);
|
1997-04-27 20:01:29 +00:00
|
|
|
if (error)
|
|
|
|
break; /* XXX */
|
|
|
|
} else {
|
|
|
|
error = ENOTCONN;
|
|
|
|
break;
|
|
|
|
}
|
1995-02-07 02:01:16 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2004-06-14 18:16:22 +00:00
|
|
|
if (so->so_snd.sb_state & SBS_CANTSENDMORE) {
|
1997-04-27 20:01:29 +00:00
|
|
|
error = EPIPE;
|
|
|
|
break;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp->unp_conn == NULL)
|
1997-04-27 20:01:29 +00:00
|
|
|
panic("uipc_send connected but no connection?");
|
|
|
|
so2 = unp->unp_conn->unp_socket;
|
|
|
|
/*
|
|
|
|
* Send to paired receive port, and then reduce
|
|
|
|
* send buffer hiwater marks to maintain backpressure.
|
|
|
|
* Wake up readers.
|
|
|
|
*/
|
2004-03-30 02:16:25 +00:00
|
|
|
if (control != NULL) {
|
1999-09-17 21:38:24 +00:00
|
|
|
if (sbappendcontrol(&so2->so_rcv, m, control))
|
2004-03-30 02:16:25 +00:00
|
|
|
control = NULL;
|
2004-01-11 19:48:19 +00:00
|
|
|
} else {
|
1999-09-17 21:38:24 +00:00
|
|
|
sbappend(&so2->so_rcv, m);
|
2004-01-11 19:48:19 +00:00
|
|
|
}
|
1999-09-17 21:38:24 +00:00
|
|
|
so->so_snd.sb_mbmax -=
|
|
|
|
so2->so_rcv.sb_mbcnt - unp->unp_conn->unp_mbcnt;
|
|
|
|
unp->unp_conn->unp_mbcnt = so2->so_rcv.sb_mbcnt;
|
2000-08-29 11:28:06 +00:00
|
|
|
newhiwat = so->so_snd.sb_hiwat -
|
|
|
|
(so2->so_rcv.sb_cc - unp->unp_conn->unp_cc);
|
2000-09-05 22:11:13 +00:00
|
|
|
(void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat,
|
2000-08-29 11:28:06 +00:00
|
|
|
newhiwat, RLIM_INFINITY);
|
1999-09-17 21:38:24 +00:00
|
|
|
unp->unp_conn->unp_cc = so2->so_rcv.sb_cc;
|
1997-04-27 20:01:29 +00:00
|
|
|
sorwakeup(so2);
|
2004-03-30 02:16:25 +00:00
|
|
|
m = NULL;
|
1994-05-24 10:09:53 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
1997-04-27 20:01:29 +00:00
|
|
|
panic("uipc_send unknown socktype");
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
1997-04-27 20:01:29 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* SEND_EOF is equivalent to a SEND followed by
|
|
|
|
* a SHUTDOWN.
|
|
|
|
*/
|
|
|
|
if (flags & PRUS_EOF) {
|
|
|
|
socantsendmore(so);
|
|
|
|
unp_shutdown(unp);
|
|
|
|
}
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_UNLOCK();
|
1997-04-27 20:01:29 +00:00
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (control != NULL && error != 0)
|
1999-05-10 18:09:39 +00:00
|
|
|
unp_dispose(control);
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
release:
|
2004-03-30 02:16:25 +00:00
|
|
|
if (control != NULL)
|
1994-05-24 10:09:53 +00:00
|
|
|
m_freem(control);
|
2004-03-30 02:16:25 +00:00
|
|
|
if (m != NULL)
|
1994-05-24 10:09:53 +00:00
|
|
|
m_freem(m);
|
2004-01-11 19:48:19 +00:00
|
|
|
return (error);
|
1997-04-27 20:01:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
uipc_sense(struct socket *so, struct stat *sb)
|
|
|
|
{
|
|
|
|
struct unpcb *unp = sotounpcb(so);
|
|
|
|
struct socket *so2;
|
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp == NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EINVAL);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK();
|
1997-04-27 20:01:29 +00:00
|
|
|
sb->st_blksize = so->so_snd.sb_hiwat;
|
2004-03-30 02:16:25 +00:00
|
|
|
if (so->so_type == SOCK_STREAM && unp->unp_conn != NULL) {
|
1997-04-27 20:01:29 +00:00
|
|
|
so2 = unp->unp_conn->unp_socket;
|
|
|
|
sb->st_blksize += so2->so_rcv.sb_cc;
|
|
|
|
}
|
2004-06-17 17:16:53 +00:00
|
|
|
sb->st_dev = NODEV;
|
1997-04-27 20:01:29 +00:00
|
|
|
if (unp->unp_ino == 0)
|
2002-12-25 07:59:39 +00:00
|
|
|
unp->unp_ino = (++unp_ino == 0) ? ++unp_ino : unp_ino;
|
1997-04-27 20:01:29 +00:00
|
|
|
sb->st_ino = unp->unp_ino;
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_UNLOCK();
|
1997-04-27 20:01:29 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
uipc_shutdown(struct socket *so)
|
|
|
|
{
|
|
|
|
struct unpcb *unp = sotounpcb(so);
|
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp == NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EINVAL);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK();
|
1997-04-27 20:01:29 +00:00
|
|
|
socantsendmore(so);
|
|
|
|
unp_shutdown(unp);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_UNLOCK();
|
2004-01-11 19:48:19 +00:00
|
|
|
return (0);
|
1997-04-27 20:01:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1997-08-16 19:16:27 +00:00
|
|
|
uipc_sockaddr(struct socket *so, struct sockaddr **nam)
|
1997-04-27 20:01:29 +00:00
|
|
|
{
|
|
|
|
struct unpcb *unp = sotounpcb(so);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
const struct sockaddr *sa;
|
1997-04-27 20:01:29 +00:00
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp == NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EINVAL);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
*nam = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK);
|
|
|
|
UNP_LOCK();
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp->unp_addr != NULL)
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
sa = (struct sockaddr *) unp->unp_addr;
|
2001-04-24 19:09:23 +00:00
|
|
|
else
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
sa = &sun_noname;
|
|
|
|
bcopy(sa, *nam, sa->sa_len);
|
|
|
|
UNP_UNLOCK();
|
2004-01-11 19:48:19 +00:00
|
|
|
return (0);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1997-04-27 20:01:29 +00:00
|
|
|
struct pr_usrreqs uipc_usrreqs = {
|
|
|
|
uipc_abort, uipc_accept, uipc_attach, uipc_bind, uipc_connect,
|
|
|
|
uipc_connect2, pru_control_notsupp, uipc_detach, uipc_disconnect,
|
|
|
|
uipc_listen, uipc_peeraddr, uipc_rcvd, pru_rcvoob_notsupp,
|
|
|
|
uipc_send, uipc_sense, uipc_shutdown, uipc_sockaddr,
|
Introduce a MAC label reference in 'struct inpcb', which caches
the MAC label referenced from 'struct socket' in the IPv4 and
IPv6-based protocols. This permits MAC labels to be checked during
network delivery operations without dereferencing inp->inp_socket
to get to so->so_label, which will eventually avoid our having to
grab the socket lock during delivery at the network layer.
This change introduces 'struct inpcb' as a labeled object to the
MAC Framework, along with the normal circus of entry points:
initialization, creation from socket, destruction, as well as a
delivery access control check.
For most policies, the inpcb label will simply be a cache of the
socket label, so a new protocol switch method is introduced,
pr_sosetlabel() to notify protocols that the socket layer label
has been updated so that the cache can be updated while holding
appropriate locks. Most protocols implement this using
pru_sosetlabel_null(), but IPv4/IPv6 protocols using inpcbs use
the the worker function in_pcbsosetlabel(), which calls into the
MAC Framework to perform a cache update.
Biba, LOMAC, and MLS implement these entry points, as do the stub
policy, and test policy.
Reviewed by: sam, bms
Obtained from: TrustedBSD Project
Sponsored by: DARPA, Network Associates Laboratories
2003-11-18 00:39:07 +00:00
|
|
|
sosend, soreceive, sopoll, pru_sosetlabel_null
|
1997-04-27 20:01:29 +00:00
|
|
|
};
|
2001-08-17 22:01:18 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
uipc_ctloutput(so, sopt)
|
|
|
|
struct socket *so;
|
|
|
|
struct sockopt *sopt;
|
|
|
|
{
|
|
|
|
struct unpcb *unp = sotounpcb(so);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
struct xucred xu;
|
2001-08-17 22:01:18 +00:00
|
|
|
int error;
|
|
|
|
|
|
|
|
switch (sopt->sopt_dir) {
|
|
|
|
case SOPT_GET:
|
|
|
|
switch (sopt->sopt_name) {
|
|
|
|
case LOCAL_PEERCRED:
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
error = 0;
|
|
|
|
UNP_LOCK();
|
2001-08-17 22:01:18 +00:00
|
|
|
if (unp->unp_flags & UNP_HAVEPC)
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
xu = unp->unp_peercred;
|
2001-08-17 22:01:18 +00:00
|
|
|
else {
|
|
|
|
if (so->so_type == SOCK_STREAM)
|
|
|
|
error = ENOTCONN;
|
|
|
|
else
|
|
|
|
error = EINVAL;
|
|
|
|
}
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_UNLOCK();
|
|
|
|
if (error == 0)
|
|
|
|
error = sooptcopyout(sopt, &xu, sizeof(xu));
|
2001-08-17 22:01:18 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error = EOPNOTSUPP;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SOPT_SET:
|
|
|
|
default:
|
|
|
|
error = EOPNOTSUPP;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
2004-01-11 19:48:19 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Both send and receive buffers are allocated PIPSIZ bytes of buffering
|
|
|
|
* for stream sockets, although the total for sender and receiver is
|
|
|
|
* actually only PIPSIZ.
|
|
|
|
* Datagram sockets really use the sendspace as the maximum datagram size,
|
|
|
|
* and don't really want to reserve the sendspace. Their recvspace should
|
|
|
|
* be large enough for at least one max-size datagram plus address.
|
|
|
|
*/
|
1995-08-31 01:39:31 +00:00
|
|
|
#ifndef PIPSIZ
|
|
|
|
#define PIPSIZ 8192
|
|
|
|
#endif
|
1995-12-14 09:55:16 +00:00
|
|
|
static u_long unpst_sendspace = PIPSIZ;
|
|
|
|
static u_long unpst_recvspace = PIPSIZ;
|
|
|
|
static u_long unpdg_sendspace = 2*1024; /* really max datagram size */
|
|
|
|
static u_long unpdg_recvspace = 4*1024;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1995-12-14 09:55:16 +00:00
|
|
|
static int unp_rights; /* file descriptors in flight */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1999-02-16 10:49:55 +00:00
|
|
|
SYSCTL_DECL(_net_local_stream);
|
2004-01-11 19:48:19 +00:00
|
|
|
SYSCTL_INT(_net_local_stream, OID_AUTO, sendspace, CTLFLAG_RW,
|
1997-02-24 20:30:58 +00:00
|
|
|
&unpst_sendspace, 0, "");
|
|
|
|
SYSCTL_INT(_net_local_stream, OID_AUTO, recvspace, CTLFLAG_RW,
|
|
|
|
&unpst_recvspace, 0, "");
|
1999-02-16 10:49:55 +00:00
|
|
|
SYSCTL_DECL(_net_local_dgram);
|
1997-02-24 20:30:58 +00:00
|
|
|
SYSCTL_INT(_net_local_dgram, OID_AUTO, maxdgram, CTLFLAG_RW,
|
|
|
|
&unpdg_sendspace, 0, "");
|
|
|
|
SYSCTL_INT(_net_local_dgram, OID_AUTO, recvspace, CTLFLAG_RW,
|
|
|
|
&unpdg_recvspace, 0, "");
|
1999-02-16 10:49:55 +00:00
|
|
|
SYSCTL_DECL(_net_local);
|
1997-02-24 20:30:58 +00:00
|
|
|
SYSCTL_INT(_net_local, OID_AUTO, inflight, CTLFLAG_RD, &unp_rights, 0, "");
|
|
|
|
|
1995-12-14 09:55:16 +00:00
|
|
|
static int
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_attach(so)
|
|
|
|
struct socket *so;
|
|
|
|
{
|
|
|
|
register struct unpcb *unp;
|
|
|
|
int error;
|
1995-05-30 08:16:23 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
|
|
|
|
switch (so->so_type) {
|
|
|
|
|
|
|
|
case SOCK_STREAM:
|
|
|
|
error = soreserve(so, unpst_sendspace, unpst_recvspace);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SOCK_DGRAM:
|
|
|
|
error = soreserve(so, unpdg_sendspace, unpdg_recvspace);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
panic("unp_attach");
|
|
|
|
}
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
}
|
2003-02-19 05:47:46 +00:00
|
|
|
unp = uma_zalloc(unp_zone, M_WAITOK);
|
1997-08-16 19:16:27 +00:00
|
|
|
if (unp == NULL)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (ENOBUFS);
|
1997-08-16 19:16:27 +00:00
|
|
|
bzero(unp, sizeof *unp);
|
1998-05-15 20:11:40 +00:00
|
|
|
LIST_INIT(&unp->unp_refs);
|
1994-05-24 10:09:53 +00:00
|
|
|
unp->unp_socket = so;
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
|
|
|
|
UNP_LOCK();
|
|
|
|
unp->unp_gencnt = ++unp_gencnt;
|
|
|
|
unp_count++;
|
1998-05-15 20:11:40 +00:00
|
|
|
LIST_INSERT_HEAD(so->so_type == SOCK_DGRAM ? &unp_dhead
|
|
|
|
: &unp_shead, unp, unp_link);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_UNLOCK();
|
|
|
|
|
2002-06-28 23:17:36 +00:00
|
|
|
so->so_pcb = unp;
|
1994-05-24 10:09:53 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1995-12-14 09:55:16 +00:00
|
|
|
static void
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_detach(unp)
|
|
|
|
register struct unpcb *unp;
|
|
|
|
{
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
struct vnode *vp;
|
|
|
|
|
|
|
|
UNP_LOCK_ASSERT();
|
|
|
|
|
1998-05-15 20:11:40 +00:00
|
|
|
LIST_REMOVE(unp, unp_link);
|
|
|
|
unp->unp_gencnt = ++unp_gencnt;
|
|
|
|
--unp_count;
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
if ((vp = unp->unp_vnode) != NULL) {
|
|
|
|
/*
|
|
|
|
* XXXRW: should v_socket be frobbed only while holding
|
|
|
|
* Giant?
|
|
|
|
*/
|
2004-03-30 02:16:25 +00:00
|
|
|
unp->unp_vnode->v_socket = NULL;
|
|
|
|
unp->unp_vnode = NULL;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp->unp_conn != NULL)
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_disconnect(unp);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
while (!LIST_EMPTY(&unp->unp_refs)) {
|
|
|
|
struct unpcb *ref = LIST_FIRST(&unp->unp_refs);
|
|
|
|
unp_drop(ref, ECONNRESET);
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
soisdisconnected(unp->unp_socket);
|
2004-03-30 02:16:25 +00:00
|
|
|
unp->unp_socket->so_pcb = NULL;
|
1994-05-24 10:09:53 +00:00
|
|
|
if (unp_rights) {
|
|
|
|
/*
|
|
|
|
* Normally the receive buffer is flushed later,
|
|
|
|
* in sofree, but if our receive buffer holds references
|
|
|
|
* to descriptors that are now garbage, we will dispose
|
|
|
|
* of those descriptor references after the garbage collector
|
|
|
|
* gets them (resulting in a "panic: closef: count < 0").
|
|
|
|
*/
|
|
|
|
sorflush(unp->unp_socket);
|
|
|
|
unp_gc();
|
|
|
|
}
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp->unp_addr != NULL)
|
1997-08-16 19:16:27 +00:00
|
|
|
FREE(unp->unp_addr, M_SONAME);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_UNLOCK();
|
2002-03-20 04:11:52 +00:00
|
|
|
uma_zfree(unp_zone, unp);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
if (vp) {
|
|
|
|
mtx_lock(&Giant);
|
|
|
|
vrele(vp);
|
|
|
|
mtx_unlock(&Giant);
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1995-12-14 09:55:16 +00:00
|
|
|
static int
|
2001-09-12 08:38:13 +00:00
|
|
|
unp_bind(unp, nam, td)
|
1994-05-24 10:09:53 +00:00
|
|
|
struct unpcb *unp;
|
1997-08-16 19:16:27 +00:00
|
|
|
struct sockaddr *nam;
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
1997-08-16 19:16:27 +00:00
|
|
|
struct sockaddr_un *soun = (struct sockaddr_un *)nam;
|
2000-07-11 22:07:57 +00:00
|
|
|
struct vnode *vp;
|
|
|
|
struct mount *mp;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct vattr vattr;
|
1997-08-16 19:16:27 +00:00
|
|
|
int error, namelen;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nameidata nd;
|
2001-08-18 02:53:50 +00:00
|
|
|
char *buf;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
/*
|
|
|
|
* XXXRW: This test-and-set of unp_vnode is non-atomic; the
|
|
|
|
* unlocked read here is fine, but the value of unp_vnode needs
|
|
|
|
* to be tested again after we do all the lookups to see if the
|
|
|
|
* pcb is still unbound?
|
|
|
|
*/
|
1994-05-24 10:09:53 +00:00
|
|
|
if (unp->unp_vnode != NULL)
|
|
|
|
return (EINVAL);
|
2002-10-17 15:52:42 +00:00
|
|
|
|
1997-08-16 19:16:27 +00:00
|
|
|
namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path);
|
|
|
|
if (namelen <= 0)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EINVAL);
|
2002-10-17 15:52:42 +00:00
|
|
|
|
2003-02-19 05:47:46 +00:00
|
|
|
buf = malloc(namelen + 1, M_TEMP, M_WAITOK);
|
2002-10-17 15:52:42 +00:00
|
|
|
strlcpy(buf, soun->sun_path, namelen + 1);
|
|
|
|
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
mtx_lock(&Giant);
|
2000-07-11 22:07:57 +00:00
|
|
|
restart:
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
mtx_assert(&Giant, MA_OWNED);
|
2002-08-01 01:16:22 +00:00
|
|
|
NDINIT(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME, UIO_SYSSPACE,
|
2001-09-12 08:38:13 +00:00
|
|
|
buf, td);
|
1994-05-24 10:09:53 +00:00
|
|
|
/* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
|
1994-10-02 17:35:40 +00:00
|
|
|
error = namei(&nd);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
if (error)
|
|
|
|
goto done;
|
1994-05-24 10:09:53 +00:00
|
|
|
vp = nd.ni_vp;
|
2000-07-11 22:07:57 +00:00
|
|
|
if (vp != NULL || vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
1994-05-24 10:09:53 +00:00
|
|
|
if (nd.ni_dvp == vp)
|
|
|
|
vrele(nd.ni_dvp);
|
|
|
|
else
|
|
|
|
vput(nd.ni_dvp);
|
2000-07-11 22:07:57 +00:00
|
|
|
if (vp != NULL) {
|
|
|
|
vrele(vp);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
error = EADDRINUSE;
|
|
|
|
goto done;
|
2000-07-11 22:07:57 +00:00
|
|
|
}
|
2001-08-18 02:53:50 +00:00
|
|
|
error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
if (error)
|
|
|
|
goto done;
|
2000-07-11 22:07:57 +00:00
|
|
|
goto restart;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
VATTR_NULL(&vattr);
|
|
|
|
vattr.va_type = VSOCK;
|
2001-09-12 08:38:13 +00:00
|
|
|
vattr.va_mode = (ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask);
|
2002-08-01 01:18:42 +00:00
|
|
|
#ifdef MAC
|
|
|
|
error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
|
|
|
|
&vattr);
|
2002-10-28 21:17:53 +00:00
|
|
|
#endif
|
2002-08-01 01:18:42 +00:00
|
|
|
if (error == 0) {
|
|
|
|
VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
|
|
|
|
error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
|
|
|
|
}
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
1998-05-07 04:58:58 +00:00
|
|
|
vput(nd.ni_dvp);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
if (error)
|
|
|
|
goto done;
|
1994-05-24 10:09:53 +00:00
|
|
|
vp = nd.ni_vp;
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
ASSERT_VOP_LOCKED(vp, "unp_bind");
|
|
|
|
soun = (struct sockaddr_un *)sodupsockaddr(nam, M_WAITOK);
|
|
|
|
UNP_LOCK();
|
1994-05-24 10:09:53 +00:00
|
|
|
vp->v_socket = unp->unp_socket;
|
|
|
|
unp->unp_vnode = vp;
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
unp->unp_addr = soun;
|
|
|
|
UNP_UNLOCK();
|
2001-09-12 08:38:13 +00:00
|
|
|
VOP_UNLOCK(vp, 0, td);
|
2000-07-11 22:07:57 +00:00
|
|
|
vn_finished_write(mp);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
done:
|
|
|
|
mtx_unlock(&Giant);
|
2001-08-18 02:53:50 +00:00
|
|
|
free(buf, M_TEMP);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1995-12-14 09:55:16 +00:00
|
|
|
static int
|
2001-09-12 08:38:13 +00:00
|
|
|
unp_connect(so, nam, td)
|
1994-05-24 10:09:53 +00:00
|
|
|
struct socket *so;
|
1997-08-16 19:16:27 +00:00
|
|
|
struct sockaddr *nam;
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
1997-08-16 19:16:27 +00:00
|
|
|
register struct sockaddr_un *soun = (struct sockaddr_un *)nam;
|
1994-05-24 10:09:53 +00:00
|
|
|
register struct vnode *vp;
|
|
|
|
register struct socket *so2, *so3;
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
struct unpcb *unp = sotounpcb(so);
|
|
|
|
struct unpcb *unp2, *unp3;
|
1997-08-16 19:16:27 +00:00
|
|
|
int error, len;
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nameidata nd;
|
1997-08-16 19:16:27 +00:00
|
|
|
char buf[SOCK_MAXADDRLEN];
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
struct sockaddr *sa;
|
|
|
|
|
|
|
|
UNP_LOCK_ASSERT();
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1997-08-16 19:16:27 +00:00
|
|
|
len = nam->sa_len - offsetof(struct sockaddr_un, sun_path);
|
|
|
|
if (len <= 0)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EINVAL);
|
2002-10-17 15:52:42 +00:00
|
|
|
strlcpy(buf, soun->sun_path, len + 1);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_UNLOCK();
|
|
|
|
sa = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK);
|
|
|
|
mtx_lock(&Giant);
|
2001-09-12 08:38:13 +00:00
|
|
|
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, buf, td);
|
1994-10-02 17:35:40 +00:00
|
|
|
error = namei(&nd);
|
|
|
|
if (error)
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
vp = NULL;
|
|
|
|
else
|
|
|
|
vp = nd.ni_vp;
|
|
|
|
ASSERT_VOP_LOCKED(vp, "unp_connect");
|
1999-12-15 23:02:35 +00:00
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
if (error)
|
|
|
|
goto bad;
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
if (vp->v_type != VSOCK) {
|
|
|
|
error = ENOTSOCK;
|
|
|
|
goto bad;
|
|
|
|
}
|
2002-02-27 18:32:23 +00:00
|
|
|
error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td);
|
1994-10-02 17:35:40 +00:00
|
|
|
if (error)
|
1994-05-24 10:09:53 +00:00
|
|
|
goto bad;
|
|
|
|
so2 = vp->v_socket;
|
2004-03-30 02:16:25 +00:00
|
|
|
if (so2 == NULL) {
|
1994-05-24 10:09:53 +00:00
|
|
|
error = ECONNREFUSED;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
if (so->so_type != so2->so_type) {
|
|
|
|
error = EPROTOTYPE;
|
|
|
|
goto bad;
|
|
|
|
}
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
mtx_unlock(&Giant);
|
|
|
|
UNP_LOCK();
|
1994-05-24 10:09:53 +00:00
|
|
|
if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
if (so2->so_options & SO_ACCEPTCONN) {
|
|
|
|
/*
|
|
|
|
* NB: drop locks here so unp_attach is entered
|
|
|
|
* w/o locks; this avoids a recursive lock
|
|
|
|
* of the head and holding sleep locks across
|
|
|
|
* a (potentially) blocking malloc.
|
|
|
|
*/
|
|
|
|
UNP_UNLOCK();
|
|
|
|
so3 = sonewconn(so2, 0);
|
|
|
|
UNP_LOCK();
|
|
|
|
} else
|
|
|
|
so3 = NULL;
|
|
|
|
if (so3 == NULL) {
|
1994-05-24 10:09:53 +00:00
|
|
|
error = ECONNREFUSED;
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
goto bad2;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2001-08-17 22:01:18 +00:00
|
|
|
unp = sotounpcb(so);
|
1994-05-24 10:09:53 +00:00
|
|
|
unp2 = sotounpcb(so2);
|
|
|
|
unp3 = sotounpcb(so3);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
if (unp2->unp_addr != NULL) {
|
|
|
|
bcopy(unp2->unp_addr, sa, unp2->unp_addr->sun_len);
|
|
|
|
unp3->unp_addr = (struct sockaddr_un *) sa;
|
|
|
|
sa = NULL;
|
|
|
|
}
|
2001-08-17 22:01:18 +00:00
|
|
|
/*
|
|
|
|
* unp_peercred management:
|
|
|
|
*
|
|
|
|
* The connecter's (client's) credentials are copied
|
|
|
|
* from its process structure at the time of connect()
|
|
|
|
* (which is now).
|
|
|
|
*/
|
2002-02-27 18:32:23 +00:00
|
|
|
cru2x(td->td_ucred, &unp3->unp_peercred);
|
2001-08-17 22:01:18 +00:00
|
|
|
unp3->unp_flags |= UNP_HAVEPC;
|
|
|
|
/*
|
|
|
|
* The receiver's (server's) credentials are copied
|
|
|
|
* from the unp_peercred member of socket on which the
|
|
|
|
* former called listen(); unp_listen() cached that
|
|
|
|
* process's credentials at that time so we can use
|
|
|
|
* them now.
|
|
|
|
*/
|
|
|
|
KASSERT(unp2->unp_flags & UNP_HAVEPCCACHED,
|
|
|
|
("unp_connect: listener without cached peercred"));
|
|
|
|
memcpy(&unp->unp_peercred, &unp2->unp_peercred,
|
|
|
|
sizeof(unp->unp_peercred));
|
|
|
|
unp->unp_flags |= UNP_HAVEPC;
|
2002-07-31 03:03:22 +00:00
|
|
|
#ifdef MAC
|
2004-06-13 02:50:07 +00:00
|
|
|
SOCK_LOCK(so);
|
2002-07-31 03:03:22 +00:00
|
|
|
mac_set_socket_peer_from_socket(so, so3);
|
|
|
|
mac_set_socket_peer_from_socket(so3, so);
|
2004-06-13 02:50:07 +00:00
|
|
|
SOCK_UNLOCK(so);
|
2002-07-31 03:03:22 +00:00
|
|
|
#endif
|
2001-08-17 22:01:18 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
so2 = so3;
|
|
|
|
}
|
|
|
|
error = unp_connect2(so, so2);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
bad2:
|
|
|
|
UNP_UNLOCK();
|
|
|
|
mtx_lock(&Giant);
|
1994-05-24 10:09:53 +00:00
|
|
|
bad:
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
mtx_assert(&Giant, MA_OWNED);
|
|
|
|
if (vp != NULL)
|
|
|
|
vput(vp);
|
|
|
|
mtx_unlock(&Giant);
|
|
|
|
free(sa, M_SONAME);
|
|
|
|
UNP_LOCK();
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2004-03-31 01:41:30 +00:00
|
|
|
static int
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_connect2(so, so2)
|
|
|
|
register struct socket *so;
|
|
|
|
register struct socket *so2;
|
|
|
|
{
|
|
|
|
register struct unpcb *unp = sotounpcb(so);
|
|
|
|
register struct unpcb *unp2;
|
|
|
|
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK_ASSERT();
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
if (so2->so_type != so->so_type)
|
|
|
|
return (EPROTOTYPE);
|
|
|
|
unp2 = sotounpcb(so2);
|
|
|
|
unp->unp_conn = unp2;
|
|
|
|
switch (so->so_type) {
|
|
|
|
|
|
|
|
case SOCK_DGRAM:
|
1998-05-15 20:11:40 +00:00
|
|
|
LIST_INSERT_HEAD(&unp2->unp_refs, unp, unp_reflink);
|
1994-05-24 10:09:53 +00:00
|
|
|
soisconnected(so);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SOCK_STREAM:
|
|
|
|
unp2->unp_conn = unp;
|
|
|
|
soisconnected(so);
|
|
|
|
soisconnected(so2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
panic("unp_connect2");
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1995-12-14 09:55:16 +00:00
|
|
|
static void
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_disconnect(unp)
|
|
|
|
struct unpcb *unp;
|
|
|
|
{
|
|
|
|
register struct unpcb *unp2 = unp->unp_conn;
|
|
|
|
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK_ASSERT();
|
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp2 == NULL)
|
1994-05-24 10:09:53 +00:00
|
|
|
return;
|
2004-03-30 02:16:25 +00:00
|
|
|
unp->unp_conn = NULL;
|
1994-05-24 10:09:53 +00:00
|
|
|
switch (unp->unp_socket->so_type) {
|
|
|
|
|
|
|
|
case SOCK_DGRAM:
|
1998-05-15 20:11:40 +00:00
|
|
|
LIST_REMOVE(unp, unp_reflink);
|
1994-05-24 10:09:53 +00:00
|
|
|
unp->unp_socket->so_state &= ~SS_ISCONNECTED;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SOCK_STREAM:
|
|
|
|
soisdisconnected(unp->unp_socket);
|
2004-03-30 02:16:25 +00:00
|
|
|
unp2->unp_conn = NULL;
|
1994-05-24 10:09:53 +00:00
|
|
|
soisdisconnected(unp2->unp_socket);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef notdef
|
1994-05-25 09:21:21 +00:00
|
|
|
void
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_abort(unp)
|
|
|
|
struct unpcb *unp;
|
|
|
|
{
|
|
|
|
|
|
|
|
unp_detach(unp);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
/*
|
|
|
|
* unp_pcblist() assumes that UNIX domain socket memory is never reclaimed
|
|
|
|
* by the zone (UMA_ZONE_NOFREE), and as such potentially stale pointers
|
|
|
|
* are safe to reference. It first scans the list of struct unpcb's to
|
|
|
|
* generate a pointer list, then it rescans its list one entry at a time to
|
|
|
|
* externalize and copyout. It checks the generation number to see if a
|
|
|
|
* struct unpcb has been reused, and will skip it if so.
|
|
|
|
*/
|
1998-05-15 20:11:40 +00:00
|
|
|
static int
|
2000-07-04 11:25:35 +00:00
|
|
|
unp_pcblist(SYSCTL_HANDLER_ARGS)
|
1998-05-15 20:11:40 +00:00
|
|
|
{
|
1998-10-25 17:44:59 +00:00
|
|
|
int error, i, n;
|
1998-05-15 20:11:40 +00:00
|
|
|
struct unpcb *unp, **unp_list;
|
|
|
|
unp_gen_t gencnt;
|
2001-08-18 02:53:50 +00:00
|
|
|
struct xunpgen *xug;
|
1998-05-15 20:11:40 +00:00
|
|
|
struct unp_head *head;
|
2001-08-18 02:53:50 +00:00
|
|
|
struct xunpcb *xu;
|
1998-05-15 20:11:40 +00:00
|
|
|
|
1998-07-15 02:32:35 +00:00
|
|
|
head = ((intptr_t)arg1 == SOCK_DGRAM ? &unp_dhead : &unp_shead);
|
1998-05-15 20:11:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The process of preparing the PCB list is too time-consuming and
|
|
|
|
* resource-intensive to repeat twice on every request.
|
|
|
|
*/
|
2004-03-30 02:16:25 +00:00
|
|
|
if (req->oldptr == NULL) {
|
1998-05-15 20:11:40 +00:00
|
|
|
n = unp_count;
|
2001-08-18 02:53:50 +00:00
|
|
|
req->oldidx = 2 * (sizeof *xug)
|
1998-05-15 20:11:40 +00:00
|
|
|
+ (n + n/8) * sizeof(struct xunpcb);
|
2004-01-11 19:48:19 +00:00
|
|
|
return (0);
|
1998-05-15 20:11:40 +00:00
|
|
|
}
|
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
if (req->newptr != NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
return (EPERM);
|
1998-05-15 20:11:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* OK, now we're committed to doing something.
|
|
|
|
*/
|
2003-02-19 05:47:46 +00:00
|
|
|
xug = malloc(sizeof(*xug), M_TEMP, M_WAITOK);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK();
|
1998-05-15 20:11:40 +00:00
|
|
|
gencnt = unp_gencnt;
|
|
|
|
n = unp_count;
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_UNLOCK();
|
1998-05-15 20:11:40 +00:00
|
|
|
|
2001-08-18 02:53:50 +00:00
|
|
|
xug->xug_len = sizeof *xug;
|
|
|
|
xug->xug_count = n;
|
|
|
|
xug->xug_gen = gencnt;
|
|
|
|
xug->xug_sogen = so_gencnt;
|
|
|
|
error = SYSCTL_OUT(req, xug, sizeof *xug);
|
|
|
|
if (error) {
|
|
|
|
free(xug, M_TEMP);
|
2004-01-11 19:48:19 +00:00
|
|
|
return (error);
|
2001-08-18 02:53:50 +00:00
|
|
|
}
|
1998-05-15 20:11:40 +00:00
|
|
|
|
2003-02-19 05:47:46 +00:00
|
|
|
unp_list = malloc(n * sizeof *unp_list, M_TEMP, M_WAITOK);
|
2004-01-11 19:48:19 +00:00
|
|
|
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK();
|
1999-11-16 10:56:05 +00:00
|
|
|
for (unp = LIST_FIRST(head), i = 0; unp && i < n;
|
|
|
|
unp = LIST_NEXT(unp, unp_link)) {
|
2001-10-09 21:40:30 +00:00
|
|
|
if (unp->unp_gencnt <= gencnt) {
|
2002-02-27 18:32:23 +00:00
|
|
|
if (cr_cansee(req->td->td_ucred,
|
2001-10-09 21:40:30 +00:00
|
|
|
unp->unp_socket->so_cred))
|
2001-10-05 07:06:32 +00:00
|
|
|
continue;
|
1998-05-15 20:11:40 +00:00
|
|
|
unp_list[i++] = unp;
|
2001-10-05 07:06:32 +00:00
|
|
|
}
|
1998-05-15 20:11:40 +00:00
|
|
|
}
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_UNLOCK();
|
1998-05-15 20:11:40 +00:00
|
|
|
n = i; /* in case we lost some during malloc */
|
|
|
|
|
|
|
|
error = 0;
|
2003-02-19 05:47:46 +00:00
|
|
|
xu = malloc(sizeof(*xu), M_TEMP, M_WAITOK);
|
1998-05-15 20:11:40 +00:00
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
unp = unp_list[i];
|
|
|
|
if (unp->unp_gencnt <= gencnt) {
|
2001-08-18 02:53:50 +00:00
|
|
|
xu->xu_len = sizeof *xu;
|
|
|
|
xu->xu_unpp = unp;
|
1998-05-15 20:11:40 +00:00
|
|
|
/*
|
|
|
|
* XXX - need more locking here to protect against
|
|
|
|
* connect/disconnect races for SMP.
|
|
|
|
*/
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp->unp_addr != NULL)
|
2004-01-11 19:48:19 +00:00
|
|
|
bcopy(unp->unp_addr, &xu->xu_addr,
|
1998-05-15 20:11:40 +00:00
|
|
|
unp->unp_addr->sun_len);
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp->unp_conn != NULL &&
|
|
|
|
unp->unp_conn->unp_addr != NULL)
|
1998-05-15 20:11:40 +00:00
|
|
|
bcopy(unp->unp_conn->unp_addr,
|
2001-08-18 02:53:50 +00:00
|
|
|
&xu->xu_caddr,
|
1998-05-15 20:11:40 +00:00
|
|
|
unp->unp_conn->unp_addr->sun_len);
|
2001-08-18 02:53:50 +00:00
|
|
|
bcopy(unp, &xu->xu_unp, sizeof *unp);
|
|
|
|
sotoxsocket(unp->unp_socket, &xu->xu_socket);
|
|
|
|
error = SYSCTL_OUT(req, xu, sizeof *xu);
|
1998-05-15 20:11:40 +00:00
|
|
|
}
|
|
|
|
}
|
2001-08-18 02:53:50 +00:00
|
|
|
free(xu, M_TEMP);
|
1998-05-15 20:11:40 +00:00
|
|
|
if (!error) {
|
|
|
|
/*
|
|
|
|
* Give the user an updated idea of our state.
|
|
|
|
* If the generation differs from what we told
|
|
|
|
* her before, she knows that something happened
|
|
|
|
* while we were processing this request, and it
|
|
|
|
* might be necessary to retry.
|
|
|
|
*/
|
2001-08-18 02:53:50 +00:00
|
|
|
xug->xug_gen = unp_gencnt;
|
|
|
|
xug->xug_sogen = so_gencnt;
|
|
|
|
xug->xug_count = unp_count;
|
|
|
|
error = SYSCTL_OUT(req, xug, sizeof *xug);
|
1998-05-15 20:11:40 +00:00
|
|
|
}
|
|
|
|
free(unp_list, M_TEMP);
|
2001-08-18 02:53:50 +00:00
|
|
|
free(xug, M_TEMP);
|
2004-01-11 19:48:19 +00:00
|
|
|
return (error);
|
1998-05-15 20:11:40 +00:00
|
|
|
}
|
|
|
|
|
2004-01-11 19:48:19 +00:00
|
|
|
SYSCTL_PROC(_net_local_dgram, OID_AUTO, pcblist, CTLFLAG_RD,
|
1998-05-15 20:11:40 +00:00
|
|
|
(caddr_t)(long)SOCK_DGRAM, 0, unp_pcblist, "S,xunpcb",
|
|
|
|
"List of active local datagram sockets");
|
2004-01-11 19:48:19 +00:00
|
|
|
SYSCTL_PROC(_net_local_stream, OID_AUTO, pcblist, CTLFLAG_RD,
|
1998-05-15 20:11:40 +00:00
|
|
|
(caddr_t)(long)SOCK_STREAM, 0, unp_pcblist, "S,xunpcb",
|
|
|
|
"List of active local stream sockets");
|
|
|
|
|
1995-12-14 09:55:16 +00:00
|
|
|
static void
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_shutdown(unp)
|
|
|
|
struct unpcb *unp;
|
|
|
|
{
|
|
|
|
struct socket *so;
|
|
|
|
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK_ASSERT();
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
if (unp->unp_socket->so_type == SOCK_STREAM && unp->unp_conn &&
|
|
|
|
(so = unp->unp_conn->unp_socket))
|
|
|
|
socantrcvmore(so);
|
|
|
|
}
|
|
|
|
|
1995-12-14 09:55:16 +00:00
|
|
|
static void
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_drop(unp, errno)
|
|
|
|
struct unpcb *unp;
|
|
|
|
int errno;
|
|
|
|
{
|
|
|
|
struct socket *so = unp->unp_socket;
|
|
|
|
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK_ASSERT();
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
so->so_error = errno;
|
|
|
|
unp_disconnect(unp);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef notdef
|
1994-05-25 09:21:21 +00:00
|
|
|
void
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_drain()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2001-10-04 13:11:48 +00:00
|
|
|
static void
|
|
|
|
unp_freerights(rp, fdcount)
|
|
|
|
struct file **rp;
|
|
|
|
int fdcount;
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct file *fp;
|
|
|
|
|
|
|
|
for (i = 0; i < fdcount; i++) {
|
|
|
|
fp = *rp;
|
|
|
|
/*
|
|
|
|
* zero the pointer before calling
|
|
|
|
* unp_discard since it may end up
|
|
|
|
* in unp_gc()..
|
|
|
|
*/
|
|
|
|
*rp++ = 0;
|
|
|
|
unp_discard(fp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2001-10-04 13:11:48 +00:00
|
|
|
unp_externalize(control, controlp)
|
|
|
|
struct mbuf *control, **controlp;
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td = curthread; /* XXX */
|
2001-10-04 13:11:48 +00:00
|
|
|
struct cmsghdr *cm = mtod(control, struct cmsghdr *);
|
|
|
|
int i;
|
|
|
|
int *fdp;
|
|
|
|
struct file **rp;
|
|
|
|
struct file *fp;
|
|
|
|
void *data;
|
|
|
|
socklen_t clen = control->m_len, datalen;
|
|
|
|
int error, newfds;
|
1994-05-24 10:09:53 +00:00
|
|
|
int f;
|
2001-10-04 13:11:48 +00:00
|
|
|
u_int newlen;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2001-10-04 13:11:48 +00:00
|
|
|
error = 0;
|
|
|
|
if (controlp != NULL) /* controlp == NULL => free control messages */
|
|
|
|
*controlp = NULL;
|
|
|
|
|
|
|
|
while (cm != NULL) {
|
|
|
|
if (sizeof(*cm) > clen || cm->cmsg_len > clen) {
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = CMSG_DATA(cm);
|
|
|
|
datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
|
|
|
|
|
|
|
|
if (cm->cmsg_level == SOL_SOCKET
|
|
|
|
&& cm->cmsg_type == SCM_RIGHTS) {
|
|
|
|
newfds = datalen / sizeof(struct file *);
|
|
|
|
rp = data;
|
|
|
|
|
2003-03-23 19:41:34 +00:00
|
|
|
/* If we're not outputting the descriptors free them. */
|
2001-10-04 13:11:48 +00:00
|
|
|
if (error || controlp == NULL) {
|
|
|
|
unp_freerights(rp, newfds);
|
|
|
|
goto next;
|
|
|
|
}
|
2002-01-13 11:58:06 +00:00
|
|
|
FILEDESC_LOCK(td->td_proc->p_fd);
|
2001-10-04 13:11:48 +00:00
|
|
|
/* if the new FD's will not fit free them. */
|
|
|
|
if (!fdavail(td, newfds)) {
|
2002-01-13 11:58:06 +00:00
|
|
|
FILEDESC_UNLOCK(td->td_proc->p_fd);
|
2001-10-04 13:11:48 +00:00
|
|
|
error = EMSGSIZE;
|
|
|
|
unp_freerights(rp, newfds);
|
|
|
|
goto next;
|
|
|
|
}
|
2000-03-09 15:15:27 +00:00
|
|
|
/*
|
2001-10-04 13:11:48 +00:00
|
|
|
* now change each pointer to an fd in the global
|
|
|
|
* table to an integer that is the index to the
|
|
|
|
* local fd table entry that we set up to point
|
|
|
|
* to the global one we are transferring.
|
2000-03-09 15:15:27 +00:00
|
|
|
*/
|
2001-10-04 13:11:48 +00:00
|
|
|
newlen = newfds * sizeof(int);
|
|
|
|
*controlp = sbcreatecontrol(NULL, newlen,
|
|
|
|
SCM_RIGHTS, SOL_SOCKET);
|
|
|
|
if (*controlp == NULL) {
|
2002-01-13 11:58:06 +00:00
|
|
|
FILEDESC_UNLOCK(td->td_proc->p_fd);
|
2001-10-04 13:11:48 +00:00
|
|
|
error = E2BIG;
|
|
|
|
unp_freerights(rp, newfds);
|
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
|
|
|
|
fdp = (int *)
|
|
|
|
CMSG_DATA(mtod(*controlp, struct cmsghdr *));
|
|
|
|
for (i = 0; i < newfds; i++) {
|
2004-01-17 00:59:04 +00:00
|
|
|
if (fdalloc(td, 0, &f))
|
2001-10-04 13:11:48 +00:00
|
|
|
panic("unp_externalize fdalloc failed");
|
|
|
|
fp = *rp++;
|
|
|
|
td->td_proc->p_fd->fd_ofiles[f] = fp;
|
2002-01-13 11:58:06 +00:00
|
|
|
FILE_LOCK(fp);
|
2001-10-04 13:11:48 +00:00
|
|
|
fp->f_msgcount--;
|
2002-01-13 11:58:06 +00:00
|
|
|
FILE_UNLOCK(fp);
|
2001-10-04 13:11:48 +00:00
|
|
|
unp_rights--;
|
|
|
|
*fdp++ = f;
|
|
|
|
}
|
2002-01-13 11:58:06 +00:00
|
|
|
FILEDESC_UNLOCK(td->td_proc->p_fd);
|
2001-10-04 13:11:48 +00:00
|
|
|
} else { /* We can just copy anything else across */
|
|
|
|
if (error || controlp == NULL)
|
|
|
|
goto next;
|
|
|
|
*controlp = sbcreatecontrol(NULL, datalen,
|
|
|
|
cm->cmsg_type, cm->cmsg_level);
|
|
|
|
if (*controlp == NULL) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
bcopy(data,
|
|
|
|
CMSG_DATA(mtod(*controlp, struct cmsghdr *)),
|
|
|
|
datalen);
|
2000-03-09 15:15:27 +00:00
|
|
|
}
|
2001-10-04 13:11:48 +00:00
|
|
|
|
|
|
|
controlp = &(*controlp)->m_next;
|
|
|
|
|
|
|
|
next:
|
|
|
|
if (CMSG_SPACE(datalen) < clen) {
|
|
|
|
clen -= CMSG_SPACE(datalen);
|
|
|
|
cm = (struct cmsghdr *)
|
|
|
|
((caddr_t)cm + CMSG_SPACE(datalen));
|
|
|
|
} else {
|
|
|
|
clen = 0;
|
|
|
|
cm = NULL;
|
2000-03-09 15:15:27 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2000-03-09 15:15:27 +00:00
|
|
|
|
2001-10-04 13:11:48 +00:00
|
|
|
m_freem(control);
|
|
|
|
|
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1998-05-15 20:11:40 +00:00
|
|
|
void
|
|
|
|
unp_init(void)
|
|
|
|
{
|
2002-03-20 04:11:52 +00:00
|
|
|
unp_zone = uma_zcreate("unpcb", sizeof(struct unpcb), NULL, NULL,
|
|
|
|
NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
|
2004-03-30 02:16:25 +00:00
|
|
|
if (unp_zone == NULL)
|
1998-05-15 20:11:40 +00:00
|
|
|
panic("unp_init");
|
2004-02-22 01:11:53 +00:00
|
|
|
uma_zone_set_max(unp_zone, nmbclusters);
|
1998-05-15 20:11:40 +00:00
|
|
|
LIST_INIT(&unp_dhead);
|
|
|
|
LIST_INIT(&unp_shead);
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
|
|
|
|
UNP_LOCK_INIT();
|
1998-05-15 20:11:40 +00:00
|
|
|
}
|
|
|
|
|
1995-12-14 09:55:16 +00:00
|
|
|
static int
|
2001-10-04 13:11:48 +00:00
|
|
|
unp_internalize(controlp, td)
|
|
|
|
struct mbuf **controlp;
|
2001-09-12 08:38:13 +00:00
|
|
|
struct thread *td;
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2001-10-04 13:11:48 +00:00
|
|
|
struct mbuf *control = *controlp;
|
2001-09-12 08:38:13 +00:00
|
|
|
struct proc *p = td->td_proc;
|
2000-03-09 15:15:27 +00:00
|
|
|
struct filedesc *fdescp = p->p_fd;
|
2001-10-04 13:11:48 +00:00
|
|
|
struct cmsghdr *cm = mtod(control, struct cmsghdr *);
|
|
|
|
struct cmsgcred *cmcred;
|
|
|
|
struct file **rp;
|
|
|
|
struct file *fp;
|
|
|
|
struct timeval *tv;
|
|
|
|
int i, fd, *fdp;
|
|
|
|
void *data;
|
|
|
|
socklen_t clen = control->m_len, datalen;
|
|
|
|
int error, oldfds;
|
2000-03-09 15:15:27 +00:00
|
|
|
u_int newlen;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2001-10-04 13:11:48 +00:00
|
|
|
error = 0;
|
|
|
|
*controlp = NULL;
|
Add support to sendmsg()/recvmsg() for passing credentials between
processes using AF_LOCAL sockets. This hack is going to be used with
Secure RPC to duplicate a feature of STREAMS which has no real counterpart
in sockets (with STREAMS/TLI, you can apparently use t_getinfo() to learn
UID of a local process on the other side of a transport endpoint).
What happens is this: the client sets up a sendmsg() call with ancillary
data using the SCM_CREDS socket-level control message type. It does not
need to fill in the structure. When the kernel notices the data,
unp_internalize() fills in the cmesgcred structure with the sending
process' credentials (UID, EUID, GID, and ancillary groups). This data
is later delivered to the receiving process. The receiver can then
perform the follwing tests:
- Did the client send ancillary data?
o Yes, proceed.
o No, refuse to authenticate the client.
- The the client send data of type SCM_CREDS?
o Yes, proceed.
o No, refuse to authenticate the client.
- Is the cmsgcred structure the right size?
o Yes, proceed.
o No, signal a possible error.
The receiver can now inspect the credential information and use it to
authenticate the client.
1997-03-21 16:12:32 +00:00
|
|
|
|
2001-10-04 13:11:48 +00:00
|
|
|
while (cm != NULL) {
|
|
|
|
if (sizeof(*cm) > clen || cm->cmsg_level != SOL_SOCKET
|
|
|
|
|| cm->cmsg_len > clen) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = CMSG_DATA(cm);
|
|
|
|
datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
|
|
|
|
|
|
|
|
switch (cm->cmsg_type) {
|
|
|
|
/*
|
|
|
|
* Fill in credential information.
|
|
|
|
*/
|
|
|
|
case SCM_CREDS:
|
|
|
|
*controlp = sbcreatecontrol(NULL, sizeof(*cmcred),
|
|
|
|
SCM_CREDS, SOL_SOCKET);
|
|
|
|
if (*controlp == NULL) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
cmcred = (struct cmsgcred *)
|
|
|
|
CMSG_DATA(mtod(*controlp, struct cmsghdr *));
|
|
|
|
cmcred->cmcred_pid = p->p_pid;
|
2002-02-27 18:32:23 +00:00
|
|
|
cmcred->cmcred_uid = td->td_ucred->cr_ruid;
|
|
|
|
cmcred->cmcred_gid = td->td_ucred->cr_rgid;
|
|
|
|
cmcred->cmcred_euid = td->td_ucred->cr_uid;
|
|
|
|
cmcred->cmcred_ngroups = MIN(td->td_ucred->cr_ngroups,
|
Add support to sendmsg()/recvmsg() for passing credentials between
processes using AF_LOCAL sockets. This hack is going to be used with
Secure RPC to duplicate a feature of STREAMS which has no real counterpart
in sockets (with STREAMS/TLI, you can apparently use t_getinfo() to learn
UID of a local process on the other side of a transport endpoint).
What happens is this: the client sets up a sendmsg() call with ancillary
data using the SCM_CREDS socket-level control message type. It does not
need to fill in the structure. When the kernel notices the data,
unp_internalize() fills in the cmesgcred structure with the sending
process' credentials (UID, EUID, GID, and ancillary groups). This data
is later delivered to the receiving process. The receiver can then
perform the follwing tests:
- Did the client send ancillary data?
o Yes, proceed.
o No, refuse to authenticate the client.
- The the client send data of type SCM_CREDS?
o Yes, proceed.
o No, refuse to authenticate the client.
- Is the cmsgcred structure the right size?
o Yes, proceed.
o No, signal a possible error.
The receiver can now inspect the credential information and use it to
authenticate the client.
1997-03-21 16:12:32 +00:00
|
|
|
CMGROUP_MAX);
|
2001-10-04 13:11:48 +00:00
|
|
|
for (i = 0; i < cmcred->cmcred_ngroups; i++)
|
|
|
|
cmcred->cmcred_groups[i] =
|
2002-02-27 18:32:23 +00:00
|
|
|
td->td_ucred->cr_groups[i];
|
2001-10-04 13:11:48 +00:00
|
|
|
break;
|
Add support to sendmsg()/recvmsg() for passing credentials between
processes using AF_LOCAL sockets. This hack is going to be used with
Secure RPC to duplicate a feature of STREAMS which has no real counterpart
in sockets (with STREAMS/TLI, you can apparently use t_getinfo() to learn
UID of a local process on the other side of a transport endpoint).
What happens is this: the client sets up a sendmsg() call with ancillary
data using the SCM_CREDS socket-level control message type. It does not
need to fill in the structure. When the kernel notices the data,
unp_internalize() fills in the cmesgcred structure with the sending
process' credentials (UID, EUID, GID, and ancillary groups). This data
is later delivered to the receiving process. The receiver can then
perform the follwing tests:
- Did the client send ancillary data?
o Yes, proceed.
o No, refuse to authenticate the client.
- The the client send data of type SCM_CREDS?
o Yes, proceed.
o No, refuse to authenticate the client.
- Is the cmsgcred structure the right size?
o Yes, proceed.
o No, signal a possible error.
The receiver can now inspect the credential information and use it to
authenticate the client.
1997-03-21 16:12:32 +00:00
|
|
|
|
2001-10-04 13:11:48 +00:00
|
|
|
case SCM_RIGHTS:
|
|
|
|
oldfds = datalen / sizeof (int);
|
|
|
|
/*
|
|
|
|
* check that all the FDs passed in refer to legal files
|
|
|
|
* If not, reject the entire operation.
|
|
|
|
*/
|
|
|
|
fdp = data;
|
2002-01-13 11:58:06 +00:00
|
|
|
FILEDESC_LOCK(fdescp);
|
2001-10-04 13:11:48 +00:00
|
|
|
for (i = 0; i < oldfds; i++) {
|
|
|
|
fd = *fdp++;
|
|
|
|
if ((unsigned)fd >= fdescp->fd_nfiles ||
|
|
|
|
fdescp->fd_ofiles[fd] == NULL) {
|
2002-01-13 11:58:06 +00:00
|
|
|
FILEDESC_UNLOCK(fdescp);
|
2001-10-04 13:11:48 +00:00
|
|
|
error = EBADF;
|
|
|
|
goto out;
|
|
|
|
}
|
2003-02-15 06:04:55 +00:00
|
|
|
fp = fdescp->fd_ofiles[fd];
|
|
|
|
if (!(fp->f_ops->fo_flags & DFLAG_PASSABLE)) {
|
|
|
|
FILEDESC_UNLOCK(fdescp);
|
|
|
|
error = EOPNOTSUPP;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2001-10-04 13:11:48 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Now replace the integer FDs with pointers to
|
|
|
|
* the associated global file table entry..
|
|
|
|
*/
|
|
|
|
newlen = oldfds * sizeof(struct file *);
|
|
|
|
*controlp = sbcreatecontrol(NULL, newlen,
|
|
|
|
SCM_RIGHTS, SOL_SOCKET);
|
|
|
|
if (*controlp == NULL) {
|
2002-01-13 11:58:06 +00:00
|
|
|
FILEDESC_UNLOCK(fdescp);
|
2001-10-04 13:11:48 +00:00
|
|
|
error = E2BIG;
|
|
|
|
goto out;
|
|
|
|
}
|
2000-03-09 15:15:27 +00:00
|
|
|
|
2001-10-04 13:11:48 +00:00
|
|
|
fdp = data;
|
|
|
|
rp = (struct file **)
|
|
|
|
CMSG_DATA(mtod(*controlp, struct cmsghdr *));
|
|
|
|
for (i = 0; i < oldfds; i++) {
|
|
|
|
fp = fdescp->fd_ofiles[*fdp++];
|
|
|
|
*rp++ = fp;
|
2002-01-13 11:58:06 +00:00
|
|
|
FILE_LOCK(fp);
|
2001-10-04 13:11:48 +00:00
|
|
|
fp->f_count++;
|
|
|
|
fp->f_msgcount++;
|
2002-01-13 11:58:06 +00:00
|
|
|
FILE_UNLOCK(fp);
|
2001-10-04 13:11:48 +00:00
|
|
|
unp_rights++;
|
|
|
|
}
|
2002-01-13 11:58:06 +00:00
|
|
|
FILEDESC_UNLOCK(fdescp);
|
2001-10-04 13:11:48 +00:00
|
|
|
break;
|
2000-03-09 15:15:27 +00:00
|
|
|
|
2001-10-04 13:11:48 +00:00
|
|
|
case SCM_TIMESTAMP:
|
|
|
|
*controlp = sbcreatecontrol(NULL, sizeof(*tv),
|
|
|
|
SCM_TIMESTAMP, SOL_SOCKET);
|
|
|
|
if (*controlp == NULL) {
|
|
|
|
error = ENOBUFS;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
tv = (struct timeval *)
|
|
|
|
CMSG_DATA(mtod(*controlp, struct cmsghdr *));
|
|
|
|
microtime(tv);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
goto out;
|
2000-03-09 15:15:27 +00:00
|
|
|
}
|
2001-10-04 13:11:48 +00:00
|
|
|
|
|
|
|
controlp = &(*controlp)->m_next;
|
|
|
|
|
|
|
|
if (CMSG_SPACE(datalen) < clen) {
|
|
|
|
clen -= CMSG_SPACE(datalen);
|
|
|
|
cm = (struct cmsghdr *)
|
|
|
|
((caddr_t)cm + CMSG_SPACE(datalen));
|
|
|
|
} else {
|
|
|
|
clen = 0;
|
|
|
|
cm = NULL;
|
2000-03-09 15:15:27 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2001-10-04 13:11:48 +00:00
|
|
|
|
|
|
|
out:
|
|
|
|
m_freem(control);
|
|
|
|
|
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1995-12-14 09:55:16 +00:00
|
|
|
static int unp_defer, unp_gcing;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1995-12-14 09:55:16 +00:00
|
|
|
static void
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_gc()
|
|
|
|
{
|
|
|
|
register struct file *fp, *nextfp;
|
|
|
|
register struct socket *so;
|
|
|
|
struct file **extra_ref, **fpp;
|
|
|
|
int nunref, i;
|
|
|
|
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK_ASSERT();
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
if (unp_gcing)
|
|
|
|
return;
|
|
|
|
unp_gcing = 1;
|
|
|
|
unp_defer = 0;
|
2004-01-11 19:48:19 +00:00
|
|
|
/*
|
|
|
|
* before going through all this, set all FDs to
|
1996-12-05 22:41:13 +00:00
|
|
|
* be NOT defered and NOT externally accessible
|
|
|
|
*/
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
/*
|
|
|
|
* XXXRW: Acquiring a sleep lock while holding UNP
|
|
|
|
* mutex cannot be a good thing.
|
|
|
|
*/
|
2002-01-13 11:58:06 +00:00
|
|
|
sx_slock(&filelist_lock);
|
1999-11-16 10:56:05 +00:00
|
|
|
LIST_FOREACH(fp, &filehead, f_list)
|
2002-01-13 11:58:06 +00:00
|
|
|
fp->f_gcflag &= ~(FMARK|FDEFER);
|
1994-05-24 10:09:53 +00:00
|
|
|
do {
|
1999-11-16 10:56:05 +00:00
|
|
|
LIST_FOREACH(fp, &filehead, f_list) {
|
2002-01-13 11:58:06 +00:00
|
|
|
FILE_LOCK(fp);
|
1996-12-05 22:41:13 +00:00
|
|
|
/*
|
|
|
|
* If the file is not open, skip it
|
|
|
|
*/
|
2002-01-13 11:58:06 +00:00
|
|
|
if (fp->f_count == 0) {
|
|
|
|
FILE_UNLOCK(fp);
|
1994-05-24 10:09:53 +00:00
|
|
|
continue;
|
2002-01-13 11:58:06 +00:00
|
|
|
}
|
1996-12-05 22:41:13 +00:00
|
|
|
/*
|
|
|
|
* If we already marked it as 'defer' in a
|
|
|
|
* previous pass, then try process it this time
|
|
|
|
* and un-mark it
|
|
|
|
*/
|
2002-01-13 11:58:06 +00:00
|
|
|
if (fp->f_gcflag & FDEFER) {
|
|
|
|
fp->f_gcflag &= ~FDEFER;
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_defer--;
|
|
|
|
} else {
|
1996-12-05 22:41:13 +00:00
|
|
|
/*
|
|
|
|
* if it's not defered, then check if it's
|
|
|
|
* already marked.. if so skip it
|
|
|
|
*/
|
2002-01-13 11:58:06 +00:00
|
|
|
if (fp->f_gcflag & FMARK) {
|
|
|
|
FILE_UNLOCK(fp);
|
1994-05-24 10:09:53 +00:00
|
|
|
continue;
|
2002-01-13 11:58:06 +00:00
|
|
|
}
|
2004-01-11 19:48:19 +00:00
|
|
|
/*
|
1996-12-05 22:41:13 +00:00
|
|
|
* If all references are from messages
|
2004-01-11 19:48:19 +00:00
|
|
|
* in transit, then skip it. it's not
|
1996-12-05 22:41:13 +00:00
|
|
|
* externally accessible.
|
2004-01-11 19:48:19 +00:00
|
|
|
*/
|
2002-01-13 11:58:06 +00:00
|
|
|
if (fp->f_count == fp->f_msgcount) {
|
|
|
|
FILE_UNLOCK(fp);
|
1994-05-24 10:09:53 +00:00
|
|
|
continue;
|
2002-01-13 11:58:06 +00:00
|
|
|
}
|
2004-01-11 19:48:19 +00:00
|
|
|
/*
|
1996-12-05 22:41:13 +00:00
|
|
|
* If it got this far then it must be
|
|
|
|
* externally accessible.
|
|
|
|
*/
|
2002-01-13 11:58:06 +00:00
|
|
|
fp->f_gcflag |= FMARK;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
1996-12-05 22:41:13 +00:00
|
|
|
/*
|
2004-01-11 19:48:19 +00:00
|
|
|
* either it was defered, or it is externally
|
1996-12-05 22:41:13 +00:00
|
|
|
* accessible and not already marked so.
|
|
|
|
* Now check if it is possibly one of OUR sockets.
|
2004-01-11 19:48:19 +00:00
|
|
|
*/
|
1994-05-24 10:09:53 +00:00
|
|
|
if (fp->f_type != DTYPE_SOCKET ||
|
2003-01-13 00:33:17 +00:00
|
|
|
(so = fp->f_data) == NULL) {
|
2002-01-13 11:58:06 +00:00
|
|
|
FILE_UNLOCK(fp);
|
1994-05-24 10:09:53 +00:00
|
|
|
continue;
|
2002-01-13 11:58:06 +00:00
|
|
|
}
|
|
|
|
FILE_UNLOCK(fp);
|
1995-05-11 00:13:26 +00:00
|
|
|
if (so->so_proto->pr_domain != &localdomain ||
|
1994-05-24 10:09:53 +00:00
|
|
|
(so->so_proto->pr_flags&PR_RIGHTS) == 0)
|
|
|
|
continue;
|
|
|
|
#ifdef notdef
|
|
|
|
if (so->so_rcv.sb_flags & SB_LOCK) {
|
|
|
|
/*
|
|
|
|
* This is problematical; it's not clear
|
|
|
|
* we need to wait for the sockbuf to be
|
|
|
|
* unlocked (on a uniprocessor, at least),
|
|
|
|
* and it's also not clear what to do
|
|
|
|
* if sbwait returns an error due to receipt
|
|
|
|
* of a signal. If sbwait does return
|
|
|
|
* an error, we'll go into an infinite
|
|
|
|
* loop. Delete all of this for now.
|
|
|
|
*/
|
|
|
|
(void) sbwait(&so->so_rcv);
|
|
|
|
goto restart;
|
|
|
|
}
|
|
|
|
#endif
|
1996-12-05 22:41:13 +00:00
|
|
|
/*
|
|
|
|
* So, Ok, it's one of our sockets and it IS externally
|
|
|
|
* accessible (or was defered). Now we look
|
1998-04-17 22:37:19 +00:00
|
|
|
* to see if we hold any file descriptors in its
|
2004-01-11 19:48:19 +00:00
|
|
|
* message buffers. Follow those links and mark them
|
1996-12-05 22:41:13 +00:00
|
|
|
* as accessible too.
|
|
|
|
*/
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_scan(so->so_rcv.sb_mb, unp_mark);
|
|
|
|
}
|
|
|
|
} while (unp_defer);
|
2002-01-13 11:58:06 +00:00
|
|
|
sx_sunlock(&filelist_lock);
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* We grab an extra reference to each of the file table entries
|
|
|
|
* that are not otherwise accessible and then free the rights
|
|
|
|
* that are stored in messages on them.
|
|
|
|
*
|
|
|
|
* The bug in the orginal code is a little tricky, so I'll describe
|
|
|
|
* what's wrong with it here.
|
|
|
|
*
|
|
|
|
* It is incorrect to simply unp_discard each entry for f_msgcount
|
|
|
|
* times -- consider the case of sockets A and B that contain
|
|
|
|
* references to each other. On a last close of some other socket,
|
|
|
|
* we trigger a gc since the number of outstanding rights (unp_rights)
|
|
|
|
* is non-zero. If during the sweep phase the gc code un_discards,
|
|
|
|
* we end up doing a (full) closef on the descriptor. A closef on A
|
|
|
|
* results in the following chain. Closef calls soo_close, which
|
|
|
|
* calls soclose. Soclose calls first (through the switch
|
|
|
|
* uipc_usrreq) unp_detach, which re-invokes unp_gc. Unp_gc simply
|
|
|
|
* returns because the previous instance had set unp_gcing, and
|
|
|
|
* we return all the way back to soclose, which marks the socket
|
|
|
|
* with SS_NOFDREF, and then calls sofree. Sofree calls sorflush
|
|
|
|
* to free up the rights that are queued in messages on the socket A,
|
|
|
|
* i.e., the reference on B. The sorflush calls via the dom_dispose
|
|
|
|
* switch unp_dispose, which unp_scans with unp_discard. This second
|
|
|
|
* instance of unp_discard just calls closef on B.
|
|
|
|
*
|
|
|
|
* Well, a similar chain occurs on B, resulting in a sorflush on B,
|
|
|
|
* which results in another closef on A. Unfortunately, A is already
|
|
|
|
* being closed, and the descriptor has already been marked with
|
|
|
|
* SS_NOFDREF, and soclose panics at this point.
|
|
|
|
*
|
|
|
|
* Here, we first take an extra reference to each inaccessible
|
|
|
|
* descriptor. Then, we call sorflush ourself, since we know
|
|
|
|
* it is a Unix domain socket anyhow. After we destroy all the
|
|
|
|
* rights carried in messages, we do a last closef to get rid
|
|
|
|
* of our extra reference. This is the last close, and the
|
|
|
|
* unp_detach etc will shut down the socket.
|
|
|
|
*
|
|
|
|
* 91/09/19, bsy@cs.cmu.edu
|
|
|
|
*/
|
2003-02-19 05:47:46 +00:00
|
|
|
extra_ref = malloc(nfiles * sizeof(struct file *), M_TEMP, M_WAITOK);
|
2002-01-13 11:58:06 +00:00
|
|
|
sx_slock(&filelist_lock);
|
2004-03-30 02:16:25 +00:00
|
|
|
for (nunref = 0, fp = LIST_FIRST(&filehead), fpp = extra_ref;
|
|
|
|
fp != NULL; fp = nextfp) {
|
1999-11-16 10:56:05 +00:00
|
|
|
nextfp = LIST_NEXT(fp, f_list);
|
2002-01-13 11:58:06 +00:00
|
|
|
FILE_LOCK(fp);
|
2004-01-11 19:48:19 +00:00
|
|
|
/*
|
1996-12-05 22:41:13 +00:00
|
|
|
* If it's not open, skip it
|
|
|
|
*/
|
2002-01-13 11:58:06 +00:00
|
|
|
if (fp->f_count == 0) {
|
|
|
|
FILE_UNLOCK(fp);
|
1994-05-24 10:09:53 +00:00
|
|
|
continue;
|
2002-01-13 11:58:06 +00:00
|
|
|
}
|
2004-01-11 19:48:19 +00:00
|
|
|
/*
|
1996-12-05 22:41:13 +00:00
|
|
|
* If all refs are from msgs, and it's not marked accessible
|
|
|
|
* then it must be referenced from some unreachable cycle
|
|
|
|
* of (shut-down) FDs, so include it in our
|
|
|
|
* list of FDs to remove
|
|
|
|
*/
|
2002-01-13 11:58:06 +00:00
|
|
|
if (fp->f_count == fp->f_msgcount && !(fp->f_gcflag & FMARK)) {
|
1994-05-24 10:09:53 +00:00
|
|
|
*fpp++ = fp;
|
|
|
|
nunref++;
|
|
|
|
fp->f_count++;
|
|
|
|
}
|
2002-01-13 11:58:06 +00:00
|
|
|
FILE_UNLOCK(fp);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2002-01-13 11:58:06 +00:00
|
|
|
sx_sunlock(&filelist_lock);
|
2004-01-11 19:48:19 +00:00
|
|
|
/*
|
1996-12-05 22:41:13 +00:00
|
|
|
* for each FD on our hit list, do the following two things
|
|
|
|
*/
|
1999-01-21 08:29:12 +00:00
|
|
|
for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) {
|
|
|
|
struct file *tfp = *fpp;
|
2002-01-13 11:58:06 +00:00
|
|
|
FILE_LOCK(tfp);
|
2003-01-12 01:37:13 +00:00
|
|
|
if (tfp->f_type == DTYPE_SOCKET &&
|
2003-01-13 00:33:17 +00:00
|
|
|
tfp->f_data != NULL) {
|
2002-01-13 11:58:06 +00:00
|
|
|
FILE_UNLOCK(tfp);
|
2003-01-13 00:33:17 +00:00
|
|
|
sorflush(tfp->f_data);
|
2004-01-11 19:48:19 +00:00
|
|
|
} else {
|
2002-01-13 11:58:06 +00:00
|
|
|
FILE_UNLOCK(tfp);
|
2004-01-11 19:48:19 +00:00
|
|
|
}
|
1999-01-21 08:29:12 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp)
|
2001-09-12 08:38:13 +00:00
|
|
|
closef(*fpp, (struct thread *) NULL);
|
2002-06-28 23:17:36 +00:00
|
|
|
free(extra_ref, M_TEMP);
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_gcing = 0;
|
|
|
|
}
|
|
|
|
|
1994-05-25 09:21:21 +00:00
|
|
|
void
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_dispose(m)
|
|
|
|
struct mbuf *m;
|
|
|
|
{
|
1997-02-10 02:22:35 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
if (m)
|
|
|
|
unp_scan(m, unp_discard);
|
|
|
|
}
|
|
|
|
|
2001-08-17 22:01:18 +00:00
|
|
|
static int
|
2002-02-27 19:14:01 +00:00
|
|
|
unp_listen(unp, td)
|
2001-08-17 22:01:18 +00:00
|
|
|
struct unpcb *unp;
|
2002-02-27 19:14:01 +00:00
|
|
|
struct thread *td;
|
2001-08-17 22:01:18 +00:00
|
|
|
{
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
UNP_LOCK_ASSERT();
|
2001-08-17 22:01:18 +00:00
|
|
|
|
Introduce a subsystem lock around UNIX domain sockets in order to protect
global and allocated variables. This strategy is derived from work
originally developed by BSDi for BSD/OS, and applied to FreeBSD by Sam
Leffler:
- Add unp_mtx, a global mutex which will protect all UNIX domain socket
related variables, structures, etc.
- Add UNP_LOCK(), UNP_UNLOCK(), UNP_LOCK_ASSERT() macros.
- Acquire unp_mtx on entering most UNIX domain socket code,
drop/re-acquire around calls into VFS, and release it on return.
- Avoid performing sodupsockaddr() while holding the mutex, so in general
move to allocating storage before acquiring the mutex to copy the data.
- Make a stack copy of the xucred rather than copying out while holding
unp_mtx. Copy the peer credential out after releasing the mutex.
- Add additional assertions of vnode locks following VOP_CREATE().
A few notes:
- Use of an sx lock for the file list mutex may cause problems with regard
to unp_mtx when garbage collection passed file descriptors.
- The locking in unp_pcblist() for sysctl monitoring is correct subject to
the unpcb zone not returning memory for reuse by other subsystems
(consistent with similar existing concerns).
- Sam's version of this change, as with the BSD/OS version, made use of
both a global lock and per-unpcb locks. However, in practice, the
global lock covered all accesses, so I have simplified out the unpcb
locks in the interest of getting this merged faster (reducing the
overhead but not sacrificing granularity in most cases). We will want
to explore possibilities for improving lock granularity in this code in
the future.
Submitted by: sam
Sponsored by: FreeBSD Foundatiuon
Obtained from: BSD/OS 5 snapshot provided by BSDi
2004-06-10 21:34:38 +00:00
|
|
|
/*
|
|
|
|
* XXXRW: Why populate the local peer cred with our own credential?
|
|
|
|
*/
|
2002-02-27 19:14:01 +00:00
|
|
|
cru2x(td->td_ucred, &unp->unp_peercred);
|
2001-08-17 22:01:18 +00:00
|
|
|
unp->unp_flags |= UNP_HAVEPCCACHED;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1995-12-14 09:55:16 +00:00
|
|
|
static void
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_scan(m0, op)
|
|
|
|
register struct mbuf *m0;
|
2002-03-19 21:25:46 +00:00
|
|
|
void (*op)(struct file *);
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2001-10-04 13:11:48 +00:00
|
|
|
struct mbuf *m;
|
|
|
|
struct file **rp;
|
|
|
|
struct cmsghdr *cm;
|
|
|
|
void *data;
|
|
|
|
int i;
|
|
|
|
socklen_t clen, datalen;
|
1994-05-24 10:09:53 +00:00
|
|
|
int qfds;
|
|
|
|
|
2004-03-30 02:16:25 +00:00
|
|
|
while (m0 != NULL) {
|
2001-10-04 13:11:48 +00:00
|
|
|
for (m = m0; m; m = m->m_next) {
|
2001-10-29 20:04:03 +00:00
|
|
|
if (m->m_type != MT_CONTROL)
|
2001-10-04 13:11:48 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
cm = mtod(m, struct cmsghdr *);
|
|
|
|
clen = m->m_len;
|
|
|
|
|
|
|
|
while (cm != NULL) {
|
|
|
|
if (sizeof(*cm) > clen || cm->cmsg_len > clen)
|
|
|
|
break;
|
|
|
|
|
|
|
|
data = CMSG_DATA(cm);
|
|
|
|
datalen = (caddr_t)cm + cm->cmsg_len
|
|
|
|
- (caddr_t)data;
|
|
|
|
|
|
|
|
if (cm->cmsg_level == SOL_SOCKET &&
|
|
|
|
cm->cmsg_type == SCM_RIGHTS) {
|
|
|
|
qfds = datalen / sizeof (struct file *);
|
|
|
|
rp = data;
|
|
|
|
for (i = 0; i < qfds; i++)
|
|
|
|
(*op)(*rp++);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CMSG_SPACE(datalen) < clen) {
|
|
|
|
clen -= CMSG_SPACE(datalen);
|
|
|
|
cm = (struct cmsghdr *)
|
|
|
|
((caddr_t)cm + CMSG_SPACE(datalen));
|
|
|
|
} else {
|
|
|
|
clen = 0;
|
|
|
|
cm = NULL;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2001-10-04 13:11:48 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
m0 = m0->m_act;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1995-12-14 09:55:16 +00:00
|
|
|
static void
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_mark(fp)
|
|
|
|
struct file *fp;
|
|
|
|
{
|
2002-01-13 11:58:06 +00:00
|
|
|
if (fp->f_gcflag & FMARK)
|
1994-05-24 10:09:53 +00:00
|
|
|
return;
|
|
|
|
unp_defer++;
|
2002-01-13 11:58:06 +00:00
|
|
|
fp->f_gcflag |= (FMARK|FDEFER);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1995-12-14 09:55:16 +00:00
|
|
|
static void
|
1994-05-24 10:09:53 +00:00
|
|
|
unp_discard(fp)
|
|
|
|
struct file *fp;
|
|
|
|
{
|
2002-01-13 11:58:06 +00:00
|
|
|
FILE_LOCK(fp);
|
1994-05-24 10:09:53 +00:00
|
|
|
fp->f_msgcount--;
|
|
|
|
unp_rights--;
|
2002-01-13 11:58:06 +00:00
|
|
|
FILE_UNLOCK(fp);
|
2001-09-12 08:38:13 +00:00
|
|
|
(void) closef(fp, (struct thread *)NULL);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|