web-dev-qa-db-ja.com

プログラム内でsetuid()/ setgid()を使用することと、Sudo -u xxx -g xxxで呼び出すことの間に違いはありますか?

次のpythonスクリプトを検討してください。このスクリプトは、DVDドライブからの読み取りを試みるプログラムであるHandBrakeCLIを呼び出します。

invoke.py

#!/usr/bin/python

import sys
import os
import subprocess as subp
import pprint

#immediately switch users
os.setgid(1002) #gid of "media"
os.setuid(1005) #uid of "jack"

#verify the switch worked
print os.getuid(), os.geteuid()
print os.getgid(), os.getegid()

#clear up any possible env var diffs
os.environ['USER'] = 'jack'
os.environ['USERNAME'] = 'jack'
os.environ['LOGNAME'] = 'jack'

#output env variables to see if there's anything different:
ff = open('env_%s.log' % sys.argv[1], 'w')
ff.write(pprint.pformat(dict(os.environ)))
ff.write("\n")
ff.close()

#call the program
p = subp.Popen(["HandBrakeCLI", "-i", "/dev/sr0", "-t", "0"])
p.communicate()

sys.exit(p.returncode)

以下が成功します( "A"):

Sudo -u jack -g media HandBrakeCLI -i /dev/sr0 -t 0

このように( "B"):

Sudo -u jack -g media ./invoke.py jack

しかし、これ(「C」)は失敗します:

Sudo ./invoke.py root

handBrakeCLIがCDドライブにアクセスできなかったことを示唆するエラーを出力します。ただし、printステートメントは、UID/GIDがjack:mediaに正常に変更されたことを確認します。 setuid/setgidを削除し、rootとしてinvoke.pyからHandBrakeCLIを呼び出すと、再び機能します。

Diffは、環境が本質的に同じであることを示しています。

$ diff env_root.log env_jack.log
8c8
<  'Sudo_COMMAND': './invoke.py root',
---
>  'Sudo_COMMAND': './invoke.py jack',

Setuidとsetgidを呼び出した後、元の呼び出しユーザーの「メモリ」はありますか?そうでない場合、HandBrakeは「B」と「C」の間で異なる見方をする可能性がありますか?

Ssh経由でアクセスするヘッドレスサーバーで10.04を実行しています。

3
trbabb

特権が昇格された(suidの場合)かどうかを検出できるため、違いが生じます。これは、Sudoを介した実行とは異なります。これは、Sudoケースではプロセス全体が「ジャック」として実行されているため(そしてuidを元に戻さないため、プロセスは終了するだけです)、suidケースでは元のuidが「記憶」され、有効なuidのみが変更されるためです。

状況は少し異なりますが、Sudo/suidの各組み合わせを検出するテストスクリプトは次のとおりです。 test_privs.sh 昇格した権限を検出するために、X11サーバーで同様のコードが使用されるようになりました。 xorg-ディスカッションを開発

私はあなたの特定のデバイス/ハンドブレーキのニーズを見ていませんが、これはあなたを正しい軌道に乗せるはずです。

2
totaam