mirror of https://git.musl-libc.org/git/musl
1 changed files with 49 additions and 0 deletions
@ -0,0 +1,49 @@ |
|||||
|
#include <unistd.h> |
||||
|
#include <errno.h> |
||||
|
#include <sys/resource.h> |
||||
|
#include "syscall.h" |
||||
|
#include "libc.h" |
||||
|
|
||||
|
struct ctx { |
||||
|
int id, eid, sid; |
||||
|
int nr, rlim, err; |
||||
|
}; |
||||
|
|
||||
|
/* We jump through hoops to eliminate the possibility of partial failures. */ |
||||
|
|
||||
|
static void do_setxid(void *p) |
||||
|
{ |
||||
|
struct ctx *c = p; |
||||
|
if (c->err) return; |
||||
|
if (c->rlim && c->id >= 0 && c->id != getuid()) { |
||||
|
struct rlimit inf = { RLIM_INFINITY, RLIM_INFINITY }, old; |
||||
|
getrlimit(RLIMIT_NPROC, &old); |
||||
|
if (setrlimit(RLIMIT_NPROC, &inf) && libc.threads_minus_1) { |
||||
|
c->err = errno; |
||||
|
return; |
||||
|
} |
||||
|
if (__syscall(c->nr, c->id, c->eid, c->sid)) |
||||
|
c->err = errno; |
||||
|
setrlimit(RLIMIT_NPROC, &old); |
||||
|
return; |
||||
|
} |
||||
|
if (__syscall(c->nr, c->id, c->eid, c->sid)) |
||||
|
c->err = errno; |
||||
|
} |
||||
|
|
||||
|
int __setxid(int nr, int id, int eid, int sid) |
||||
|
{ |
||||
|
struct ctx c = { .nr = nr, .id = id, .eid = eid, .sid = sid }; |
||||
|
switch (nr) { |
||||
|
case SYS_setuid: |
||||
|
case SYS_setreuid: |
||||
|
case SYS_setresuid: |
||||
|
c.rlim = 1; |
||||
|
} |
||||
|
__synccall(do_setxid, &c); |
||||
|
if (c.err) { |
||||
|
errno = c.err; |
||||
|
return -1; |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
Loading…
Reference in new issue