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

Re: Strange stack & execve() behavior



OK, I'm getting some similarly wierd behaviour.  I've got an SS-5, I'm
running a minimal potato install with a 2.4.0-test11 kernel ( I need this
latest kernel since potato kernel crashes if more then one SCSI device on
chain :( ... ).

I get similar, but even wierder results to what Michel reports with the
little progies he provided.

On my x86 I run foo with comline param 10,000 it's fine, with 100,000 it's
still fine, at 1,000,000 it complains "that's too long", and at 10,000,000
it segfaults. 

However on my sparc I run foo with 10,000 it's fine, with 100,000 it
doesn't truncate the command-line buffer, yet it does trash the environment
variable, with 1,000,000 it does actually complain "that's too long", and
at 10,000,000 we're segfaulting.

You're guess is as good, and probably better, then mine. 
See below for details .....

This is what I got on by Athlon box:

------->

12:17pm bungley /tmp -> uname -a
Linux bungley 2.2.17 #2 Wed Sep 6 16:20:30 CST 2000 i686 unknown

12:17pm bungley /tmp -> ./foo 100000
strlen(execve_argv[1]) = 100000;
FOO=BAR;
strlen(argv[1]) = 100000;
FOO=BAR;

12:17pm bungley /tmp -> ./foo 1000000
strlen(execve_argv[1]) = 1000000;
FOO=BAR;
strerror(errno) = Argument list too long;

12:17pm bungley /tmp -> ./foo 10000000
Segmentation fault

<-------

And this is what I get on my SS5:

------->

hawaiian:/tmp# uname -a
Linux hawaiian 2.4.0-test11 #1 Tue Nov 28 20:13:55 CST 2000 sparc unknown

hawaiian:/tmp# ./foo 10000
strlen(execve_argv[1]) = 10000;
FOO=BAR;
strlen(argv[1]) = 10000;
FOO=BAR;

hawaiian:/tmp# ./foo 100000
strlen(execve_argv[1]) = 100000;
FOO=BAR;
strlen(argv[1]) = 100000;
FOO=(null);

hawaiian:/tmp# ./foo 1000000
strlen(execve_argv[1]) = 1000000;
FOO=BAR;
strerror(errno) = Argument list too long;

hawaiian:/tmp# ./foo 10000000
Segmentation fault

<-------

Enjoy!
------------------------------------------------
 Matt Lowry      ( mclowry@cs.adelaide.edu.au )
------------------------------------------------
This email sent with 100% recycled electrons.
------------------------------------------------



On Sun, 10 Dec 2000, Michel Kaempf wrote:

> Hello,
> 
> Something strange is going on when passing very long arguments to
> execve() on Linux sparc. Instead of complaining because of a too long
> argument list like on Linux i386, execve() successfully starts the new
> program, but some arguments passed to the program are overwritten, and
> some environment variables are lost, but without any notification.
> 
> The following program, foo, calls a second program, bar, via execve(),
> and together they demonstrate the problem:
> 
> /tmp% cat foo.c
> #include <errno.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <unistd.h>
> 
> int main( int argc, char * argv[] )
> {
>     unsigned long ul = strtoul( argv[1], NULL, 0 );
>     char foobar[ ul + 1 ];
>     char * execve_argv[] = { "/tmp/bar", foobar, NULL };
>     char * execve_envp[] = { "FOO=BAR", NULL };
> 
>     memset( foobar, 0x42, ul );
>     foobar[ ul ] = 0;
> 
>     printf( "strlen(execve_argv[1]) = %i;\n", strlen(execve_argv[1]) );
>     printf( "%s;\n", execve_envp[0] );
> 
>     execve( execve_argv[0], execve_argv, execve_envp );
> 
>     printf( "strerror(errno) = %s;\n", strerror(errno) );
>     return( -1 );
> }
> 
> /tmp% cat bar.c
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> 
> int main( int argc, char * argv[] )
> {
>     printf( "strlen(argv[1]) = %i;\n", strlen(argv[1]) );
>     printf( "FOO=%s;\n", getenv("FOO") );
>     return( 0 );
> }
> 
> First, when passing a not too long argument to /tmp/bar:
> 
> % uname -sm
> Linux i686
> 
> % /tmp/foo 4242
> strlen(execve_argv[1]) = 4242;
> FOO=BAR;
> strlen(argv[1]) = 4242;
> FOO=BAR;
> 
> % uname -sm
> Linux sparc64
> 
> % /tmp/foo 4242
> strlen(execve_argv[1]) = 4242;
> FOO=BAR;
> strlen(argv[1]) = 4242;
> FOO=BAR;
> 
> On both architectures everything works well. Now, when passing a long
> argument to /tmp/bar:
> 
> % uname -sm
> Linux i686
> 
> % /tmp/foo 424242
> strlen(execve_argv[1]) = 424242;
> FOO=BAR;
> strerror(errno) = Argument list too long;
> 
> % uname -sm
> Linux sparc64
> 
> % /tmp/foo 424242
> strlen(execve_argv[1]) = 424242;
> FOO=BAR;
> strlen(argv[1]) = 32775;
> FOO=(null);
> 
> Here, on Linux sparc, the argument passed to /tmp/bar was truncated and
> the FOO environment variable disappeared, although execve() started
> without any error. The last argument length working is 32767 (how
> strange :-):
> 
> % uname -sm
> Linux sparc64
> 
> % /tmp/foo 32767
> strlen(execve_argv[1]) = 32767;
> FOO=BAR;
> strlen(argv[1]) = 32767;
> FOO=BAR;
> 
> % /tmp/foo 32768
> strlen(execve_argv[1]) = 32768;
> FOO=BAR;
> strlen(argv[1]) = 32775;
> FOO=(null);
> 
> Is it a known bug, is it a libc bug, a kernel bug? I do not have enough
> time to work on the problem, and I am clearly not the best qualified
> person... Any ideas, comments? Please do not forget to CC me your
> answers, as I am not subscribed to the debian-sparc mailing list. Thank
> you very much, and best regards,
> 
> -- 
> MaXX
> 
> 
> --  
> To UNSUBSCRIBE, email to debian-sparc-request@lists.debian.org
> with a subject of "unsubscribe". Trouble? Contact listmaster@lists.debian.org
> 
> 




Reply to: