web-dev-qa-db-fra.com

Pourquoi la source de Bash n'a-t-elle pas besoin du bit d'exécution?

Avec source de Bash, il est possible d'exécuter un script sans bit d'exécution défini. C'est un comportement documenté et attendu, mais n'est-ce pas contre l'utilisation d'un bit d'exécution?

Je sais que source ne crée pas de sous-shell.

60
Motte001

Bash est interprète; il accepte l'entrée et fait tout ce qu'il veut. Il n'a pas besoin de tenir compte du bit exécutable. En fait, Bash est portable et peut s'exécuter sur des systèmes d'exploitation et des systèmes de fichiers qui n'ont aucun concept de bit exécutable.

Ce qui importe au bit exécutable, c'est le noyau du système d'exploitation. Lorsque le noyau Linux effectue une exec, par exemple, il vérifie que le système de fichiers n'est pas monté avec une option noexec, il vérifie le bit exécutable du fichier programme et applique toutes les exigences imposées par modules de sécurité (tels que SELinux ou AppArmor).

Notez que le bit exécutable est un type de contrôle plutôt discrétionnaire. Sur un système Linux x86-64, par exemple, vous pouvez contourner la vérification par le noyau du bit exécutable par en invoquant explicitement /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 comme interprète :

cp /bin/ls /tmp/
chmod -x /tmp/ls
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /tmp/ls

Ceci est quelque peu analogue au sourcing de code source Bash dans Bash, sauf que ld.so est l'interpréteur, et le code qu'il exécute est le code machine au format ELF.

38
200_success

source ou l'équivalent mais standard dot . n'exécute pas le script, mais lit les commandes du fichier script, puis exécutez-les, ligne par ligne, dans l'environnement Shell actuel.

Il n'y a rien contre l'utilisation du bit d'exécution, car le Shell n'a besoin que de la permission de lecture pour lire le contenu du fichier.

Le bit d'exécution n'est requis que lorsque vous exécutez le script. Ici, le shell va fork() nouveau processus puis en utilisant la fonction execve() pour créer une nouvelle image de processus à partir du script, qui doit être un fichier exécutable régulier.

57
cuonglm

Le bit exécutable (contrairement au reste) sur les fichiers nonsetuid et nonsetguid n'est pas vraiment un mécanisme de sécurité. Tout ce que vous pouvez lire, vous pouvez l'exécuter indirectement, et Linux vous permettra de lire indirectement tout ce que vous pouvez exécuter mais pas directement lu (cela devrait être suffisant pour percer un trou dans le concept de non-set (g) uid x-bit étant un mesure de sécurité).

C'est plus une question de commodité: laissez le système l'exécuter directement pour moi si le bit est défini, sinon je dois le faire indirectement (bash the_script; ou un peu piratage pour obtenir l'image mémoire d'un exécutable sans autorisation de lecture ).

Vous pouvez le paramétrer pour plus de commodité si vous avez l'intention à la fois d'in-source et d'exécuter votre câble insourcable.

Apparemment, cependant, de nombreux implémenteurs de bibliothèques partagées partagent votre opinion et, par conséquent, de nombreux systèmes nécessitent que les bibliothèques partagées, qui sont essentiellement l'équivalent natif des insourcables Shell, soient marquées comme exécutables afin d'être utilisables. Voir Pourquoi les bibliothèques partagées sont-elles exécutables? .

20
PSkocik

C'est une bonne question! Unix utilise le bit exécutable pour faire la distinction entre les programmes et les données. L'OS ne nécessite pas le bit d'exécution, puisqu'un script d'origine n'est pas transmis à l'OS pour exécution en tant que nouveau processus. Mais le shell traite un script d'origine comme un programme et regardera dans $PATH pour le fichier que vous souhaitez source. Ainsi, le shell lui-même aurait pu nécessiter une autorisation d'exécution pour les fichiers d'origine; mais ce ne fut pas le cas.

La question a dû se poser depuis longtemps. La conception du Bourne Shell était le résultat de "une longue séquence de modifications, dialogues, discussions" parmi les habitants des Bell Labs, et de nombreuses décisions de conception ont été discutées par S.R. Bourne et d'autres au fil des ans. Malheureusement, mon regard rapide n'a trouvé aucune discussion sur la fonctionnalité source (pour ma défense, il est difficile de la rechercher sur Google). Ce que j'ai trouvé, c'est que le "." La commande n'apparaît pas dans cette première introduction au shell par Bourne lui-même, mais elle est présente dans la version plus mature version 7 .

En l'absence d'autorité, voici ma propre interprétation:

  1. Le ., alias source, est en fait une inclusion textuelle (comme #include dans le préprocesseur C) dans le code source du script en cours d'exécution ou de la session interactive. En tant que tel, le fichier inclus n'est sans doute pas "exécuté".

  2. La philosophie Unix a toujours été de donner aux programmeurs assez de corde pour se pendre. Trop de restrictions sur la tenue de la main et arbitraires se mettent en place. Ce n'est que récemment que certaines distributions ont fait rm -r / refuser de faire ce que vous demandez. (Cette commande indique à rm de supprimer tout sur votre ordinateur. Ne l'essayez pas en tant que root! Ou mieux encore, pas du tout.) Donc, peut-être que Bourne et al. vient de décider que lorsque vous essayez de source un fichier, vous êtes supposé savoir ce que vous faites. Cela évite également un travail inutile et les cycles comptaient beaucoup à l'époque.

9
alexis

En ce qui concerne le système d'exploitation, un fichier contenant un script Shell n'est que des données. Si vous passez le nom d'un tel fichier de données à la commande source ou le passez sur la ligne de commande à un appel du shell bash, tout le système d'exploitation voit est une chaîne qui coïncide avec le nom d'un fichier contenant des données.

En quoi le bit d'exécution serait-il pertinent dans ce cas?

4
Stephen M. Webb

La distinction est importante car vous pouvez avoir un fichier de commandes Shell qui n'est pas utile en tant qu'exécutable, mais utile uniquement lorsqu'il est fourni. Pour ce fichier, vous pouvez désactiver le bit d'exécution, puis il ne sera jamais accessible sauf si explicitement dans une commande source. La raison d'une telle chose est d'avoir des effets secondaires sur le Shell à partir duquel elle est exécutée. Pour un exemple spécifique, j'ai un script appelé fix_path qui regarde et modifie le chemin.

3
MAP

Juste au cas où quelqu'un serait intéressé par d'autres études et/ou clarifications: dans un Shell presque conforme à POSIX mis en œuvre il y a quelque temps, le fonctionnement interne des fonctions 'exec_program ()' et 'builtin_source ()' est très exemplaire. Dans ces fonctions, vous voyez exactement quelle est la différence entre elles:

https://github.com/rsenn/shish/blob/master/src/builtin/builtin_source.c

https://github.com/rsenn/shish/blob/master/src/exec/exec_program.c

le sourcing peut être vu comme le Shell redirigeant temporairement son descripteur de fichier interne d'où il analyse le script Shell (le terminal en mode interactif). il est donc très similaire à d'autres redirections comme <input_file.txt et >>append_to_something.list et celles-ci ont juste besoin d'ouvrir et de fermer des fichiers.

l'exécution est donc gérée par l'appel système execve() pour lequel le bit d'exécution est obligatoire.

Je me souviens avoir vu certains systèmes qui permettent l'exécution des binaires ELF/a.out, mais via l'exécution de "/lib/ld-dynamic-linker.so" et avec le programme binaire (sans bit d'exécution) comme premier argument. Je crois que c'était sur certaines machines DEC Alpha ou VAX (Cela aurait-il pu être SCO Unix?)

1
rsenn