Avoid stack munching stdio implementations.
authorEric Andersen <andersen@codepoet.org>
Tue, 4 Jun 2002 13:28:43 +0000 (13:28 -0000)
committerEric Andersen <andersen@codepoet.org>
Tue, 4 Jun 2002 13:28:43 +0000 (13:28 -0000)
 -Erik

modutils/modprobe.c

index 6a3e06df483d4ad49097fe82751fe4e648a29025..a72028fa2807a26929f2f77d80f3c51b4e2dd8e7 100644 (file)
@@ -9,13 +9,13 @@
  */
 
 #include <sys/utsname.h>
-#include <stdio.h>
 #include <getopt.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <syslog.h>
 #include <string.h>
 #include <ctype.h>
+#include <fcntl.h>
 #include "busybox.h"
 
 
@@ -46,11 +46,11 @@ static int autoclean, show_only, quiet, do_syslog, verbose;
 
 static struct dep_t *build_dep ( void )
 {
+       int fd, n;
        struct utsname un;
-       FILE *f;
        struct dep_t *first = 0;
        struct dep_t *current = 0;
-       char buffer [4096];
+       char buffer[256];
        char *filename = buffer;
        int continuation_line = 0;
        
@@ -58,21 +58,35 @@ static struct dep_t *build_dep ( void )
                return 0;
                
        // check for buffer overflow in following code
-       if ( xstrlen ( un. release ) > ( sizeof( buffer ) - 64 ))
+       if ( xstrlen ( un.release ) > ( sizeof( buffer ) - 64 )) {
                return 0;
+       }
                                
        strcpy ( filename, "/lib/modules/" );
-       strcat ( filename, un. release );
+       strcat ( filename, un.release );
        strcat ( filename, "/modules.dep" );
 
-       f = fopen ( filename, "r" );
-       if ( !f )
+       if ((fd = open ( filename, O_RDONLY )) < 0)
                return 0;
-       
-       while ( fgets ( buffer, sizeof( buffer), f )) {
-               int l = xstrlen ( buffer );
+
+       while ( (n = read(fd, buffer, 255)) > 0) {
+               int l;
                char *p = 0;
-               
+
+               /* Jump through hoops to simulate how fgets() grabs just one line at a
+                * time... Don't use any stdio since modprobe gets called from a kernel
+                * thread and stdio junk can overflow the limited stack... */
+               p = strchr ( buffer, '\n' );
+               if (p) {
+                       off_t offset;
+                       /* Get the current file descriptor offset */
+                       offset = lseek(fd, 0L, SEEK_CUR);
+                       /* Set the file descriptor offset to right after the \n */
+                       lseek(fd, offset-n+p-buffer+1, SEEK_SET);
+                       *(p+1)='\0';
+               }
+
+               l = xstrlen ( buffer );
                while ( isspace ( buffer [l-1] )) {
                        buffer [l-1] = 0;
                        l--;
@@ -105,10 +119,10 @@ static struct dep_t *build_dep ( void )
                                mod = xstrndup ( mods, col - mods - ext );
                                        
                                if ( !current ) {
-                                       first = current = (struct dep_t *) malloc ( sizeof ( struct dep_t ));
+                                       first = current = (struct dep_t *) xmalloc ( sizeof ( struct dep_t ));
                                }
                                else {
-                                       current-> m_next = (struct dep_t *) malloc ( sizeof ( struct dep_t ));
+                                       current-> m_next = (struct dep_t *) xmalloc ( sizeof ( struct dep_t ));
                                        current = current-> m_next;
                                }
                                current-> m_module  = mod;
@@ -164,79 +178,90 @@ static struct dep_t *build_dep ( void )
                else
                        continuation_line = 0;
        }
-       fclose ( f );
+       close ( fd );
 
        // alias parsing is not 100% correct (no correct handling of continuation lines within an alias) !
 
-       f = fopen ( "/etc/modules.conf", "r" );
-       if ( !f )
-               f = fopen ( "/etc/conf.modules", "r" );
-       if ( f ) {
-               continuation_line = 0;
+       if ((fd = open ( "/etc/modules.conf", O_RDONLY )) < 0)
+               if ((fd = open ( "/etc/conf.modules", O_RDONLY )) < 0)
+                       return first;
        
-               while ( fgets ( buffer, sizeof( buffer), f )) {
-                       int l;
-                       char *p;
-                       
-                       p = strchr ( buffer, '#' );
-                       if ( p )
-                               *p = 0;
-                               
-                       l = xstrlen ( buffer );
+       continuation_line = 0;
+       while ( read(fd, buffer, 255) > 0) {
+               int l;
+               char *p;
                
-                       while ( l && isspace ( buffer [l-1] )) {
-                               buffer [l-1] = 0;
-                               l--;
-                       }
-                       
-                       if ( l == 0 ) {
-                               continuation_line = 0;
-                               continue;
-                       }
+               /* Jump through hoops to simulate how fgets() grabs just one line at a
+                * time... Don't use any stdio since modprobe gets called from a kernel
+                * thread and stdio junk can overflow the limited stack... */
+               p = strchr ( buffer, '\n' );
+               if (p) {
+                       off_t offset;
+                       /* Get the current file descriptor offset */
+                       offset = lseek(fd, 0L, SEEK_CUR);
+                       /* Set the file descriptor offset to right after the \n */
+                       lseek(fd, offset-n+p-buffer+1, SEEK_SET);
+                       *(p+1)='\0';
+               }
+
+               p = strchr ( buffer, '#' );
+               if ( p )
+                       *p = 0;
                        
-                       if ( !continuation_line ) {             
-                               if (( strncmp ( buffer, "alias", 5 ) == 0 ) && isspace ( buffer [5] )) {
-                                       char *alias, *mod;
+               l = xstrlen ( buffer );
+       
+               while ( l && isspace ( buffer [l-1] )) {
+                       buffer [l-1] = 0;
+                       l--;
+               }
+               
+               if ( l == 0 ) {
+                       continuation_line = 0;
+                       continue;
+               }
+               
+               if ( !continuation_line ) {             
+                       if (( strncmp ( buffer, "alias", 5 ) == 0 ) && isspace ( buffer [5] )) {
+                               char *alias, *mod;
 
-                                       alias = buffer + 6;
-                                       
-                                       while ( isspace ( *alias ))
-                                               alias++;                        
-                                       mod = alias;                                    
-                                       while ( !isspace ( *mod ))
-                                               mod++;
-                                       *mod = 0;
+                               alias = buffer + 6;
+                               
+                               while ( isspace ( *alias ))
+                                       alias++;                        
+                               mod = alias;                                    
+                               while ( !isspace ( *mod ))
+                                       mod++;
+                               *mod = 0;
+                               mod++;
+                               while ( isspace ( *mod ))
                                        mod++;
-                                       while ( isspace ( *mod ))
-                                               mod++;
-                                                                                       
+                                                                               
 //                                     fprintf ( stderr, "ALIAS: '%s' -> '%s'\n", alias, mod );
-                                       
-                                       if ( !current ) {
-                                               first = current = (struct dep_t *) malloc ( sizeof ( struct dep_t ));
-                                       }
-                                       else {
-                                               current-> m_next = (struct dep_t *) malloc ( sizeof ( struct dep_t ));
-                                               current = current-> m_next;
-                                       }
-                                       current-> m_module  = xstrdup ( alias );
-                                       current-> m_isalias = 1;
-                                       
-                                       if (( strcmp ( alias, "off" ) == 0 ) || ( strcmp ( alias, "null" ) == 0 )) {
-                                               current-> m_depcnt = 0;
-                                               current-> m_deparr = 0;
-                                       }
-                                       else {
-                                               current-> m_depcnt  = 1;
-                                               current-> m_deparr  = xmalloc ( 1 * sizeof( char * ));
-                                               current-> m_deparr[0] = xstrdup ( mod );
-                                       }
-                                       current-> m_next    = 0;                                        
-                               }                               
-                       }
+                               
+                               if ( !current ) {
+                                       first = current = (struct dep_t *) xmalloc ( sizeof ( struct dep_t ));
+                               }
+                               else {
+                                       current-> m_next = (struct dep_t *) xmalloc ( sizeof ( struct dep_t ));
+                                       current = current-> m_next;
+                               }
+                               current-> m_module  = xstrdup ( alias );
+                               current-> m_isalias = 1;
+                               
+                               if (( strcmp ( alias, "off" ) == 0 ) || ( strcmp ( alias, "null" ) == 0 )) {
+                                       current-> m_depcnt = 0;
+                                       current-> m_deparr = 0;
+                               }
+                               else {
+                                       current-> m_depcnt  = 1;
+                                       current-> m_deparr  = xmalloc ( 1 * sizeof( char * ));
+                                       current-> m_deparr[0] = xstrdup ( mod );
+                               }
+                               current-> m_next    = 0;                                        
+                       }                               
                }
-               fclose ( f );
        }
+       close ( fd );
        
        return first;
 }