SCM_RIGHTS: XTrans vs ssh forwarding with MIT-SHM clients

4 views
Skip to first unread message

Jeremy Huddleston Sequoia

unread,
Jan 16, 2023, 3:58:29 AM1/16/23
to X.Org Development
A user reported (https://github.com/XQuartz/XQuartz/issues/314) that running `feh` on a remote system would hang the process without producing any windows when they updated from an older XQuartz server to a newer one.

I traced this to a difference in autoconf vs meson builds. With meson, we're setting XTRANS_SEND_FDS whereas with autoconf, we weren't:

if cc.has_header_symbol('sys/socket.h', 'SCM_RIGHTS')
conf_data.set('XTRANS_SEND_FDS', '1')
endif

vs

linux*|solaris*|freebsd*|dragonfly*|openbsd*)
XTRANS_SEND_FDS=yes
;;
*)
XTRANS_SEND_FDS=no
;;

This change certainly looks fine to me. darwin supports SCM_RIGHTS. It was probably just overlooked in that configure.ac condition, and it never caused enough of a problem for someone to notice.

So I turned my attention to figuring out why things aren't working with XTRANS_SEND_FDS set...

Soon after launching `feh`, it enters ProcShmCreateSegment. With local and unix connections, we try using SCM_RIGHTS to send an fd in the reply (_XSERVTransSocketSendFd). With inet, inet6, and tcp, we skip sending the FD (_XSERVTransSocketSendFdInvalid). This all sounds fine and good except that ssh forwarding throws a wrench into things...

When we use ssh forwarding with a local DISPLAY (eg: `DISPLAY=:0 ssh -Y some.host`), the X11 server ends up seeing this as a local connection (thus using _XSERVTransSocketLocalFuncs) and uses SCM_RIGHTS to send a fd. On the server, we successfully send the message with FDs attached. On the client, we receive a reply, but there is no fd, so xcb continues to wait (specifically, read_fds() fails and we end up stuck in wait_for_reply()).

Now, I haven't dug into what's happening between the server and client, but I suspect OpenSSH just drops the FDs on the floor without logging a warning to the user and passes the rest of the message along.

So there seem to be two issues here:

1 - libxcb should recover from this.
2 - The server should be able to determine that the transport does not support SCM_RIGHTS.

---

How should this work? Why hasn't this been reported as an issue on other platforms? This all seems pretty platform agnostic, so I'd expect this to be an issue on other platforms as well. Is it not? If not, why not?

Thanks,
Jeremy

Michel Dänzer

unread,
Jan 16, 2023, 4:20:34 AM1/16/23
to Jeremy Huddleston Sequoia, X.Org Development
On 1/16/23 06:31, Jeremy Huddleston Sequoia wrote:
>
> How should this work? Why hasn't this been reported as an issue on other platforms? This all seems pretty platform agnostic, so I'd expect this to be an issue on other platforms as well. Is it not? If not, why not?

ComputeLocalClient attempts to detect SSH clients and treats them as non-local. Maybe this isn't working on macos for some reason?


--
Earthling Michel Dänzer | https://redhat.com
Libre software enthusiast | Mesa and Xwayland developer

Jeremy Huddleston Sequoia

unread,
Jan 17, 2023, 5:07:43 AM1/17/23
to Michel Dänzer, X.Org Development
Yep, thanks for the pointer. Looks like DetermineClientCmd() needs to be implemented for darwin.

Jeremy Huddleston Sequoia

unread,
Jan 18, 2023, 2:43:34 PM1/18/23
to Michel Dänzer, X.Org Development
After implementing DetermineClientCmd for darwin (https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1040), we still have an issue.  We still do not know the pid of the peer (which we need to pass DetermineClientCmd).

We expect to determine the pid in GetLocalClientCreds().  Looking into that function, I expect it to be failing on other UNIX as well.  GetLocalClientCreds() prefers getpeereid() if getpeereid() is available.  getpeereid(), however, only returns uid and gid.  If getpeereid() is not available, the implementation will try getpeerucred() or SO_PEERCRED (both of which *DO* return the pid in addition to uid/gid).  So it looks like this should only be working if getpeereid() is NOT available and getpeerucred() or SO_PEERCRED are available.

Am I missing something?  How is this ssh detection working on other UNIX systems that have getpeereid right now (or is it not)?.

Alan Coopersmith

unread,
Jan 18, 2023, 3:57:04 PM1/18/23
to xorg-...@lists.x.org
Solaris only has getpeerucred(), not getpeereid(), so this hasn't affected us.

-alan-

On 1/18/23 11:43, Jeremy Huddleston Sequoia wrote:
> After implementing DetermineClientCmd for darwin
> (https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1040
> <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1040>), we still
--
-Alan Coopersmith- alan.coo...@oracle.com
Oracle Solaris Engineering - https://blogs.oracle.com/solaris

Aaron Plattner

unread,
Feb 3, 2023, 5:12:05 PM2/3/23
to Jeremy Huddleston Sequoia, Michel Dänzer, X.Org Development

At least on Arch Linux, getpeereid() is only defined in bsd/unistd.h and Meson doesn't seem to find it. HAVE_GETPEEREID is undefined and GetLocalClientCreds() ends up in the `defined(SO_PEERCRED)` path.

I agree that it's just broken on platforms that have getpeereid().

-- Aaron

Reply all
Reply to author
Forward
0 new messages