Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F149477506
D3044.id6832.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D3044.id6832.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D3044: PR 194264: Fix race between unp_dispose and unp_gc
Attached
Detach File
Event Timeline
Log In to Comment