プログラムは以下で提供されます。アプエ。
#include "apue.h"
#include <fcntl.h>
int main(int argc, char *argv[])
{
if(argc!=2)
err_quit("usage: a.out <pathname>");
if(access(argv[1], R_OK)<0)
err_ret("access error for %s",argv[1]);
else
printf("read access OK\n");
if (open(argv[1], O_RDONLY)) {
err_ret("open error for %s", argv[1]);
} else {
printf("open for reading OK\n");
}
return 0;
}
私はそれを呼び出された実行可能ファイルにコンパイル4-2
し、所有者を変更してsuidを設定しました。これは次の出力ですls -l
。
-rwsr-xr-x 1 root sinners 8490 Jan 7 18:50 4-2*
そして/etc/shadow
:
-rw------- 1 root root 421 Jan 4 01:29 /etc/shadow
しかし、実行してみると:
user% ./4-2 /etc/shadow
access error for /etc/shadow: Permission denied
open error for /etc/shadow: Permission denied
access
誰かがこれらのエラーが発生する理由を説明できますかopen
?
答え1
引用するaccess()
マンページ:
このチェックは、実際にファイルを操作しようとすると(たとえば、open(2))、有効なIDを使用する代わりに、呼び出しプロセスの実際のUIDとGIDを使用して実行されます。これにより、SetUserID プログラムは呼び出し側ユーザーの権限を簡単に確認できます。
ユーザ ID ビットを設定すると、プロセスがアクティブになります。有効なUIDファイル所有者と同じですが、実際のユーザーIDは変更されません(つまり、以前の状態を維持しますexec()
)。
あなたはそれを使用することができますsetreuid()
プロセスの有効なUIDと実際のUIDを変更するか、それを使用してopen()
権限を決定できます。特にすでに電話をかけているので、2番目の解決策をお勧めしますopen()
。errno
同じことを確認して、EPERM
権限の不足によってopen()
エラーが発生したかどうかを確認できます。
open()
open()
戻り値をif条件として使用しているため、コード内の呼び出しは失敗します。私は実際に呼び出しが成功し、ゼロ以外の有効なファイル記述子を返し、制御がエラー処理ブランチに入ると思います。 if のエラー処理ブランチは、呼び出しによって発生した最後のエラーであるEPERM
ため、エラーメッセージを表示します。access()
エラー処理ブランチを入力する条件は、open()
-1が返されることを確認する必要があります。