-static const int evilsignals[]= { SIGFPE, SIGILL, SIGSEGV, SIGBUS, 0 };
-
-int bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
- pid_t child, rchild;
- char portarg[5], addrarg[33];
- const char *afarg;
- int i, r, status, restore_sigchild;
- const int *evilsignal;
- sigset_t block, saved;
- struct sigaction old_sigchild;
- unsigned int portval;
-
- switch (addr->sa_family) {
- case AF_INET:
- portval = ((struct sockaddr_in*)addr)->sin_port;
- if (addrlen != sizeof(struct sockaddr_in)) goto bail;
- break;
- case AF_INET6:
- portval = ((struct sockaddr_in6*)addr)->sin6_port;
- if (addrlen != sizeof(struct sockaddr_in6)) goto bail;
- break;
- default:
- goto bail;
- }
-
- if (!geteuid() || portval == 0 || ntohs(portval) >= IPPORT_RESERVED) {
- bail:
- return old_bind(fd,addr,addrlen);
- }
-
- sigfillset(&block);
- for (evilsignal=evilsignals;
- *evilsignal;
- evilsignal++)
- sigdelset(&block,*evilsignal);
- if (sigprocmask(SIG_BLOCK,&block,&saved)) return -1;
-
- switch (addr->sa_family) {
- case AF_INET:
- afarg = 0;
- sprintf(addrarg,"%08lx",
- ((unsigned long)(((struct sockaddr_in*)addr)->sin_addr.s_addr))
- &0x0ffffffffUL);
- break;
- case AF_INET6:
- afarg = "6";
- for (i=0; i<16; i++)
- sprintf(addrarg+i*2,"%02x",
- ((struct sockaddr_in6*)addr)->sin6_addr.s6_addr[i]);
- break;
- default:
- abort();
- }
- sprintf(portarg,"%04x",
- portval&0x0ffff);
-
- restore_sigchild= 0;
- if (sigaction(SIGCHLD,NULL,&old_sigchild)) return -1;
- if (old_sigchild.sa_handler == SIG_IGN) {
- struct sigaction new_sigchild;
-
- new_sigchild.sa_handler= SIG_DFL;
- sigemptyset(&new_sigchild.sa_mask);
- new_sigchild.sa_flags= 0;
- if (sigaction(SIGCHLD,&new_sigchild,&old_sigchild)) return -1;
- restore_sigchild= 1;
- }
-
- child= fork(); if (child==-1) goto x_err;
-
- if (!child) {
- if (dup2(fd,0)) exiterrno(errno);
- removepreload();
- execl(HELPER,HELPER,addrarg,portarg,afarg,(char*)0);
- status= errno > 0 && errno < 127 ? errno : 127;
- STDERRSTR_CONST("libauthbind: possible installation problem - "
- "could not invoke " HELPER "\n");
- exiterrno(status);
- }
-
- rchild= waitpid(child,&status,0);
- if (rchild==-1) goto x_err;
- if (rchild!=child) { errno= ECHILD; goto x_err; }
-
- if (WIFEXITED(status)) {
- if (WEXITSTATUS(status)) {
- errno= WEXITSTATUS(status);
- if (errno >= 127) errno= ENXIO;
- goto x_err;
- }
- r= 0;
- goto x;
- } else {
- errno= ENOSYS;
- goto x_err;
- }
-
-x_err:
- r= -1;
-x:
- if (sigprocmask(SIG_SETMASK,&saved,0)) abort();
- if (restore_sigchild) {
- if (sigaction(SIGCHLD,&old_sigchild,NULL)) return -1;
- if (old_sigchild.sa_handler == SIG_IGN) {
- int discard;
- while (waitpid(-1, &discard, WNOHANG) > 0)
- ;
- }
- }
- return r;