¿Por qué bash incluso analiza / ejecuta cosas en la variable de entorno?

9

El error shellshock en bash funciona a través de variables de entorno. Honestamente, me sorprendió el hecho de que existe una característica como:

"transmisión de definiciones de funciones a través de env vars"

Por lo tanto, esta pregunta, aunque quizás no esté perfectamente formulada, es pedir un ejemplo o un caso en el que sería necesario tener esta función.

Prima. ¿Otros shells zsh, dash, etc. también tienen esta característica?

humanidad y paz
fuente
Utiliza los env para transmitir definiciones de funciones. ¿Qué quiere decir con "¿Por qué no simplemente mantiene las variables de entorno disponibles / accesibles?" ?
Anthon
@Anthon Gracias por el comentario. Tal vez debería ser más claro y reformularlo. ¿Por qué motivo es necesario poder transmitir definiciones de funciones a través de env vars?
humanityANDpeace
1
No estoy 100% seguro, pero creo que, por ejemplo, esa es la forma en que GNU parallelobtiene las definiciones de funciones distribuidas si invoca múltiples instancias de bash. Si no es así, tendría que escribirlos en un archivo, que cada instancia invocada se lee y luego tiene que lidiar con problemas como cuándo se puede eliminar ese archivo.
Anthon
2
Este hilo tiene algo de historia. Sin embargo, las funciones exportadas son una locura . si desea que un nuevo shell herede los comandos ejecutables del antiguo shell, obtenga .dotel mismo archivo que el antiguo shell. así es como se hace, y eso tiene sentido, o se alimenta el nuevo shell al archivo como entrada cuando se execing. una vez que se lee una vez que el archivo está en caché por el núcleo de todos modos.
mikeserv
@mikeserv ¿Lo entiendo bien, que una gran parte del shellshock está relacionado con esta característica, que de todos modos no es tan esencial?
humanityANDpeace

Respuestas:

4

Cuando una secuencia de comandos invoca otra secuencia de comandos, las variables de la secuencia de comandos principal se pueden exportar y luego serán visibles en la secuencia de comandos secundaria. Exportar funciones es una generalización obvia: exportar la función desde el padre, hacerla visible en el hijo.

El entorno es la única forma conveniente en que un proceso puede pasar datos arbitrarios a sus hijos. Los datos deben agruparse en cadenas que no contengan bytes nulos, lo que no es una dificultad para las funciones de shell. Existen otros métodos potenciales, como bloques de memoria compartida o archivos temporales pasados ​​a través de descriptores de archivos, pero estos podrían causar problemas con programas intermedios que no saben qué hacer con ellos o los cerrarían. Los programas esperan ejecutarse en un entorno que contiene variables que no conocen o no les importan, por lo que no las sobrescribirán ni las borrarán.

La elección de usar el nombre de la función como el nombre de la variable de entorno es extraña. Por un lado, significa que una variable exportada choca con una función exportada del mismo nombre.

Las funciones exportadas son una característica antigua. Se agregaron funciones en el shell Bourne en SVR2 , y las funciones exportadas en el shell de la Versión 8 lanzadas el mismo año (1984). En ese shell, las variables y funciones utilizan el mismo espacio de nombres. No sé cómo funcionó la exportación de funciones. El shell Heirloom se basa en una variante Bourne que tiene funciones pero no las exporta.

ATT ksh supuestamente admite funciones de exportación, pero al mirar la fuente o jugar con ella, no puedo ver que lo haga, a partir de ksh93u.

env -i /usr/bin/ksh -c 'f=variable; f () { echo function; }; typeset -fx f; /usr/bin/env; ksh -c f'
_=*25182*/usr/bin/env
PWD=/home/gilles
SHLVL=1
A__z="*SHLVL
ksh: f: not found

Los clones de dominio público de Ksh (pdksh, mksh), dash y zsh no admiten funciones de exportación.

Gilles 'SO- deja de ser malvado'
fuente
1
¡gracias! Entonces, sin exportar funciones, la funcionalidad de la característica se pierde, sin embargo, hay algunos shell como dash, zsh y pdksh, etc. que carecen de esta funcionalidad, ¿lo leo bien?
humanityANDpeace
Pero cuando exporto una función en bash, entra en una variable como BASH_FUNC_f%%=() { echo hi }. ¿Por qué bash analizaría otras variables de entorno? ¿Por qué incluso se analizaría BASH_FUNC_g%%cuando solo estoy llamando f? (Aparentemente, antes del shellshock, la variable de entorno acababa de llamarse fo g, pero todavía me pregunto por qué ghabría sido analizada si nunca llamo gen mi script)
Metamorphic
@Met Tiene que mirar todas las variables de entorno para determinar cuáles son las definiciones de funciones. Podría memorizar ese hecho y evitar analizar el código de una función hasta la primera vez que se necesita, pero eso sería una complejidad adicional para muy poca ganancia. Es más fácil tener solo un tipo de función y no dos ("función normal" y "función de una variable de entorno que necesita un poco de análisis").
Gilles 'SO- deja de ser malvado'
No es claro. Estoy sugiriendo que lo más obvio habría sido, cuando ejecuto algo llamado f, (1) verificar una función de shell llamada f, (2) verificar una variable de entorno llamada fe intentar analizarla, (3) verificar cada PATHcomponente para un ejecutable llamado f. ¿Cómo podría analizar cada variable de entorno como código de shell, en el inicio de shell, parecer un diseño menos complicado?
Metamórfico el
@Metamorphic Sugiere agregar otro paso que debe realizarse en cada comando. También tendría que agregar otro paso cuando defina o defina funciones (después unset -f foo, bash ya no debe buscar una definición de función fooen el entorno), al enumerar funciones (¿cómo maneja, declare -fademás de leer todas las variables de entorno?) , y cualquier otra cosa en la que no esté pensando. Su diseño solo parece más fácil porque dejó de lado la mayor parte. Por el contrario, hacer todo en el inicio es una sola pieza de código y después de eso, todo funciona.
Gilles 'SO- deja de ser malvado'