2010-11-18 17 views
5

私が書いたPythonの拡張機能は、単一のハードウェアの初期化呼び出しを行うにはrootアクセスが必要です。私はむしろ、私の拡張でこの1つの呼び出しのためだけにrootとしてスクリプト全体を実行しないので、ユーザ権限に落として実際のスクリプトを実行する前に、この初期化を行うラッパーを書きたいと思います。setuidラッパーに関する考慮事項

このラッパーはsudo経由で実行されるために、私は私のようなもの(はバグのカップルを修正するために更新)を考慮した例

$ sudo devwrap python somescript.py 

、つもり:だから私は持っている

int main(int argc, char * argv[]) 
{ 
    if(argc < 2) return 0; 

    int res = do_hardware_init(); 
    if(res != OK_VALUE) 
    { 
    // Print error message 
    return HW_ERR; 
    } 

    const char *sudo_uid = getenv("SUDO_UID"); 
    if(sudo_uid) 
    { 
     int real_uid = (int) strtol(sudo_uid, NULL, 0); 
     setuid(real_uid); 
    } 

    return execvp(argv[1], &argv[1]); // No return if successful 

} 

を3つの質問:

  1. これは正常に見えますか?私は通常、* uid()呼び出しを混乱させる必要はないので、私は通常の落とし穴に精通していません。 execvpコールも少し奇妙に見えますが、私が見る限り、適切な場所に引数があります)。
  2. execvpのマニュアルページにはがあります。 "environアレイはアプリケーションによって直接アクセスされるべきではありません" - getenvは悪い考えですか?
  3. execvpより良いコールがありますので、私はsudo devwrap somescript.py(「パイソン」のノート不在)を行うことができ、より下の正気の

答えて

1
  1. ソート...。
  2. getenv()を使用していると、environアレイに直接アクセスしていません。つまり、きれいです。配列environに直接アクセスすると、 'strcpy(buffer、environ [3])'などのようになります。
  3. スクリプトがシバン(#!/usr/bin/env python、おそらく)で始まっていれば、すでに望むことができます。もちろん、somescript.pyは実行可能でなければなりません。

最初の部分で見られる問題は、ハードウェアの初期化によるエラーの処理方法によって異なります。省略されたエラー処理が終了しない場合、nullポインタ上でstrtol()を実行するため、 'sudo'で実行されないとコアダンプ(またはsegfault)を取得する可能性があります。 do_hardware_init()が失敗しても終了する場合は、ユーザーが 'sudo'から環境を破壊する方法を見つけない限り、問題はありません。 SUDO_UIDが妥当に設定されていないと、環境を検証してエラーで終了する必要があります。ルートはこの拡張機能を実行しますか?

私はsudoの仕様を見てSUDO_UID環境変数を設定していることを確認していません。あなたはそれが正しいと思います。

これを入力したユーザーの影響は何ですか?

sudo devwrap ls 

それは、ハードウェアの初期化を行いUIDをリセットし、その後ls実行します - おそらくあまりにも有害ではなく、そうでないかもしれない、あなたが考えていたものを。それは重要ですか?あなたはそれをまったく制御できますか?

引数の数が2より小さい場合は、正常終了するのではなく、エラー終了を与えるべきです。


「sudo」を使って拡張機能を実行するように要求することは非常に珍しいことです。

これを達成する別の方法はありませんか?初期化の要件は何ですか?それはすべてのプロセスに対して1回実行されますか、プロセスごとに1回(つまり、連鎖が重要です)行われますか?


devwrapプログラムをSUIDルートに設定するだけですか?その後、異なったUIDをリセットする必要があります:

いかなるSGIDネスおよびコマンドを実行する前に、任意のSUIDネスを削除
setgid(getgid()); 
setuid(getuid()); 

。重大な損害を被ることはかなり難しい。プログラムがSGIDなしでインストールされている場合でもsetgid()呼び出しが必須であることは明らかではありませんが、害はありません。

+0

*達成するための別の方法がないと確信していますか?いいえ、私はいないが、私は別の方法を考えることはできません。初期化コールがルートとして実行されない場合は、失敗して完全に停止します。私は*それがプロセス毎に必要であるとは思わない* – detly

+0

...しかしそれは文書化されていない。私は驚くかもしれませんが、メモリマップされた制御レジスタのようです。 – detly

+0

申し訳ありませんが、これを受け入れるには長い時間がかかります。私はあなたの助言を取り、SUIDルートに行くことに決めました。 – detly

関連する問題