私が知る限り、さまざまなユーザーIDは次のとおりです(プロセスの観点から)。
- 実際のユーザーID:プロセスを所有するユーザーID
- 有効ユーザーID:現在許可されているものと許可されていないものを決定するユーザーID。
- 保存されたユーザーID:デフォルトでは元の有効ユーザーIDで、必要に応じて元の有効ユーザーIDに戻すことができます。
今、2つの質問があります。
プログラムの起動時に有効なユーザーIDを変数に保存すると、保存する必要のないユーザーIDになりますか?
Cプログラムで保存されたユーザーIDを取得するには?これを行う機能が見つかりません。
答え1
プログラムの起動時に有効なユーザーIDを変数に保存すると、保存されたユーザーIDは不要になりますか?
ユーザー空間プログラムが何を覚えているのではなく、カーネルがどの権限を使用できるかが問題です。ユーザーを分離するには、システムがプロセスで使用できるユーザーIDを制御する必要があります。それ以外の場合は、すべてのプロセスでroot権限を要求できます。
Cプログラムで保存されたユーザーIDを取得するには?これを行う機能が見つかりません。
getuid()
これは標準関数(sumのみ)を使用することはできませんgeteuid()
。少なくともLinuxはgetresuid()
ただし、3 つのユーザー ID がすべて返されます。
とにかく一般的に読む必要はありません。 setuid プログラムの場合、実際のユーザー ID と実効ユーザー ID の間の切り替えが許可されるため、実効ユーザー ID のコピーから始まります。
setuidプログラムでは、実際のユーザーIDはプログラムを実行しているユーザーのIDであり、有効で保存されたユーザーIDはそのプログラムを所有するユーザーのIDです。有効なユーザー ID は権限の確認に非常に重要であるため、プロセスが一時的に権限を放棄したい場合は、実際のユーザー ID と保存されたユーザー ID の間で有効なユーザー ID を変更します。
プロセスがユーザーIDを変更できることを確認するために、カーネルは保存されたユーザーIDをどのように使用しますか?これは、プロセスが有効なユーザーIDを変更しようとしたときにカーネルが保存されているユーザーIDを調べて、プロセスがそのようにできることを確認することを意味しますか?
はい。 Linuxのマニュアルページにsetuid()
これについての言及がありますが、やや隠されています。
ERRORS
EPERM The user is not privileged and uid does not match the real
UID or saved set-user-ID of the calling process.
つまり、(有効な)ユーザIDは、実際のIDまたは保存されたIDのいずれかを設定することができる。
setreuid()
これについてのマニュアルページがより明確です。
Unprivileged processes may only set the effective user ID to the real
user ID, the effective user ID, or the saved set-user-ID.
答え2
保存されたuidが変数の場合。
有効または実際のuidにコピーする権限がないため、一般変数は使用できません。コアできない一般変数からコピーできます。これはあなたが望むようにすることができます(大丈夫ですが、値がすでにsの1つにある場合にのみuid
)。
そうですね。有効なuidは、システムコールの権限を確認するために使用されます。例外はsetuid
/ですsetgid
(関数を参照)。
権限はsetuid
次のとおりです。 IDを移動できますが(あるuidから別のuidへ)、新しいIDを導入することはできません(CAP_SETUID
これを含む:rootがない限り)。
だから一般ユーザーとして。 1 つまたは 2 つの uid (実際と有効ですが、両方とも同じことができる) で始まります。異なる場合は、実際のアイテムを有効なアイテムにコピーできます。そうすれば、元に戻せずに一つだけ残ります。カーネルは通常の変数からロードすることを許可しません。したがって、有効なコンテンツを保存ファイルにコピーします。残りの実行では、元の有効なコンテンツを保存しますが、これは本当です。これで、Effective-uidにコピーして有効にすることができます。しばらくすると、1つを捨てることができます。たとえば、real を他の 2 つにコピーします。もう元に戻せません。今、権限を取得する唯一の方法はexec
setuidバイナリを使用することです。 (または新機能を備えたバイナリですが、今は心配しないでください)。
suidを取得するには、次のものを使用できますgetresuid
。http://man7.org/linux/man-pages/man2/getresuid.2.html
実際には通常のC変数を使用してください。ただし、uid値がuidの1つにすでに含まれていない場合は、その値を追加できません。
/*setup UIDs*/
uid_t real_uid = getuid(void);
uid_t original_effective_uid = geteuid(void);
int err = setresuid(real_uid, original_effective_uid, original_effective_uid); /*this line not needed as done by kernel for setuid binary*/
#ifdef see_effect_of_no_suid
int err = setresuid(real_uid, original_effective_uid, real_uid);
#endif
while (true) {
err=seteuid(original_effective_uid);
/*do stuff as original_effective uid*/
err=seteuid(real_uid);
/*do stuff as real uid*/
}