web-dev-qa-db-ja.com

なぜBashのソースは実行ビットを必要としないのですか?

Bashのsourceを使用すると、実行ビットを設定せずにスクリプトを実行できます。これは文書化され、予想される動作ですが、これは実行ビットの使用に反しませんか?

sourceはサブシェルを作成しないことを知っています。

60
Motte001

バッシュは通訳です。入力を受け入れ、やりたいことをすべて行います。実行可能ビットに注意する必要はありません。実際、Bashは移植性があり、実行可能ビットの概念を持たないオペレーティングシステムやファイルシステムで実行できます。

実行可能ビットを気にするのは、オペレーティングシステムのカーネルです。たとえば、Linuxカーネルがexecを実行する場合、ファイルシステムがnoexecオプションでマウントされていないことを確認し、プログラムファイルの実行可能ビットを確認し、セキュリティモジュール(SELinuxやAppArmorなど)。

実行可能ビットはかなり自由裁量の制御であることに注意してください。たとえば、Linux x86-64システムでは、実行可能ビットのカーネルによる検証を 明示的に/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2をインタープリターとして呼び出す でバイパスできます。

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

これは、ld.soがインタープリターであり、実行するコードがELF形式のマシンコードであることを除いて、BashでのBashソースコードの調達に多少似ています。

38
200_success

sourceまたは同等ですが標準 dot _._ スクリプトは実行しませんが、readスクリプトファイルのコマンドを実行し、現在のシェル環境で1行ずつ実行します。

シェルにはファイルのコンテンツを読み取るためのread権限のみが必要であるため、実行ビットの使用に反対することは何もありません。

実行ビットは、スクリプトをrunする場合にのみ必要です。ここで、シェルはfork()新しいプロセスを実行し、次に execve() 関数を使用してスクリプトから新しいプロセスイメージを作成します。これは、通常の実行可能ファイルである必要があります。

57
cuonglm

Nonsetuidおよびnonsetguidファイルの実行可能ビット(他のファイルとは異なります)は、セキュリティメカニズムではありません。読み取り可能なものはすべて間接的に実行できます。Linuxでは実行可能なものを間接的に読み取ることができますが、直接読み取ることはできません(set(g)uid x-bitの概念に穴を開けるには十分です)セキュリティ対策)。

それはより便利なことです:ビットが設定されている場合はシステムに直接実行させてください。そうでない場合は間接的に実行する必要があります(bash the_script;または一部 読み取り権限のない実行可能ファイルのメモリイメージを取得するためのハッキング )。

インソースとインソーサブルの両方を実行する場合は、便利に設定できます。

しかし、どうやら、多くの共有ライブラリの実装者はあなたの考えを共有しているため、多くのシステムでは、使用できるように、本質的にシェルインソーサブルのネイティブ同等物である共有ライブラリを実行可能としてマークする必要があります。 共有ライブラリはなぜ実行可能ですか? を参照してください。

20
PSkocik

それは良い質問です! Unixは、実行可能ビットを使用してプログラムとデータを区別します。ソーススクリプトは新しいプロセスとして実行するためにOSに渡されないため、OSは実行ビットを必要としません。ただし、シェルはソースを取得したスクリプトをプログラムとして扱い、$PATHでソースを取得するファイルを探します。したがって、シェル自体がソースファイルの実行権限を必要とする可能性があります。しかし、そうではありませんでした。

問題はずっと前に出てきたに違いない。ボーンシェルの設計は、ベルラボの住人の間で "修正、対話、議論の長いシーケンス" の結果であり、多くの設計決定はS.R.ボーンと長年にわたって。残念ながら、私のざっと見ただけではソース機能の説明は見つかりませんでした(私の弁護では、グーグルで検索するのは難しいです)。私が見つけたのは「。」コマンドは、ボーン自身によるシェルへの この初期の紹介 には表示されませんが、より成熟した バージョン7バージョン には表示されます。

権限がないため、ここに私自身の解釈を示します。

  1. .コマンド(別名source)は、実行中のスクリプトまたはインタラクティブセッションのソースコードに、テキストで(Cプリプロセッサの#includeのように)挿入されます。そのため、インクルードされたファイルは間違いなく「実行」されません。

  2. Unixの哲学は、常にプログラマーにぶら下がるのに十分なロープを与えることでした。あまりにも多くの手持ちと恣意的な制限が邪魔をしています。ごく最近になって、一部のディストリビューションでrm -r /が要求したことを拒否するようになりました。 (このコマンドはrmコンピュータ上のすべてを削除します)と伝えますrootとしてそれを試さないでください!またはまだ、全然良くありません。)それで、おそらくボーンなど。あなたがファイルを調達しようとするとき、あなたはあなたが何をしているのかを知っていると仮定されるとちょうど決めました。これにより、不要な作業も回避され、当時はサイクルが非常に重要でした。

9
alexis

OSに関する限り、シェルスクリプトを含むファイルは単なるデータです。そのようなデータファイルの名前をsourceコマンドに渡すか、コマンドラインでbashシェルの呼び出しに渡すと、OSが見る文字列はすべて、データを含むファイル。

その場合、実行ビットはどのように関連しますか?

4
Stephen M. Webb

実行可能ファイルとしては役に立たないが、ソースが提供されたときにのみ役立つシェルコマンドのファイルがある場合があるため、区別は重要です。このファイルの場合、実行ビットをオフにすると、ソースコマンドで明示的に指定しない限り、アクセスされません。このようなことの理由は、実行元のシェルに副作用があるためです。特定の例として、パスを確認して変更するfix_pathというスクリプトがあります。

3
MAP

誰かがさらなる研究や説明に興味がある場合に備えて:少し前に実装されたほぼPOSIX準拠のシェルでは、「exec_program()」関数と「builtin_source()」関数の内部動作は非常に典型的です。これらの関数では、それらの違いが正確にわかります。

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

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

基本的にソースとは、シェルが内部ファイル記述子を一時的にリダイレクトしてシェルスクリプトを解析する場所(対話モードの端末)と見なすことができます。そのため、_<input_file.txt_や_>>append_to_something.list_などの他のリダイレクトと非常に似ており、これらはファイルを開いたり閉じたりする必要があるだけです。

そのため、実行は、実行ビットが必須であるexecve()システムコールによって処理されます。

ELF/a.outバイナリの実行を許可するシステムをいくつか見ましたが、「/ lib/ld-dynamic-linker.so」を実行し、最初の引数としてバイナリプログラム(execビットなし)を使用します。一部のDEC AlphaまたはVAXマシンで発生したと思います(SCO Unixでしたか?)

1
rsenn