A program from apue.
#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;
}
I compiled it to an executable named 4-2
and I changed the owner and set the suid this is the output of ls -l
:
-rwsr-xr-x 1 root sinners 8490 Jan 7 18:50 4-2*
and /etc/shadow
:
-rw------- 1 root root 421 Jan 4 01:29 /etc/shadow
But when I run it:
user% ./4-2 /etc/shadow
access error for /etc/shadow: Permission denied
open error for /etc/shadow: Permission denied
Can someone explain why I am getting these access
and open
errors?
Best Answer
Quoting
access()
manpage:Set-user-ID bit makes the process's effective UID equal to the file owner, but the real user ID remains unchanged (i.e. remains what it was before
exec()
).You can use
setreuid()
to modify both effective UID and real UID of the process or you can useopen()
to determine privileges. I recommend the second solution especially since you already callopen()
anyway. You can check whethererrno
is equal toEPERM
to find out whether insufficient permissions was the reasonopen()
failed.The call to
open()
fails in your code, because you use the return value fromopen()
as the if condition. I guess the call actually succeeds and returns you a valid, non-zero (zero being already taken by stdin) file descriptor making the control go into the error-handling branch. The error-handling branch of the if displaysEPERM
error message since this is the last error which occurred due toaccess()
call. The condition to enter the error handling branch should check whetheropen()
returned -1.