/usr/bin/env hangs when a variable is set

Bug #1421760 reported by linas
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
coreutils (Ubuntu)
New
Undecided
Unassigned

Bug Description

/usr/bin/env hangs when a variable is set. To reproduce this, create a file with the following contents:

 #!/usr/bin/env A=B python

; !#
(display "wtf")
(newline)

lets say the file was "wtf.sh". Then chmod ugo+x wtf.sh and then execute it: ./wtf.sh This will hang and spin and burn cpu time. Removing the A=B will cause the script to run just fine (and spew errors, because the conents is not valid python, but that's OK. Instead of python, you could say guile. Its valuid guile. Or you could say bash. whatever, it does not matter)

According to gdb, it is stuck in an infinite loop in the dynamic linker-loader, where /usr/bin/env is calling itself over and over.

I can't quite tell if this is a bug in env, or in ld.so or in thelinux kernel. FWIW #!/usr/bin/env python 42 also gives unexpeted results: it searches for the interpreter "python 42" instead of searching for "python" and passing it the argument "42". Also the following does not work: #!/usr/bin/env -i python -- it spews an error about the -i flag.

This is on both trusty and precise

Attaching gdb to the hung pid gives the following:

gdb -p 27957
(gdb) bt
#0 0x00007fa5286c92d0 in _start () from /lib64/ld-linux-x86-64.so.2
#1 0x0000000000000003 in ?? ()
#2 0x00007fff36b5ac89 in ?? ()
#3 0x00007fff36b5ac96 in ?? ()
#4 0x00007fff36b5aca0 in ?? ()
#5 0x0000000000000000 in ?? ()
(gdb) c
Continuing.
process 27957 is executing new program: /usr/bin/env
process 27957 is executing new program: /usr/bin/env
process 27957 is executing new program: /usr/bin/env
...
ctrl-C
^C__GI__dl_debug_state () at dl-debug.c:74
74 dl-debug.c: No such file or directory.
Quit
(gdb) bt
#0 __GI__dl_debug_state () at dl-debug.c:74
#1 0x00007f7292b3396a in dl_main (phdr=<optimized out>, phdr@entry=0x400040,
    phnum=<optimized out>, phnum@entry=9,
    user_entry=user_entry@entry=0x7fff11adf818, auxv=<optimized out>)
    at rtld.c:2305
#2 0x00007f7292b47565 in _dl_sysdep_start (
    start_argptr=start_argptr@entry=0x7fff11adf900,
    dl_main=dl_main@entry=0x7f7292b31910 <dl_main>) at ../elf/dl-sysdep.c:249
#3 0x00007f7292b34cf8 in _dl_start_final (arg=0x7fff11adf900) at rtld.c:332
#4 _dl_start (arg=0x7fff11adf900) at rtld.c:558
#5 0x00007f7292b312d8 in _start () from /lib64/ld-linux-x86-64.so.2
#6 0x0000000000000003 in ?? ()
#7 0x00007fff11ae0c89 in ?? ()
#8 0x00007fff11ae0c96 in ?? ()
#9 0x00007fff11ae0ca0 in ?? ()
#10 0x0000000000000000 in ?? ()
(gdb) c
Continuing.
process 27957 is executing new program: /usr/bin/env
process 27957 is executing new program: /usr/bin/env
process 27957 is executing new program: /usr/bin/env
process 27957 is executing new program: /usr/bin/env
process 27957 is executing new program: /usr/bin/env
^C__GI__dl_debug_state () at dl-debug.c:74
74 dl-debug.c: No such file or directory.
Quit
(gdb) Quit
(gdb) Quit
(gdb) bt
#0 __GI__dl_debug_state () at dl-debug.c:74
#1 0x00007f990150396a in dl_main (phdr=<optimized out>, phdr@entry=0x400040,
    phnum=<optimized out>, phnum@entry=9,
    user_entry=user_entry@entry=0x7fff61a966a8, auxv=<optimized out>)
    at rtld.c:2305
#2 0x00007f9901517565 in _dl_sysdep_start (
    start_argptr=start_argptr@entry=0x7fff61a96790,
    dl_main=dl_main@entry=0x7f9901501910 <dl_main>) at ../elf/dl-sysdep.c:249
#3 0x00007f9901504cf8 in _dl_start_final (arg=0x7fff61a96790) at rtld.c:332
#4 _dl_start (arg=0x7fff61a96790) at rtld.c:558
#5 0x00007f99015012d8 in _start () from /lib64/ld-linux-x86-64.so.2
#6 0x0000000000000003 in ?? ()
#7 0x00007fff61a97c89 in ?? ()
#8 0x00007fff61a97c96 in ?? ()
#9 0x00007fff61a97ca0 in ?? ()
#10 0x0000000000000000 in ?? ()

Revision history for this message
Milan Hauth (milahu) wrote :

workaround: add -S

#! /usr/bin/env -S A=B python
import os; print(os.environ["A"])

why?

shebangs have the limitation (or feature)
that you can pass only one argument

so

#! /usr/bin/env A=B python

is parsed as

argv[0] = "/usr/bin/env"
argv[1] = "A=B python"

you can see this with

#! /usr/bin/printf A=B '(%s) ' 1 2 3 4

which prints

A=B '(./test.sh) ' 1 2 3 4

and

#! /usr/bin/env -S printf '(%s) ' 1 2 3 4

prints

(1) (2) (3) (4) (./test.sh)

now the question is,
why does `argv[1] = "A=B python"` lead to infinite recursion?

expected result:

/usr/bin/env: ‘A=B python’: No such file or directory
/usr/bin/env: use -[v]S to pass options in shebang lines

just like

#! /usr/bin/env hello world

throws

/usr/bin/env: ‘hello world’: No such file or directory
/usr/bin/env: use -[v]S to pass options in shebang lines

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.