「command」、「builtin」、「unset」というbash機能をバイパスする方法は?

「command」、「builtin」、「unset」というbash機能をバイパスする方法は?

コマンド自体を参照すると、エイリアスをバイパスできることがわかります。

ただし、組み込み機能が同じ名前の関数によって「隠されている」場合、デフォルトの組み込み機能は組み込み機能を使用している場合を除いては実行できないようです。できれば。

bashのマニュアルページを引用すると、次のようになりますLESS='+/^COMMAND EXECUTION' man bash

COMMAND EXECUTION
       After a command has been split into words, if it results  in  a  simple
       command  and  an  optional list of arguments, the following actions are
       taken.

       If the command name contains no slashes, the shell attempts  to  locate
       it.   If  there  exists a shell function by that name, that function is
       invoked as described above in FUNCTIONS.  If the name does not match  a
       function,  the shell searches for it in the list of shell builtins.  If
       a match is found, that builtin is invoked.

それでは、新しいシェルを起動せずに次のような状況で回復することができますか?

unset() { printf 'Haha, nice try!\n%s\n' "$*";}
builtin() { printf 'Haha, nice try!\n%s\n' "$*";}
command() { printf 'Haha, nice try!\n%s\n' "$*";}

私はそれを追加しませんでしたreadonly -f unset builtin command。その場合はい上記の項目から回復できますか?追加の質問としてこれを検討してください。 3つの機能がすべて読み取り専用としてマークされている場合は、まだ回復できますか?


Bashでこの質問をしましたが、他のシェルにも適用できるかどうかに興味があります。

答え1

3つの機能がすべて読み取り専用としてマークされていても回復できますか?

はい、一般的に可能です。しかし、それでもそうすべきという意味ではありません。

最高の努力読み取り専用変数の設定解除unbind_variable以下のようにデバッガを接続して呼び出します。この質問に対するanishsaneの答え、読み取り専用関数の設定を解除し、その名前を渡してunbind_funcデバッガを使用することもできます。

これは、読み取り専用でない場合(実際に読み取り専用の場合)、合理的なアプローチではありません。この場合は、以下を使用する必要があります。cuonglmのソリューションunset、これはPOSIXモデルの処理を利用します。 その解決策実際の生活で実際に使えるものです。

readonlyデバッガを使用してシェルをバイパスした後は、シェルが正しく実行されるという実際の保証はないので、execより合理的な選択肢があるたびに(たとえば、シェルをシャットダウンして再起動したり、シェルを新しいものに置き換えたりするなど)、使用しないことをお勧めします。

そういえばこれアニッシュ・サニ(Anish Sani)方法変数の代わりに設定解除関数に適応:

cat <<EOF | sudo gdb
attach $$
call unbind_func("unset")
call unbind_func("builtin")
call unbind_func("command")
detach
EOF

気づく$$ 延長するEOFinのどの部分も引用されていないため、入力されるシェルのプロセスIDです<<EOF

Ubuntu 16.04 LTSのBash 4.3.48(1)リリースでこれをテストしましたが、うまくいきます。gdb他のデバッガに適用できますが、これが必要です。 〜のようにアニッシュサニーコメントパイプの目的は、cat入力を提供するプロセスが停止しgdbたデッドロックを防ぐことですgdb。私は、2つ以上のコマンドで構成されたパイプラインで、Bashが各コマンドをサブシェルで実行するため、この目標を達成すると信じています。しかし、これが最も信頼できる方法であるかどうかはわかりません。しかし、最終的にBashは読み取り専用変数と関数が変更されないという完全に合理的な仮定をするため、このアプローチが機能するという実際の保証はありません。実際、私の考えでは、これは実際には常に動作しているようです。

この技術を作成したとおりに使用するには、そのsudo技術をインストールしてルーティングできる必要がありますsudo。もちろん、これを他の特権の昇格方法に置き換えることもできます。実行しているオペレーティングシステムと構成方法によっては、完全に省略し、sudorootgdbではなくユーザー自身で実行することもできます。たとえば、Linux カーネルは/proc/sys/kernel/yama/ptrace_scope次の値を参照します。sysctlで設定可能他のプロセスをデバッグできるプロセスを決定するために、読み取りまたは(ルートとして)書き込みできます。値があれば、1プロセスの直系親(またはルートとして実行されているすべてのプロセス)のみをデバッグできます。ほとんどの最新のGNU / Linuxシステムではに設定されているため、1これを含めましたsudo

Linuxカーネルの動作に関するこれらの説明は、他の値が受け入れられ、必要な関係が調整される可能性があるptrace_scopeため、やや過度に単純化されました。1バラより関連文書詳細を確認してください。

答え2

posix モードの場合、bash一部の組み込み関数は POSIX 標準に準拠する特殊なものと見なされます。

これらの特殊な組み込み関数の1つの珍しい点は、コマンド検索プロセスでその関数が関数の前に見つかることです。これを利用するには、以下を試してください。

$ unset builtin
Haha, nice try!
builtin
$ set -o posix
$ unset builtin
$ builtin command -v echo
echo

setただし、次の関数でオーバーライドすると機能しませんset

$ set() { printf 'Haha, nice try!\n%s\n' "$*";}
$ set -o posix
Haha, nice try!

この場合、posixモードに入るPOSIXLY_CORRECTように設定するbashと、すべての特別な組み込みコマンドが提供されます。

$ POSIXLY_CORRECT=1

関連情報