Author: pjd
Date: Mon Mar 11 22:59:07 2013
New Revision: 248176
URL: http://svnweb.freebsd.org/changeset/base/248176

Log:
  Fix memory leak when one process send descriptor over UNIX domain socket,
  but the other process exited before receiving it.

Modified:
  head/sys/kern/uipc_usrreq.c

Modified: head/sys/kern/uipc_usrreq.c
==============================================================================
--- head/sys/kern/uipc_usrreq.c Mon Mar 11 22:17:39 2013        (r248175)
+++ head/sys/kern/uipc_usrreq.c Mon Mar 11 22:59:07 2013        (r248176)
@@ -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)(str
 
                                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) {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to