From: Rich Felker Date: Sat, 30 Jul 2011 03:10:07 +0000 (-0400) Subject: add setxid.c for new set*id() framework. missed in last commit. X-Git-Tag: v0.8.0~78 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=afade2356ea148e715307be8f7334b790282341e;p=oweals%2Fmusl.git add setxid.c for new set*id() framework. missed in last commit. --- diff --git a/src/unistd/setxid.c b/src/unistd/setxid.c new file mode 100644 index 00000000..d3bfaf62 --- /dev/null +++ b/src/unistd/setxid.c @@ -0,0 +1,49 @@ +#include +#include +#include +#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; +}