Skip to content

Commit

Permalink
Detect local X start by socket creation if dropping privileges
Browse files Browse the repository at this point in the history
* A depriviledged X cannot send back a SIGUSR1 when it is ready
  • Loading branch information
twhitehead committed Aug 4, 2020
1 parent 5fd7e78 commit 1e59ef4
Showing 1 changed file with 52 additions and 1 deletion.
53 changes: 52 additions & 1 deletion src/x-server-local.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ typedef struct
/* TRUE when received ready signal */
gboolean got_signal;

/* Poll source ID (fallback for signal if uids differ) */
guint poll_for_socket_source;

/* VT to run on */
gint vt;
gboolean have_vt_ref;
Expand Down Expand Up @@ -391,6 +394,46 @@ got_signal_cb (Process *process, int signum, XServerLocal *server)
}
}

static gboolean
poll_for_socket_cb (XServerLocal *server)
{
XServerLocalPrivate *priv = x_server_local_get_instance_private (server);

/* Check is X11 socket file exists as an alternative startup test to SIGUSR1 */
GStatBuf statbuf;
g_autofree gchar *socketpath = g_strdup_printf ("/tmp/.X11-unix/X%d", priv->display_number);
if ( g_stat (socketpath, &statbuf) == 0 )
{
uid_t uid = priv->user ? user_get_uid(priv->user) : 0;

/* It has to be a valid socket file */
if (!(statbuf.st_mode & S_IFSOCK))
{
l_debug (server, "X11 socket file is not a socket: %s", socketpath);
return G_SOURCE_REMOVE;
}

/* It has to be owned by the correct user */
if (statbuf.st_uid != uid)
{
l_debug (server, "X11 socket file is not owned by uid %d: %s", uid, socketpath);
return G_SOURCE_REMOVE;
}

/* Consider SIGUSR1 to have been recieved */
priv->got_signal = TRUE;
l_debug (server, "Detected valid X11 socket for X server :%d", priv->display_number);

// FIXME: Check return value
DISPLAY_SERVER_CLASS (x_server_local_parent_class)->start (DISPLAY_SERVER (server));

return G_SOURCE_REMOVE;
}

/* Wait another second and check again */
return G_SOURCE_CONTINUE;
}

static void
stopped_cb (Process *process, XServerLocal *server)
{
Expand Down Expand Up @@ -468,7 +511,10 @@ x_server_local_start (DisplayServer *display_server)
ProcessRunFunc run_cb = X_SERVER_LOCAL_GET_CLASS (server)->get_run_function (server);
priv->x_server_process = process_new (run_cb, server);
process_set_clear_environment (priv->x_server_process, TRUE);
g_signal_connect (priv->x_server_process, PROCESS_SIGNAL_GOT_SIGNAL, G_CALLBACK (got_signal_cb), server);
if (priv->user == NULL || user_get_uid (priv->user) == getuid ())
g_signal_connect (priv->x_server_process, PROCESS_SIGNAL_GOT_SIGNAL, G_CALLBACK (got_signal_cb), server);
else if (!priv->poll_for_socket_source)
priv->poll_for_socket_source = g_timeout_add_seconds (1, (GSourceFunc)poll_for_socket_cb, server);
g_signal_connect (priv->x_server_process, PROCESS_SIGNAL_STOPPED, G_CALLBACK (stopped_cb), server);

/* Setup logging */
Expand Down Expand Up @@ -594,6 +640,11 @@ x_server_local_finalize (GObject *object)

if (priv->x_server_process)
g_signal_handlers_disconnect_matched (priv->x_server_process, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
if (priv->poll_for_socket_source)
{
g_source_remove (priv->poll_for_socket_source);
priv->poll_for_socket_source = 0;
}
g_clear_object (&priv->x_server_process);
g_clear_pointer (&priv->command, g_free);
g_clear_object (&priv->user);
Expand Down

0 comments on commit 1e59ef4

Please sign in to comment.