]> git.sesse.net Git - vlc/commitdiff
Whenever using select() companion macro FD_SET(), one must ensure that
authorRémi Denis-Courmont <rem@videolan.org>
Thu, 27 Apr 2006 20:18:14 +0000 (20:18 +0000)
committerRémi Denis-Courmont <rem@videolan.org>
Thu, 27 Apr 2006 20:18:14 +0000 (20:18 +0000)
the specified file descriptor does not exceeds the fd_set limit (FD_SETSIZE).
Registering a file descriptor above this limit is not defined (read: this is
a buffer overflow).

This is not normally exploitable on Linux because FD_SETSIZE equals the
default limit for file descriptors per processes, but should work on BSDs.
Cygwin is also very prone to this problem (but right, we don't use it). As
for Windows, it will overflow if you try to select() more than 64 sockets at
a time (regardless of the total numbers of socket), but for the sake of
simplicity and portability, this patch actually prevent opening more than
64 sockets at all.

There are still quite a bunch of plugins that needs fixing.

modules/access/file.c
src/network/httpd.c
src/network/io.c
src/network/tcp.c

index 345c3ca9093e55312281c20bdab226849ccff90d..c55e0ba7709e422418865e3bbc39af57e6442e75 100644 (file)
@@ -623,8 +623,20 @@ static int _OpenFile( access_t * p_access, const char * psz_name )
         return VLC_EGENERIC;
     }
 
+    // FIXME: support non-ANSI filenames on Win32
     p_sys->fd = open( psz_localname, O_NONBLOCK /*| O_LARGEFILE*/ );
     LocaleFree( psz_localname );
+
+#ifndef WIN32
+    if( p_sys->fd >= FD_SETSIZE )
+    {
+        // Avoid overflowing fd_set
+        close( p_sys->fd );
+        p_sys->fd = -1;
+        errno = EMFILE;
+    }
+#endif
+
     if ( p_sys->fd == -1 )
     {
         msg_Err( p_access, "cannot open file %s (%s)", psz_name,
index e54bcca244c9ee504264dbb04de8dd9c2bb16289..1cda10a4116f1f7e289e8f031b4826fdf85c6322 100644 (file)
@@ -2435,7 +2435,14 @@ static void httpd_HostThread( httpd_host_t *host )
                 socklen_t i_sock_size = sizeof( struct sockaddr_storage );
                 struct  sockaddr_storage sock;
 
+                // FIXME: use net_Accept()
                 fd = accept( fd, (struct sockaddr *)&sock, &i_sock_size );
+                if( fd >= FD_SETSIZE )
+                {
+                    net_Close( fd );
+                    fd = -1;
+                }
+
                 if( fd >= 0 )
                 {
                     int i_state = 0;
index 8266081fd1d25c23b5c852c1c49d0279a3779d39..3349b67c343301f482c2e173e3fcc9e368b2fb29 100644 (file)
@@ -69,7 +69,14 @@ int net_Socket( vlc_object_t *p_this, int i_family, int i_socktype,
         return -1;
     }
 
-        /* Set to non-blocking */
+    if( fd >= FD_SETSIZE )
+    {
+        msg_Err( p_this, "cannot create socket (too many already in use)" );
+        net_Close( fd );
+        return -1;
+    }
+
+    /* Set to non-blocking */
 #if defined( WIN32 ) || defined( UNDER_CE )
     {
         unsigned long i_dummy = 1;
index f9f3afbb09462866e91b660529763eea798c3f93..3b088dcd6949b170a915b18b759d6cc1ed17dc6a 100644 (file)
@@ -416,6 +416,11 @@ int __net_Accept( vlc_object_t *p_this, int *pi_fd, mtime_t i_wait )
             if( i_val < 0 )
                 msg_Err( p_this, "accept failed (%s)",
                          net_strerror( net_errno ) );
+            else if( i_val >= FD_SETSIZE )
+            {
+                net_Close( i_val ); /* avoid future overflows in FD_SET */
+                msg_Err( p_this, "accept failed (too many sockets opened)" );
+            }
             else
             {
                 /*