> 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;
>         }
> 

Reply via email to