shebang et chemin

22

Pourquoi un shebang a-t-il besoin d'un chemin?

Faux

#!ruby

Correct

#!/usr/local/bin/ruby

#!/usr/bin/env ruby

Le système d'exploitation doit disposer des informations concernant le chemin d'accès d'une commande enregistrée, et pourquoi s'attend-il toujours à ce qu'elle soit donnée?

sawa
la source

Réponses:

22

Probablement pour garder le noyau plus simple. Je ne pense pas que le noyau recherche jamais votre chemin pour trouver un exécutable. Cela est géré par la bibliothèque C. #!le traitement est effectué dans le noyau, qui n'utilise pas la bibliothèque C standard.

De plus, je ne pense pas que le noyau ait une idée de votre chemin. $PATHest une variable d'environnement et seuls les processus ont un environnement. Le noyau ne fonctionne pas. Je suppose qu'il pourrait accéder à l'environnement du processus qui a fait l'exec, mais je ne pense pas que quoi que ce soit actuellement dans le noyau accède à des variables d'environnement comme ça.

cjm
la source
5

Vous pouvez obtenir PATHune sémantique de recherche à l'aide de env:

#!/usr/bin/env ruby  

a la sémantique que vous souhaitez

#!ruby

La raison pour laquelle le PATHfait de ne pas être considéré comme une bonne pratique est que le script ne peut faire aucune hypothèse sur le contenu de la variable d'environnement PATH, brisant le "modèle de dépendance séquentielle" des binaires où

  1. /bin contient les exécutables nécessaires au démarrage;
  2. /usr/bin contient les autres exécutables utilisés par l'installation du système d'exploitation;
  3. /usr/local/bin contient des exécutables installés par l'administrateur système qui ne font pas partie du système d'exploitation de base.
  4. ~/bin contient les propres exécutables de l'utilisateur.

Chaque niveau ne doit pas supposer l'existence de binaires plus tard dans la séquence, qui sont plus "d'application" mais peuvent s'appuyer sur des binaires plus tôt, qui sont plus "fondamentaux". Et la variable PATH a tendance à aller de l'application à la fondamentale, qui est la direction opposée à la dépendance naturelle ci-dessus.

Pour illustrer le problème, demandez-vous ce qui se passe si un script dans ~/bininvoque un script /usr/local/binqui invoque Ruby? Ce script doit-il dépendre de la version du système d'exploitation installée sur /usr/bin/ruby, ou de la copie personnelle que l'utilisateur possède sur ~/bin/ruby? PATHla recherche donne la sémantique imprévisible associée à celle-ci (peut ~/bin/ruby- être est un lien symbolique brisé), tandis que la cuisson dans le chemin #!donne à la première.

Il n'y a pas vraiment d'autre "système d'exploitation ... indépendant de la plate-forme ... d'informations concernant le chemin pour une commande enregistrée", donc la chose la plus simple est d'insister sur le chemin fourni dans le #!.

Charles Stewart
la source
0

Je pense que c'est pour que vous puissiez spécifier un autre interprète si vous en avez besoin ou si vous le souhaitez. Par exemple:

#!/home/user/myrubyinterpreter

Plus souvent vu avec les scripts shell:

#!/bin/bash
#!/bin/sh
#!/bin/dash
#!/bin/csh
Andrew Lambert
la source
4
Mais pourquoi cela rendrait-il cela nécessaire? Vous pouvez exécuter ruby ​​directement avec ruby, mais cela ne vous empêche pas de spécifier /home/user/myrubyinterpretersi vous voulez
Michael Mrozek
Le point de Michael est exactement ce que je demande.
sawa
0

Extrait du livre Classic Shell Scripting :

Les scripts shell commencent généralement par #! /bin/sh. Utilisez le chemin d'accès à un shell compatible POSIX si votre /bin/shn'est pas compatible POSIX. Il existe également des "pièges" de bas niveau à surveiller:

  • Vous devez connaître le chemin d'accès complet à l'interpréteur à exécuter. Cela peut empêcher la portabilité entre les fournisseurs, car différents fournisseurs placent les choses à différents endroits (par exemple, par /bin/awkrapport à /usr/bin/awk).
Arturo Herrero
la source
-2

Il y a d'autres raisons, mais du point de vue de la sécurité, je ne voudrais jamais qu'un script fasse des hypothèses sur le chemin correct. Que se passe-t-il s'il est incorrect et qu'il exécute le mauvais interpréteur de commandes ou interpréteur? Celui qui a été inséré par un utilisateur malveillant? Ou que se passe-t-il s'il repose sur un shell particulier et se bloque si le mauvais shell est utilisé?

Les utilisateurs peuvent jouer avec leur chemin et casser des trucs - ne faites pas confiance à l'utilisateur :-) J'ai mené de nombreuses attaques qui reposent sur le fait que l'utilisateur fait la mauvaise chose avec son chemin - obtenant généralement les choses dans le mauvais ordre - afin que je puisse subvertir un appel de script normal.

Oui, je sais que si vous avez écrit le script vous-même, vous pouvez à juste titre affirmer que vous avez réglé votre propre chemin, mais un interprète ne peut pas prendre ces décisions.

Rory Alsop
la source
Cette préoccupation ne s'applique que si le script s'exécute avec des privilèges élevés. Et c'est rare, car shebang et setxid ne jouent pas bien ensemble, et il y a beaucoup plus à s'inquiéter que $PATH. . Sans privilèges élevés, que faire si LD_PRELOADest utilisé? PS a voté car donner un faux avertissement sur la sécurité est préjudiciable à la sécurité.
Gilles 'SO- arrête d'être méchant'
Votre point sur setxid est valide, mais c'est un vecteur d'attaque parfaitement utile, donc ce n'est certainement pas un faux avertissement
Rory Alsop
1
Pourriez-vous donner un exemple de cas où il PATHy a un vecteur d'attaque et où il n'y a pas tant d'autres vecteurs d'attaque que toute l'approche devrait être repensée?
Gilles 'SO- arrête d'être méchant'
@Gilles - +1 vous avez un bon point, certainement, car si cela est cassé, il y a probablement d'autres façons qui sont tout aussi valides, mais en termes de choses cassées que vous pouvez réparer, c'est facile.
Rory Alsop