Here's the full source of the program that demonstrates my problem (OS is Ubuntu 14.04 32-bit, if that matters):
#include <stdio.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> int main(int argc, const char *argv[]) { int status, fd; printf("CURRENT UID: %d, CURRENT GID: %d\n", getuid(), getgid()); fd = open("/dev/ttyS0", O_WRONLY); if(fd < 0) { printf("Error opening /dev/ttyS0: %s\n", strerror(errno)); return 1; } printf("Successfully opened /dev/ttyS0\n"); close(fd); /* DROP PRIVILEGES */ setgid(1000); setuid(1000); printf("CURRENT UID: %d, CURRENT GID: %d\n", getuid(), getgid()); fd = open("/dev/ttyS0", O_WRONLY); if(fd < 0) { printf("Error opening /dev/ttyS0: %s\n", strerror(errno)); return 1; } printf("Successfully opened /dev/ttyS0\n"); return 0; }
There are two users in the system: root and a regular non-root user (call him "ubuntu") with id = 1000. The above program tries to open the serial port (/ dev / ttyS0) twice: the first time with root or ubuntu privileges (depending on of how it is called), and the second time is always ubuntu. The first unsuccessful attempt causes the program to abort. The user ubuntu is a member of the dialout group, so theoretically he has the necessary permissions to open / dev / ttyS 0. I invoke the program in four different ways:
1) it starts directly as ubuntu
plea:
<path to my program>
2) it starts as ubuntu, but using sudo
plea:
sudo -u ubuntu <path to my program>
3) it starts with root privileges, but with privileges omitted for ubuntu privileges (so, efficiently, run as ubuntu):
plea:
sudo su
sudo -u ubuntu <path to my program>
In all three cases, I get the following expected result:
CURRENT UID: 1000, CURRENT GID: 1000 Successfully opened /dev/ttyS0 CURRENT UID: 1000, CURRENT GID: 1000 Successfully opened /dev/ttyS0
In the latter case, however, something strange happens:
4) runs directly as root
plea:
sudo su
<path to my program>
result:
CURRENT UID: 0, CURRENT GID: 0 Successfully opened /dev/ttyS0 CURRENT UID: 1000, CURRENT GID: 1000 Error opening /dev/ttyS0: Permission denied
Of course, these are the last two lines that I donβt understand: this time, when root reset his privileges, it turns out that ubuntu does not have enough privileges to open / dev / ttyS 0, but why? How is this case different from cases 1-3?
One last thing worth mentioning: if I change this line of my code:
setgid(1000);
:
setgid(20);
then the last attempt to open / dev / ttyS 0 is also successful.
Does this mean that the information that ubuntu is a member of the dialout group is lost for some reason when I run the program with root privileges and then refuse the privileges for ubuntu by changing uid and gid to 1000? Could you give me a detailed explanation of what will happen in case 4 of my example and why the result is different from what was expected?