diff options
author | pjd <pjd@FreeBSD.org> | 2013-03-11 22:59:07 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2013-03-11 22:59:07 +0000 |
commit | 46a0405f64ba3ae10cbd811634ab9ac86db2f0de (patch) | |
tree | 820958955c3f7d2fcdbaf4245f12692227ab03b5 | |
parent | 842239b44ef849e3cc1c7fae706f077a5c462c28 (diff) | |
download | FreeBSD-src-46a0405f64ba3ae10cbd811634ab9ac86db2f0de.zip FreeBSD-src-46a0405f64ba3ae10cbd811634ab9ac86db2f0de.tar.gz |
Fix memory leak when one process send descriptor over UNIX domain socket,
but the other process exited before receiving it.
-rw-r--r-- | sys/kern/uipc_usrreq.c | 36 |
1 files changed, 18 insertions, 18 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index dcd8c4e..2ec83c5 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -282,7 +282,7 @@ static void unp_dispose(struct mbuf *); static void unp_shutdown(struct unpcb *); static void unp_drop(struct unpcb *, int); static void unp_gc(__unused void *, int); -static void unp_scan(struct mbuf *, void (*)(struct file *)); +static void unp_scan(struct mbuf *, void (*)(struct filedescent **, int)); static void unp_discard(struct file *); static void unp_freerights(struct filedescent **, int); static void unp_init(void); @@ -2135,17 +2135,22 @@ static int unp_marked; static int unp_unreachable; static void -unp_accessable(struct file *fp) +unp_accessable(struct filedescent **fdep, int fdcount) { struct unpcb *unp; + struct file *fp; + int i; - if ((unp = fptounp(fp)) == NULL) - return; - if (unp->unp_gcflag & UNPGC_REF) - return; - unp->unp_gcflag &= ~UNPGC_DEAD; - unp->unp_gcflag |= UNPGC_REF; - unp_marked++; + for (i = 0; i < fdcount; i++) { + fp = fdep[i]->fde_file; + if ((unp = fptounp(fp)) == NULL) + continue; + if (unp->unp_gcflag & UNPGC_REF) + continue; + unp->unp_gcflag &= ~UNPGC_DEAD; + unp->unp_gcflag |= UNPGC_REF; + unp_marked++; + } } static void @@ -2292,19 +2297,16 @@ unp_dispose(struct mbuf *m) { if (m) - unp_scan(m, unp_discard); + unp_scan(m, unp_freerights); } static void -unp_scan(struct mbuf *m0, void (*op)(struct file *)) +unp_scan(struct mbuf *m0, void (*op)(struct filedescent **, int)) { struct mbuf *m; - struct filedescent **fdep; struct cmsghdr *cm; void *data; - int i; socklen_t clen, datalen; - int qfds; while (m0 != NULL) { for (m = m0; m; m = m->m_next) { @@ -2324,10 +2326,8 @@ unp_scan(struct mbuf *m0, void (*op)(struct file *)) if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS) { - qfds = datalen / sizeof(*fdep); - fdep = data; - for (i = 0; i < qfds; i++) - (*op)(fdep[i]->fde_file); + (*op)(data, datalen / + sizeof(struct filedescent *)); } if (CMSG_SPACE(datalen) < clen) { |