Bug 3345 - sshd freeze when build without HAVE_PSELECT
Summary: sshd freeze when build without HAVE_PSELECT
Status: CLOSED FIXED
Alias: None
Product: Portable OpenSSH
Classification: Unclassified
Component: sshd (show other bugs)
Version: 8.7p1
Hardware: Itanium Other
: P5 normal
Assignee: Assigned to nobody
URL:
Keywords:
Depends on:
Blocks: V_8_8
  Show dependency treegraph
 
Reported: 2021-09-07 20:55 AEST by Yaroslav
Modified: 2022-02-25 13:57 AEDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Yaroslav 2021-09-07 20:55:09 AEST
In openbsd-compat/bsd-pselect.c file in pselect() function.

Line 196 incorrect call to select() function.
If unmasked !=0 , nfds need +1
 
   8   if (unmasked) {
   7     pselect_notify_setup();
   6     pselect_notify_prepare(readfds);
   5     nfds = MAX(nfds, notify_pipe[0]);
   4   }
   3 
   2   /* Unmask signals, call select then restore signal mask. */
   1   sigprocmask(SIG_SETMASK, mask, &osig);
 196   ret = select(nfds, readfds, writefds, exceptfds, tvp);
   1   saved_errno = errno;
   2   sigprocmask(SIG_SETMASK, &osig, NULL);
   3 
   4   if (unmasked)
   5     pselect_notify_done(readfds);
Comment 1 Darren Tucker 2021-09-08 11:31:11 AEST
(In reply to Yaroslav from comment #0)
> In openbsd-compat/bsd-pselect.c file in pselect() function.
> 
> Line 196 incorrect call to select() function.
> If unmasked !=0 , nfds need +1

For the common case nfds should already have the 1 added by the caller, eg in sshd.c:

    /* Wait until a connection arrives or a child exits. */
    ret = pselect(maxfd+1, fdset, NULL, NULL, NULL, &osigset);

I could see this being a problem in the case where notify_pipe[0] is higher than any descriptor in the fdsets, in which case I think the +1 should be added to notify_pipe[0]:

          nfds = MAX(nfds, notify_pipe[0]+1);

Would that solve the problem?  Also, out of curiosity, what platform is this (you indicated "Other")?
Comment 2 Yaroslav 2021-09-08 13:56:21 AEST
I added the following code and it solved the problem

200     nfds = MAX(nfds, notify_pipe[0]);
201     ++nfds;

I am porting OpenSSH to OpenVMS.
Comment 3 Darren Tucker 2021-09-08 15:21:39 AEST
(In reply to Yaroslav from comment #2)
> I added the following code and it solved the problem
> 
> 200     nfds = MAX(nfds, notify_pipe[0]);
> 201     ++nfds;

As I described above I don't think that's correct.  In the case where nfds was not increased in the MAX(), nfds is being incremented twice which may cause other problems.

The code I suggested does not do that.  Does it also fix the problem?
Comment 4 Yaroslav 2021-09-08 16:30:47 AEST
(In reply to Darren Tucker from comment #3)
> (In reply to Yaroslav from comment #2)
> > I added the following code and it solved the problem
> > 
> > 200     nfds = MAX(nfds, notify_pipe[0]);
> > 201     ++nfds;
> 
> As I described above I don't think that's correct.  In the case
> where nfds was not increased in the MAX(), nfds is being incremented
> twice which may cause other problems.
> 
> The code I suggested does not do that.  Does it also fix the problem?

I tested on 5 connections everything works correctly.

But I agree that nfsd  contains information about the number of file descriptors, and MAX  will check the maximum descriptor


  if (unmasked) {
    pselect_notify_setup();
    pselect_notify_prepare(readfds);
    --nfds;
    nfds = MAX(nfds, notify_pipe[0]);
    ++nfds;
 }
Comment 5 Darren Tucker 2021-09-08 18:53:33 AEST
Thanks, I have committed the fix and cherry-picked it into the 8.7 branch so it will be in the next release.
Comment 6 Damien Miller 2022-02-25 13:57:16 AEDT
closing bugs resolved before openssh-8.9