Page MenuHomeFreeBSD

D3044.id6832.diff
No OneTemporary

D3044.id6832.diff

Index: sys/kern/uipc_debug.c
===================================================================
--- sys/kern/uipc_debug.c
+++ sys/kern/uipc_debug.c
@@ -248,6 +248,7 @@
db_printf("dom_init: %p ", d->dom_init);
db_printf("dom_externalize: %p ", d->dom_externalize);
db_printf("dom_dispose: %p\n", d->dom_dispose);
+ db_printf("dom_dispose2: %p\n", d->dom_dispose2);
db_print_indent(indent);
db_printf("dom_protosw: %p ", d->dom_protosw);
Index: sys/kern/uipc_socket.c
===================================================================
--- sys/kern/uipc_socket.c
+++ sys/kern/uipc_socket.c
@@ -804,8 +804,12 @@
ACCEPT_UNLOCK();
VNET_SO_ASSERT(so);
- if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose != NULL)
- (*pr->pr_domain->dom_dispose)(so->so_rcv.sb_mb);
+ if (pr->pr_flags & PR_RIGHTS) {
+ if (pr->pr_domain->dom_dispose2 != NULL)
+ (*pr->pr_domain->dom_dispose2)(so);
+ else if (pr->pr_domain->dom_dispose != NULL)
+ (*pr->pr_domain->dom_dispose)(so->so_rcv.sb_mb);
+ }
if (pr->pr_usrreqs->pru_detach != NULL)
(*pr->pr_usrreqs->pru_detach)(so);
@@ -2393,8 +2397,12 @@
* Dispose of special rights and flush the socket buffer. Don't call
* any unsafe routines (that rely on locks being initialized) on asb.
*/
- if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose != NULL)
- (*pr->pr_domain->dom_dispose)(asb.sb_mb);
+ if (pr->pr_flags & PR_RIGHTS) {
+ if (pr->pr_domain->dom_dispose2 != NULL)
+ (*pr->pr_domain->dom_dispose2)(so);
+ else if (pr->pr_domain->dom_dispose != NULL)
+ (*pr->pr_domain->dom_dispose)(so->so_rcv.sb_mb);
+ }
sbrelease_internal(&asb, so);
}
Index: sys/kern/uipc_usrreq.c
===================================================================
--- sys/kern/uipc_usrreq.c
+++ sys/kern/uipc_usrreq.c
@@ -278,6 +278,7 @@
static int unp_connect2(struct socket *so, struct socket *so2, int);
static void unp_disconnect(struct unpcb *unp, struct unpcb *unp2);
static void unp_dispose(struct mbuf *);
+static void unp_dispose2(struct socket *so);
static void unp_shutdown(struct unpcb *);
static void unp_drop(struct unpcb *, int);
static void unp_gc(__unused void *, int);
@@ -334,7 +335,7 @@
.dom_name = "local",
.dom_init = unp_init,
.dom_externalize = unp_externalize,
- .dom_dispose = unp_dispose,
+ .dom_dispose2 = unp_dispose2,
.dom_protosw = localsw,
.dom_protoswNPROTOSW = &localsw[sizeof(localsw)/sizeof(localsw[0])]
};
@@ -2193,8 +2194,7 @@
struct socket *so;
struct file *fp;
- /* Already processed. */
- if (unp->unp_gcflag & UNPGC_SCANNED)
+ if (unp->unp_gcflag & (UNPGC_SCANNED | UNPGC_IGNORE))
return;
fp = unp->unp_file;
@@ -2252,11 +2252,11 @@
unp_taskcount++;
UNP_LIST_LOCK();
/*
- * First clear all gc flags from previous runs.
+ * First clear all gc flags from previous runs, apart from UNPGC_IGNORE.
*/
for (head = heads; *head != NULL; head++)
LIST_FOREACH(unp, *head, unp_link)
- unp->unp_gcflag = 0;
+ unp->unp_gcflag = unp->unp_gcflag & UNPGC_IGNORE;
/*
* Scan marking all reachable sockets with UNPGC_REF. Once a socket
@@ -2333,6 +2333,21 @@
unp_scan(m, unp_freerights);
}
+/*
+ * Synchronize against unp_gc, which can trip over data as we are freeing it.
+ */
+static void
+unp_dispose2(struct socket *so)
+{
+ struct unpcb *unp;
+
+ unp = sotounpcb(so);
+ UNP_LIST_LOCK();
+ unp->unp_gcflag |= UNPGC_IGNORE;
+ UNP_LIST_UNLOCK();
+ unp_dispose(so->so_rcv.sb_mb);
+}
+
static void
unp_scan(struct mbuf *m0, void (*op)(struct filedescent **, int))
{
Index: sys/sys/domain.h
===================================================================
--- sys/sys/domain.h
+++ sys/sys/domain.h
@@ -42,6 +42,7 @@
*/
struct mbuf;
struct ifnet;
+struct socket;
struct domain {
int dom_family; /* AF_xxx */
@@ -54,6 +55,8 @@
(struct mbuf *, struct mbuf **, int);
void (*dom_dispose) /* dispose of internalized rights */
(struct mbuf *);
+ void (*dom_dispose2) /* same, but takes socket */
+ (struct socket *);
struct protosw *dom_protosw, *dom_protoswNPROTOSW;
struct domain *dom_next;
int (*dom_rtattach) /* initialize routing table */
Index: sys/sys/unpcb.h
===================================================================
--- sys/sys/unpcb.h
+++ sys/sys/unpcb.h
@@ -106,6 +106,7 @@
#define UNPGC_REF 0x1 /* unpcb has external ref. */
#define UNPGC_DEAD 0x2 /* unpcb might be dead. */
#define UNPGC_SCANNED 0x4 /* Has been scanned. */
+#define UNPGC_IGNORE 0x4 /* Someone will clear it. */
/*
* These flags are used to handle non-atomicity in connect() and bind()

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 25, 5:31 PM (14 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30336855
Default Alt Text
D3044.id6832.diff (4 KB)

Event Timeline