> Date: Mon, 4 Oct 2021 22:03:32 +0200 > From: Rafael Sadowski <raf...@sizeofvoid.org> > > On Sun Sep 26, 2021 at 02:36:02PM +0200, Mark Kettenis wrote: > > > Date: Fri, 24 Sep 2021 19:36:21 +0200 > > > From: Rafael Sadowski <raf...@sizeofvoid.org> > > > > > > I'm trying to port the more KDE stuff so my question is from porter > > > perspective. > > > > > > I need sigwaitinfo(2)/sigtimedwait(2) and I found both functions in > > > lib/libc/gen/sigwait.c with the comment "need kernel to fill in more > > > siginfo_t bits first". Is the comment still up to date? If no, is it > > > possible to unlock the functions? > > > > Still true. These functions are somewhat underspecified by POSIX so > > it isn't really obvious whatadditional bits need to be filled in. > > Having examples of code that use these interfaces from ports could > > help with that. > > > > One use-case from kscreenlocker-5.22.5/kcheckpass/kcheckpass.c > > Full code: > https://github.com/KDE/kscreenlocker/blob/master/kcheckpass/kcheckpass.c > > It tries to handle SIGUSR1 and SIGUSR2. I think this can be solved in > another way, so this is a bad example, isn't it?
So they're using SIGUSR1 and SIGUSR2 as a primitive form of IPC and using si_pid to check that the signal actually came from the parent process. I suppose this is to prevent a local DOS against the password checker. If you don't care about that, you could just drop sigwaitinfo() call and the si_pid checks. > /* signal_info for sigwaitinfo() */ > siginfo_t signalInfo; > > // now lets block on the fd > for (;;) { > conv_server(ConvPutReadyForAuthentication, 0); > > keventData = kevent(keventQueue, NULL, 0, keventEvent, 1, NULL); > if (keventData == -1) { > /* Let's figure this out in the future, shall we */ > message("kevent() failed with %d\n", errno); > return 1; > } else if (keventData == 0) { > /* Do we need to handle timeouts? */ > message("kevent timeout\n"); > continue; > } > // We know we got a SIGUSR1 or SIGUSR2, so fetch it via > sigwaitinfo() > // (otherwise, we could have used sigtimedwait() ) > int signalReturn = sigwaitinfo(&signalMask, &signalInfo); > if (signalReturn < 0) { > if (errno == EINTR) { > message("sigawaitinfo() interrupted by unblocked caught > signal"); > continue; > } else if (errno == EAGAIN) { > /* This should not happen, as kevent notified us about > such a signal */ > message("no signal of type USR1 or USR2 pending."); > continue; > } else { > message("Unhandled error in sigwaitinfo()"); > conv_server(ConvPutAuthError, 0); > return 1; > } > } > if (signalReturn == SIGUSR1) { > if (signalInfo.si_pid != parentPid) { > message("signal from wrong process\n"); > continue; > } > /* Now do the fandango */ > ret = Authenticate(method, username, conv_server); > > if (ret == AuthBad) { > message("Authentication failure\n"); > if (!nullpass) { > openlog("kcheckpass", LOG_PID, LOG_AUTH); > syslog(LOG_NOTICE, "Authentication failure for %s > (invoked by uid %d)", username, uid); > } > } > switch (ret) { > case AuthOk: > conv_server(ConvPutAuthSucceeded, 0); > break; > case AuthBad: > conv_server(ConvPutAuthFailed, 0); > break; > case AuthError: > conv_server(ConvPutAuthError, 0); > break; > case AuthAbort: > conv_server(ConvPutAuthAbort, 0); > default: > break; > } > if (uid != geteuid()) { > // we don't support multiple auth for setuid kcheckpass > break; > } > } else if (signalReturn == SIGUSR2) { > if (signalInfo.si_pid != parentPid) { > message("signal from wrong process\n"); > continue; > } > break; > } >