Skip to content

Commit

Permalink
vncserver: Check a display #'s abstract socket
Browse files Browse the repository at this point in the history
... before assuming that the display number is available.

Newer versions of GDM use Display :0 for the greeter and Display :1 for
the session if WaylandEnable=false.  However, X11 lock files are no
longer used, and the session's X server still functions if its Unix
domain socket (/tmp/.X11-unix/X1) is deleted.  Thus, if a user logged in
locally, accidentally deleted /tmp/.X11-unix/X1, then tried to start a
TurboVNC session, vncserver would attempt to use Display :1, and the
window manager in the TurboVNC session would subsequently fail to start.

Based on:
algorythmic@1028467

Note that the aforementioned commit attempts to actually open the
Unix domain socket rather than checking for the existence of the socket
file.  However, I could find no cases in which the ability to open a
Unix domain socket was not determined by the existence of the socket
file.
  • Loading branch information
dcommander committed Jan 3, 2024
1 parent 78d9c9a commit bc73242
Showing 1 changed file with 27 additions and 8 deletions.
35 changes: 27 additions & 8 deletions unix/vncserver.in
Original file line number Diff line number Diff line change
Expand Up @@ -628,9 +628,7 @@ sub CheckGeometryAndDepth


#
# GetDisplayNumber gets the lowest available display number. A display number
# n is taken if something is listening on the VNC server port (5900+n) or the
# X server port (6000+n).
# GetDisplayNumber gets the lowest available display number.
#

sub GetDisplayNumber
Expand All @@ -647,8 +645,15 @@ sub GetDisplayNumber

#
# CheckDisplayNumber checks if the given display number is available. A
# display number n is taken if something is listening on the VNC server port
# (5900+n) or the X server port (6000+n).
# display number $n is taken if any of the following are true:
#
# - something is listening on the X server port (6000+$n)
# - something is listening on the VNC server port (5900+$n)
# - -novnc/$noVNC is specified and something is listening on the web server
# port (5800+$n)
# - (Linux only) the abstract socket \0/tmp/.X11-unix/X$n is in use
# - the lock file /tmp/.X$n-lock exists
# - the Unix domain socket /tmp/.X11-unix/X$n exists
#

sub CheckDisplayNumber
Expand Down Expand Up @@ -681,6 +686,16 @@ sub CheckDisplayNumber
close(S);
}

if ($os eq "Linux") {
socket(S, $AF_UNIX, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n";
unless (bind(S, pack_sockaddr_un("\0/tmp/.X11-unix/X$n"))) {
warn "\nWARNING: $host:$n is taken because abstract socket \\0/tmp/.X11-unix/X$n is in use.\n";
close(S);
return 0;
}
close(S);
}

if (-e "/tmp/.X$n-lock") {
warn "\nWARNING: $host:$n is taken because of /tmp/.X$n-lock\n";
warn "Remove this file if there is no X server $host:$n\n";
Expand Down Expand Up @@ -1092,9 +1107,9 @@ sub SanityCheck
# Find socket constants. 'use Socket' is a perl5-ism, so we wrap it in an
# eval, and if it fails we try 'require "sys/socket.ph"'. If this fails,
# we just guess at the values. If you find perl moaning here, just
# hard-code the values of AF_INET and SOCK_STREAM. You can find these out
# for your platform by looking in /usr/include/sys/socket.h and related
# files.
# hard-code the values of AF_UNIX, AF_INET, and SOCK_STREAM. You can find
# these out for your platform by looking in /usr/include/sys/socket.h and
# related files.
#

chop($os = `uname`);
Expand All @@ -1105,17 +1120,21 @@ sub SanityCheck
eval 'require "sys/socket.ph"';
if ($@) {
if (($os eq "SunOS") && ($osrev !~ /^4/)) {
$AF_UNIX = 1;
$AF_INET = 2;
$SOCK_STREAM = 2;
} else {
$AF_UNIX = 1;
$AF_INET = 2;
$SOCK_STREAM = 1;
}
} else {
$AF_UNIX = &AF_UNIX;
$AF_INET = &AF_INET;
$SOCK_STREAM = &SOCK_STREAM;
}
} else {
$AF_UNIX = &AF_UNIX;
$AF_INET = &AF_INET;
$SOCK_STREAM = &SOCK_STREAM;
}
Expand Down

0 comments on commit bc73242

Please sign in to comment.