diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 6a3e06df4..a72028fa2 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -9,13 +9,13 @@ */ #include -#include #include #include #include #include #include #include +#include #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; - } - - 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; - 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; - } - } + /* 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; + + 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; + mod++; + while ( isspace ( *mod )) + mod++; + +// fprintf ( stderr, "ALIAS: '%s' -> '%s'\n", alias, mod ); + + 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; }