回答:
プロセス自体がsetuid(2)を呼び出す必要があります。まだ実行していない場合は、chroot(8)内で実行することも検討する必要があります。私の知る限り、rootが別のプロセスのuidを変更する方法はありません。
ルートとして実行している理由がポートのバインドである場合は、通常のユーザーとして上位ポートで実行し、OS Xでipfw(8)を使用してポート80/443 / etcを上位ポートに転送することをお勧めします。
http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx
setuid()
ではありません。一人で電話するだけでは十分ではありません。
sudo tcpdump -Z
initgroups(3)、setgid(2)、setuid(2)を使用して、自身のプロセスのルート特権を削除します。
# code taken from:
# http://www.opensource.apple.com/source/tcpdump/tcpdump-32/tcpdump/tcpdump.c
/* Drop root privileges and chroot if necessary */
static void
droproot(const char *username, const char *chroot_dir)
{
...
if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) {
fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n",
username,
(unsigned long)pw->pw_uid,
(unsigned long)pw->pw_gid,
pcap_strerror(errno));
exit(1);
}
...
}
initgroups
、setgid
、setuid
(最後!)は、UNIX上で正確に右のパラダイムである、と常に従うべきです。さらに、責任のある「droproot」関数は、3つの主要な関数すべてが成功を返したとしても、そのuidとgidが実際に設定されていることを確認します。
以下を使用して、他のユーザーとしてコマンドを実行できますsu
。
su USERNAME -c COMMAND
にCOMMAND
ドロップされた権限で実行されUSER
ます。
デフォルトでsu
は、ターゲットユーザーのシェルインタープリターを使用してコマンドを実行することに注意してください。対照的に、のデフォルトの動作でsudo
はCOMMAND
、をスタンドアロンプログラムとして扱い、現在の環境で実行されます。もちろん、これらのデフォルトの動作は、さまざまなスイッチと環境変数で変更できます。
su
USERNAMEが定義されたシェルを持っていない(または場合は動作しません/bin/false
)sudoが作業を行うのに対し。
su
はそれを反映します。ただし、いつでも-s
スイッチを使用してオーバーライドできます。の目的はsu
、特定のユーザーの動作を模倣することであることに注意してください。これは通常、シェルの影響を受けます。対照的に、sudo
(デフォルトでは)ターゲットユーザーのシェル設定を無視します。
特権をドロップするには、ドロップする非rootユーザーが必要です。次に、そのユーザーに切り替えるだけです。
#define UNPRIV_UID 48
#define UNPRIV_GID 48
if (getuid() == 0) { // we are root
// setting UID/GID requires root privileges, so if you don't set
// the GID first, you won't be able to do it at all.
if (setgid(UNPRIV_GID)!=0) die("Failed to set nonroot GID");
if (setuid(UNPRIV_UID)!=0) die("Failed to set nonroot UID");
}
ASSERT(getuid() != 0);
これは、ラッパースクリプトではなく、プログラム自体の中で行われることに注意してください。多くのプログラムは、特定の目的(たとえば、小さい番号のポートにバインドする)のためにroot権限を必要としますが、その後はrootを必要としません。したがって、これらのプログラムはrootとして起動しますが、不要になると特権を削除します。
root権限がまったく必要ない場合は、rootとして実行しないでください。例えば:
# Change this:
myprog -C /my/config/file
# To this:
sudo -u someuser myprog -C /my/config/file
# Or this
su someuser -c "myprog -C /my/config/file"
setuid
関数は、実際のUIDではなく、実効 UID のみを設定します。setreuid
プロセスが特権を取り戻すことができないようにしたい場合に使用してください。(そして上記のコードは補足的なグループ特権も扱いません。ほとんど信頼されているコードを起動する場合にのみ適しています。)
setuid()
は、実際の保存されたユーザーIDを設定します。あなたは考えているかもしれませんseteuid()
。すべてのシステムにがあるわけsetreuid()
ではないため、どこでも使用できるわけではありません。の正確なセマンティクスsetuid()
は複雑ですが、euid 0を持っている場合は、を使用して従来のすべてのユーザーID特権を削除できますsetuid()
。この回答で最大の省略はということですinitgroups
か、setgroups
などと呼ばれなければならないsetgid
とsetuid
し、より徹底したアサーションが最後に行われるべきであるということ。
あなたが別の実行可能ファイルを実行している場合、つまり、あなたが呼んでいるexecve
かの他のexec
機能のfamiliy、おそらく間接的などの機能を通じてsystem
またはpopen
、子プロセスは最初から権限なしで実行する必要があり、その後、最も簡単な方法は、取得することですシェルが関与し、を呼び出しますsu
。これは、Perlでのコードの外観の概要であり、に必要な引用を示しています。
$shell_command = quotemeta($path_to_executable) . " --option";
$shell_command =~ s/'/'\\''/; # protect single quotes for the use as argument to su
$su_command = sprintf("su -c '%s' %s", $shell_command, quotemeta($user_name));
open(PIPE, "$su_command |") or die;
子プロセスがrootとして開始する必要があるが、後で特権を削除する必要がある場合は、この回答のコードを参照してください。プロセスの特権をダウングレードする方法が示されています。