Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use setuid() from root to become user, with the possibility of becoming root again later?

I'm trying to do the safe thing, and have a program that needs to runs as root to drop its privileges when it doesn't need them. This works well if I chmod my binary with the SUID bit, and make it belong to root, as now I have UID = some user, and EUID = root, so I can use seteuid(0) and seteuid(getuid()) to respectively raise and drop admin rights.

But if I use sudo instead of setting the SUID, then UID == EUID == 0, and so calling seteuid(getuid()) won't have any effect. And I can't just change UID to some value from some random user, as the setuid() man page clearly states that if it is called from a program running as root, one loses the privileges for good, with no hope of getting them back.

So, how do I make my program lose temporarily its privileges when run using sudo?

like image 495
Florian Avatar asked Feb 16 '10 18:02

Florian


People also ask

What does setuid return?

If successful, setuid() returns zero. On failure, it returns -1 and sets errno to one of the following values: EINVAL. The value of uid is out of range.

Why use setuid?

Setuid and setgid are a way for users to run an executable with the permissions of the user (setuid) or group (setgid) who owns the file. For example, if you want a user to be able to perform a specific task that requires root/superuser privileges, but don't want to give them sudo or root access.

Is setuid A system call?

The original Linux setuid() system call supported only 16-bit user IDs. Subsequently, Linux 2.4 added setuid32() supporting 32-bit IDs. The glibc setuid() wrapper function transparently deals with the variation across kernel versions.

What is setuid binary?

SUID stands for “Set User ID”, and it is a special type of permission that can be given to a file so the file is always run with the permissions of the owner instead of the user executing it.


2 Answers

seteuid(some random uid) to drop privileges, seteuid(0) to get them back, when running as root.

like image 177
Aidan Cully Avatar answered Sep 24 '22 15:09

Aidan Cully


It seems like seteuid(x) should work to drop and re-raise privs...

$ cat > t12.c
#include <stdio.h>
#include <unistd.h>

void p(void) { printf("euid=%4d uid=%4d\n", geteuid(), getuid()); }

int main(void) { p(); seteuid(100); p(); seteuid(0); p(); return 0; }
$ cc -Wall t12.c
$ sudo chown root a.out && sudo chmod 4555 a.out
$ sudo ./a.out
euid=   0 uid=   0
euid= 100 uid=   0
euid=   0 uid=   0
$ ./a.out
euid=   0 uid= 501
euid= 100 uid= 501
euid=   0 uid= 501
$ 
like image 29
DigitalRoss Avatar answered Sep 22 '22 15:09

DigitalRoss