Skip to content
Advertisement

bash does not get root permissions with setuid program

I have the following home-grown implementation of su:

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

int main (int argc, char *argv[]) {
    if (argc == 1) {
        printf ("Usage: %s command [argument]...n", argv[0]);
        return EXIT_SUCCESS;
    }

    if (geteuid () != 0) {
        fprintf (stderr, "%s: permissions are wrong or the setuid bit is not set.n", argv[0]);
        return EXIT_FAILURE;
    }

    argv++;

    int ret = execv (argv[0], argv);

    if (ret == -1) {
        perror (argv[0]);
        return EXIT_FAILURE;
    }

    return ret;
}

To allow for proper execution, the permissions and ownership information are set accordingly:

$ gcc su.c -o su
$ sudo chown root: su
$ sudo chmod 4755 su

When I invoke a shell, such as /bin/sh, I am able to modify root-owned files and directories:

$ rm -rf /opt/foobar/
rm: cannot remove ‘/opt/foobar/’: Permission denied
$ ./su /bin/sh
# rm -rf /opt/foobar
# exit

However, /bin/bash doesn’t seem to get root permissions:

$ ./su /bin/bash
bash-4.3$ rm -rf /opt/foobar/
rm: cannot remove ‘/opt/foobar/’: Permission denied

Advertisement

Answer

Shells reset the euid to the uid for security reasons. So if you really want to have a rooted shell, you need to enforce uid and euid to 0. Set-uid bit only change the effective user id.

You need to set the user id to 0 for bash to be run as root:

...
setuid(0);
int ret = execv (argv[0], argv);
...
Advertisement