| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 #include <unistd.h> | 
|  | 2 #include <errno.h> | 
|  | 3 #include "syscall.h" | 
|  | 4 #include "libc.h" | 
|  | 5 #include "pthread_impl.h" | 
|  | 6 | 
|  | 7 struct ctx { | 
|  | 8         int id, eid, sid; | 
|  | 9         int nr, err; | 
|  | 10 }; | 
|  | 11 | 
|  | 12 static 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 | 
|  | 28 int __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 } | 
| OLD | NEW | 
|---|