Rich Felker | afade23 | 2011-07-29 23:10:07 -0400 | [diff] [blame] | 1 | #include <unistd.h> |
| 2 | #include <errno.h> |
Rich Felker | afade23 | 2011-07-29 23:10:07 -0400 | [diff] [blame] | 3 | #include "syscall.h" |
| 4 | #include "libc.h" |
Rich Felker | 84b5c54 | 2015-01-12 18:16:32 -0500 | [diff] [blame] | 5 | #include "pthread_impl.h" |
Rich Felker | afade23 | 2011-07-29 23:10:07 -0400 | [diff] [blame] | 6 | |
| 7 | struct ctx { |
| 8 | int id, eid, sid; |
Rich Felker | 84b5c54 | 2015-01-12 18:16:32 -0500 | [diff] [blame] | 9 | int nr, err; |
Rich Felker | afade23 | 2011-07-29 23:10:07 -0400 | [diff] [blame] | 10 | }; |
| 11 | |
Rich Felker | afade23 | 2011-07-29 23:10:07 -0400 | [diff] [blame] | 12 | static void do_setxid(void *p) |
| 13 | { |
| 14 | struct ctx *c = p; |
Rich Felker | 84b5c54 | 2015-01-12 18:16:32 -0500 | [diff] [blame] | 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); |
Rich Felker | afade23 | 2011-07-29 23:10:07 -0400 | [diff] [blame] | 24 | } |
Rich Felker | 84b5c54 | 2015-01-12 18:16:32 -0500 | [diff] [blame] | 25 | c->err = ret; |
Rich Felker | afade23 | 2011-07-29 23:10:07 -0400 | [diff] [blame] | 26 | } |
| 27 | |
| 28 | int __setxid(int nr, int id, int eid, int sid) |
| 29 | { |
Rich Felker | 84b5c54 | 2015-01-12 18:16:32 -0500 | [diff] [blame] | 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 }; |
Rich Felker | afade23 | 2011-07-29 23:10:07 -0400 | [diff] [blame] | 33 | __synccall(do_setxid, &c); |
| 34 | if (c.err) { |
Rich Felker | 472e8b7 | 2015-01-15 07:09:14 -0500 | [diff] [blame] | 35 | if (c.err>0) errno = c.err; |
Rich Felker | afade23 | 2011-07-29 23:10:07 -0400 | [diff] [blame] | 36 | return -1; |
| 37 | } |
| 38 | return 0; |
| 39 | } |