Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-3-0]: src/sys Apply patch (requested by mlelstv in ticket #2004):



details:   https://anonhg.NetBSD.org/src/rev/bd9f1e4ac512
branches:  netbsd-3-0
changeset: 579525:bd9f1e4ac512
user:      snj <snj%NetBSD.org@localhost>
date:      Sat Apr 11 06:21:23 2009 +0000

description:
Apply patch (requested by mlelstv in ticket #2004):
Avoid deep recursion and file descriptor exhaustion.
1. unp_detach: go not call unp_gc directly for descriptors
that are unixdomain sockets themselves. Instead mark them
for cleanup during garbage collection.
2. unp_gc: handle detach of descriptors that were marked earlier.
3. prohibit transfer of descriptors within SCM_RIGHTS messages if
(num_files_in_transit > maxfiles / unp_rights_ratio)

diffstat:

 sys/kern/uipc_usrreq.c |  38 ++++++++++++++++++++++++++++++++++++--
 sys/sys/file.h         |   5 +++--
 2 files changed, 39 insertions(+), 4 deletions(-)

diffs (116 lines):

diff -r 4effea748c3e -r bd9f1e4ac512 sys/kern/uipc_usrreq.c
--- a/sys/kern/uipc_usrreq.c    Fri Mar 27 10:45:16 2009 +0000
+++ b/sys/kern/uipc_usrreq.c    Sat Apr 11 06:21:23 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uipc_usrreq.c,v 1.80.2.1.2.1 2007/08/26 20:27:40 bouyer Exp $  */
+/*     $NetBSD: uipc_usrreq.c,v 1.80.2.1.2.2 2009/04/11 06:21:23 snj Exp $     */
 
 /*-
  * Copyright (c) 1998, 2000, 2004 The NetBSD Foundation, Inc.
@@ -103,7 +103,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.80.2.1.2.1 2007/08/26 20:27:40 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.80.2.1.2.2 2009/04/11 06:21:23 snj Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -523,6 +523,7 @@
 u_long unpdg_recvspace = 4*1024;
 
 int    unp_rights;                     /* file descriptors in flight */
+int    unp_rights_ratio = 2;           /* limit, fraction of maxfiles */
 
 int
 unp_attach(struct socket *so)
@@ -959,6 +960,7 @@
        int i, fd, *fdp;
        int nfds;
        u_int neededspace;
+       u_int maxmsg;
 
        /* Sanity check the control message header */
        if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET ||
@@ -967,6 +969,11 @@
 
        /* Verify that the file descriptors are valid */
        nfds = (cm->cmsg_len - CMSG_ALIGN(sizeof(*cm))) / sizeof(int);
+
+       maxmsg = maxfiles / unp_rights_ratio;
+       if (unp_rights + nfds > maxmsg)
+               return (EAGAIN);
+
        fdp = (int *)CMSG_DATA(cm);
        for (i = 0; i < nfds; i++) {
                fd = *fdp++;
@@ -1150,6 +1157,8 @@
                                if (fp->f_count == fp->f_msgcount)
                                        continue;
                        }
+                       if (fp->f_iflags & FIF_DISCARDED)
+                               continue;
                        fp->f_flag |= FMARK;
 
                        if (fp->f_type != DTYPE_SOCKET ||
@@ -1255,6 +1264,14 @@
        for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) {
                fp = *fpp;
                simple_lock(&fp->f_slock);
+               if (fp->f_iflags & FIF_DISCARDED) {
+                       fp->f_usecount++;
+                       fp->f_msgcount--;
+                       simple_unlock(&fp->f_slock);
+                       unp_rights--;
+                       (void) closef(fp, (struct lwp *)0);
+                       simple_lock(&fp->f_slock);
+               }
                FILE_USE(fp);
                (void) closef(fp, (struct proc *)0);
        }
@@ -1339,7 +1356,24 @@
 {
        if (fp == NULL)
                return;
+
        simple_lock(&fp->f_slock);
+       /*
+        * closing unix domain sockets may cause a deep
+        * recursion, so leave them open and mark them
+        * for the garbage collector to discard them safely.
+        */
+       if (fp->f_type == DTYPE_SOCKET && fp->f_count == 1) {
+               struct socket *so;
+
+               so = (struct socket *)fp->f_data;
+               if (so && so->so_proto->pr_domain == &unixdomain &&
+                   (so->so_proto->pr_flags&PR_RIGHTS) != 0) {
+                       fp->f_iflags |= FIF_DISCARDED;
+                       simple_unlock(&fp->f_slock);
+                       return;
+               }
+       }
        fp->f_usecount++;       /* i.e. FILE_USE(fp) sans locking */
        fp->f_msgcount--;
        simple_unlock(&fp->f_slock);
diff -r 4effea748c3e -r bd9f1e4ac512 sys/sys/file.h
--- a/sys/sys/file.h    Fri Mar 27 10:45:16 2009 +0000
+++ b/sys/sys/file.h    Sat Apr 11 06:21:23 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: file.h,v 1.53 2005/02/12 23:14:03 christos Exp $       */
+/*     $NetBSD: file.h,v 1.53.14.1 2009/04/11 06:21:23 snj Exp $       */
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -94,9 +94,10 @@
 
 #define        FIF_WANTCLOSE           0x01    /* a close is waiting for usecount */
 #define        FIF_LARVAL              0x02    /* not fully constructed; don't use */
+#define        FIF_DISCARDED           0x04    /* file is discarded, pending close */
 
 #define        FILE_IS_USABLE(fp)      (((fp)->f_iflags &                      \
-                                 (FIF_WANTCLOSE|FIF_LARVAL)) == 0)
+                       (FIF_WANTCLOSE|FIF_LARVAL|FIF_DISCARDED)) == 0)
 
 #define        FILE_SET_MATURE(fp)                                             \
 do {                                                                   \



Home | Main Index | Thread Index | Old Index