A program from apue.

#include "apue.h"
#include <fcntl.h>

int main(int argc, char *argv[])
        err_quit("usage: a.out <pathname>");

    if(access(argv[1], R_OK)<0)
        err_ret("access error for %s",argv[1]);
        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?

  • should i ask the question here or stack overflow? – sinners Jan 7 '12 at 18:03
  • Can you please provide the link or access to apue.h? – Nikhil Mulley Jan 7 '12 at 18:06
  • 1
    Also provide, OS details, GCC details – Nikhil Mulley Jan 7 '12 at 18:07
  • @Nikhil os:archlinux 3.1.6-1-ARCH gcc 4.6.2 – sinners Jan 7 '12 at 18:12
  • @sinners Generally it's better to reply to requests for information by editing your original question, so that everyone can see it and not just people following the comments. – jw013 Jan 7 '12 at 18:24

Quoting access() manpage:

The check is done using the calling process's real UID and GID, rather than the effective IDs as is done when actually attempting an operation (e.g., open(2)) on the file. This allows set-user-ID programs to easily determine the invoking user's authority.

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 use open() to determine privileges. I recommend the second solution especially since you already call open() anyway. You can check whether errno is equal to EPERM to find out whether insufficient permissions was the reason open() failed.

The call to open() fails in your code, because you use the return value from open() 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 displays EPERM error message since this is the last error which occurred due to access() call. The condition to enter the error handling branch should check whether open() returned -1.

| improve this answer | |
  • @AdamZalcman thank you.i modified the question,i just want to ask the open error.sorry – sinners Jan 7 '12 at 18:12
  • @sinners I have added the explanation for the second error message (last paragraph). – Adam Zalcman Jan 7 '12 at 18:17
  • @AdamZalcman i understand.thank you. i'm wrong,the book was right. – sinners Jan 7 '12 at 18:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.