0

I am working in Linux and trying to execute a C program with setuid on Linux. Here is my code:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>

int main()
{
    int ret;
    fprintf ( stderr, "Orig: %d   Effective: %d\n", getuid(), geteuid() );

    ret = setuid ( 122 );
    if ( ret < 0 )
    {
        perror ( "Problem in setuid  " );
        return ( 1 );
    }

    fprintf ( stderr, "UID : %d   Effective: %d\n", getuid(), geteuid() );
    execlp ( "/bin/id", "/bin/id", NULL );

    fprintf ( stderr, "Problem executing execlp\n" );
    return ( 0 );
}

Upon execution, the UID is not changed. The output is:

[hauschild@hoare7 ~]$ ~sanjiv/bin/a.out
Orig: 155   Effective: 122
UID : 155   Effective: 122
uid=155(hauschild) gid=100(users) euid=122(sanjiv) groups=100(users)
[hauschild@hoare7 ~]$ 

I have looked at other questions in SO but unable to figure this one out. The permissions on executable are rwsr-sr-x. Notice how the code runs to completion and the exit status is reported as 0. However, when I run it through strace, it gives me an error on setuid and exists with a 1. as follows:

geteuid()                               = 155
getuid()                                = 155
write(2, "Orig: 155   Effective: 155\n", 27Orig: 155   Effective: 155
) = 27
setuid(122)                             = -1 EPERM (Operation not permitted)
write(2, "Problem in setuid  : Operation n"..., 45Problem in setuid  : Operation not permitted
) = 45
exit_group(1)                           = ?
+++ exited with 1 +++

Can anyone see what I could be doing wrong?

unxnut
  • 8,509
  • 3
  • 27
  • 41
  • 1
    Your setuid call has no effect. [The manpage for setuid](http://man7.org/linux/man-pages/man2/setuid.2.html) says that it sets the *effective* uid. Your `a.out` is `rwsr-sr-x` and so it is automatically executed with `setuid` (using the file owner), having the effective uid 122 as you print on the `Orig:` line. – Kenney Feb 11 '16 at 22:50
  • 1
    If you try to strace a program that is setuid, it will run without setuid. The reason is that strace works by using the system's process trace facilities, which are meant for debugging and allow the "debugger" (strace in this case) to arbitrarily modify the target process's memory. If an unprivileged user could do that to a program running with root privileges, it'd be bad news. – Nate Eldredge Feb 12 '16 at 00:15

1 Answers1

5

In POSIX and Linux, setuid() only sets the effective UID of the process, unless the effective UID is root, in which case it also sets the real UID and the saved set-user-ID. To set the real UID, use setreuid(). BSD setuid sets all of them regardless of the effective UID of the process.

To set the real UID, use setreuid:

ret = setreuid(122, 122);
Barmar
  • 741,623
  • 53
  • 500
  • 612