https://bugs.kde.org/show_bug.cgi?id=420921

            Bug ID: 420921
           Summary: execute_kwallet() accidentally closes syslog socket,
                    which results in failure to listen() on its own
                    socket, breaking kwalletd
           Product: kwallet-pam
           Version: unspecified
          Platform: Debian unstable
                OS: Linux
            Status: REPORTED
          Severity: major
          Priority: NOR
         Component: general
          Assignee: plasma-b...@kde.org
          Reporter: k...@kdebugs.elan.rulez.org
  Target Milestone: ---

SUMMARY

execute_kwallet() closes many of its inherited file descriptors, which includes
the one used for syslog() previously (I assume by pam_syslog()). However,
somewhere there is still global state that remembers that FD number.

The function goes on to create envSocket of type SOCK_STREAM, then calls
syslog() to log a debug message, and eventually tries to listen on envSocket.

The problem is that envSocket ends up having the same FD as the one saved for
syslog in global state; so in the call to syslog(), libc(?) closes the FD and
reopens it for logging as SOCK_DGRAM. listen() won't work on a datagram socket,
so that the listen() call fails and kwalletd does not run.

Severity set to major because this makes pam_kwallet unusable. There are a
number of reports scattered in various forums about this, but I didn't find an
actual bug report.

strace:

socket(AF_UNIX, SOCK_STREAM, 0)         = 3 // this is the 'envSocket =
socket(AF_UNIX, SOCK_STREAM, 0)' call
unlink("/run/user/xxxx/kwallet5.socket") = -1 ENOENT (No such file or
directory)
getpid()                                = xxxx
sendto(3, "<87>[some date] lightdm[xxxx]: pam_kwallet5: final socket path:
/run/user/xxxx/kwallet5.socket", 98, MSG_NOSIGNAL, NULL, 0) = -1 ENOTCONN
(Transport endpoint is not connected) // this is the syslog() call
close(3)                 = 0 // this is syslog() being smart about apparently
having lost its connection to /dev/log
socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/dev/log"}, 110) = 0
sendto(3, "<87>[some date] lightdm[xxxx]: pam_kwallet5: final socket path:
/run/user/1011/kwallet5.socket", 98, MSG_NOSIGNAL, NULL, 0) = 98        // this
is where syslog() actually logs the message, but FD3 is already SOCK_DGRAM
bind(3, {sa_family=AF_UNIX, sun_path="/run/user/xxxx/kwallet5.socket"}, 32) = 0
   // we're back from syslog() and in execute_kwallet() but at this point, FD3
is already a SOCK_DGRAM
listen(3, 5)      = -1 EOPNOTSUPP (Operation not supported)                    
   // so listen() fails

STEPS TO REPRODUCE

Try to start kwalletd from pam.

OBSERVED RESULT

kwalletd doesn't start and instead logs "pam_kwallet5-kwalletd: Couldn't listen
in socket"

EXPECTED RESULT

kwalletd starts and listens on its Unix domain socket.

SOFTWARE/OS VERSIONS
Windows: 
macOS: 
Linux/KDE Plasma: all
(available in About System)
KDE Plasma Version: reproduced with 5.17.5, but the code on github seems to be
the same
KDE Frameworks Version: 
Qt Version: irrelevant

ADDITIONAL INFORMATION

Calling closelog() explicitly might be a fix.

Also, how do you know there are no inherited FDs above 63 you need to close?
Maybe you know, but in that case a comment that points this out would be
helpful. Currently the loop boundary at the beginning of the function looks
like either magic or a guess.

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to