1#include <unistd.h> 2#include <errno.h> 3#include "syscall.h" 4#include "libc.h" 5#include "pthread_impl.h" 6 7struct ctx { 8 int id, eid, sid; 9 int nr, err; 10}; 11 12static void do_setxid(void *p) 13{ 14 struct ctx *c = p; 15 if (c->err>0) return; 16 int ret = -__syscall(c->nr, c->id, c->eid, c->sid); 17 if (ret && !c->err) { 18 /* If one thread fails to set ids after another has already 19 * succeeded, forcibly killing the process is the only safe 20 * thing to do. State is inconsistent and dangerous. Use 21 * SIGKILL because it is uncatchable. */ 22 __block_all_sigs(0); 23 __syscall(SYS_kill, __syscall(SYS_getpid), SIGKILL); 24 } 25 c->err = ret; 26} 27 28int __setxid(int nr, int id, int eid, int sid) 29{ 30 /* err is initially nonzero so that failure of the first thread does not 31 * trigger the safety kill above. */ 32 struct ctx c = { .nr = nr, .id = id, .eid = eid, .sid = sid, .err = -1 }; 33 __synccall(do_setxid, &c); 34 if (c.err) { 35 if (c.err>0) errno = c.err; 36 return -1; 37 } 38 return 0; 39} 40