github.com/afumu/libc@v0.0.6/musl/src/unistd/setxid.c (about)

     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  }