views:

44

answers:

2

I am trying to change my uid to 0 as non-root with the CAP_SETUID capability. I have the following program:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/capability.h>
#include <sys/prctl.h>

int main(int argc, char *argv[])
{
    printf("cap setuid in bset: %d\n", prctl(PR_CAPBSET_READ, CAP_SETUID, 0, 0, 0));
    printf("%s\n", cap_to_text(cap_get_file(argv[0]), NULL));
    printf("%s\n", cap_to_text(cap_get_proc(), NULL));
    printf("uid: %d\n", (int) getuid());
    setresuid(0, 0, 0);
    printf("uid: %d\n", (int) getuid());
    return 0;
}

I assign the setuid capability as follows:

sudo /sbin/setcap cap_setuid=ep ./capsetuid

And I get the following output

cap setuid in bset: 1
= cap_setuid+ep
=
uid: 1000
uid: 1000

I would expect the second printf() to also show the cap_setuid capability. Somehow my process does not get the setuid file capability. What am I doing wrong here?

Fabian

A: 

setuid() sets the effective user-id of the process, but getuid() gets the real user-id.

Change the getuid() to geteuid() and it should work.

caf
If `setuid()` sets the effective UID, what does the `seteuid()` function do? Part of the answer is "the same"; the difference is that `setuid()` does set the real and effective and saved UID values to the given UID if the process has 'appropriate privileges'. Then the subsidiary question is "does possessing the CAP_SETUID privilege confer the appropriate privileges"?
Jonathan Leffler
euid doesn change neither. The man page says: "If the effective UID of the caller is root, the real UID and saved set-user-ID are also set." I am not root, though, I am priviliged. So I am not sure what happens in my case. I found the problem is in my process not getting the cap_setuid capability. I've updated the question
Fabian
@Fabian: Does your kernel have file capabilities enabled (`CONFIG_SECURITY_FILE_CAPABILITIES=y`)? What does ` prctl(PR_CAPBSET_READ, CAP_SETUID, 0, 0, 0)` return?
caf
@caf: My kernel does have file capabilities. prctl() returns 1. So from I understand from the manpage, this means that my process does not get cap_setuid because it is blocked by the bounding capability set. Right? How do I change the bounding cap set?
Fabian
@caf: the problem was that file capabilities must be enabled on the kernel command line.
Fabian
+1  A: 

Just found out that file capabilities need to be enabled on the kernel commandline with file_caps=1.

Fabian