1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-06-27 01:28:45 -05:00

Fix crash in utmp-stamping on Wayland.

Thanks to Colin Watson for the report: if pterm is both
able (appropriately setgid) and willing (given the right options) to
stamp utmp, it will use $DISPLAY as the location to write into utmp,
and segfault if it's not set. But in a Wayland-only system it might
very well not be set.

To fix this I've generalised seat_get_x_display() into
seat_get_display(), so that it can also return a display id string
like "wayland-0" if that's what's appropriate. So now in that
situation pterm will stamp utmp with a Wayland display id in place of
an X11 one.

However, seat_get_x_display() was also used to retrieve an X11 display
name specifically so as to populate $DISPLAY in the terminal's shell.
So the new seat_get_display() has a parameter to constrain the
returned display to be of a particular type, or NULL if that type
isn't available.

As a final fallback, in case seat_get_display(seat, SDISP_ANY) might
_still_ manage to return NULL for any reason, we catch that and turn
it into the empty string before stamping utmp, so that we still won't
segfault.
This commit is contained in:
Simon Tatham 2025-06-25 13:02:56 +01:00
parent 91ad3af01c
commit 26a8ef376d
13 changed files with 40 additions and 28 deletions

View File

@ -583,7 +583,7 @@ static const SeatVtable SshProxy_seat_vt = {
.prompt_descriptions = sshproxy_prompt_descriptions,
.is_utf8 = nullseat_is_never_utf8,
.echoedit_update = nullseat_echoedit_update,
.get_x_display = nullseat_get_x_display,
.get_display = nullseat_get_display,
.get_windowid = nullseat_get_windowid,
.get_window_pixel_size = nullseat_get_window_pixel_size,
.stripctrl_new = sshproxy_stripctrl_new,

2
pscp.c
View File

@ -81,7 +81,7 @@ static const SeatVtable pscp_seat_vt = {
.prompt_descriptions = console_prompt_descriptions,
.is_utf8 = nullseat_is_never_utf8,
.echoedit_update = nullseat_echoedit_update,
.get_x_display = nullseat_get_x_display,
.get_display = nullseat_get_display,
.get_windowid = nullseat_get_windowid,
.get_window_pixel_size = nullseat_get_window_pixel_size,
.stripctrl_new = console_stripctrl_new,

View File

@ -62,7 +62,7 @@ static const SeatVtable psftp_seat_vt = {
.prompt_descriptions = console_prompt_descriptions,
.is_utf8 = nullseat_is_never_utf8,
.echoedit_update = nullseat_echoedit_update,
.get_x_display = nullseat_get_x_display,
.get_display = nullseat_get_display,
.get_windowid = nullseat_get_windowid,
.get_window_pixel_size = nullseat_get_window_pixel_size,
.stripctrl_new = console_stripctrl_new,

20
putty.h
View File

@ -1070,6 +1070,11 @@ void seat_dialog_text_free(SeatDialogText *sdt);
PRINTF_LIKE(3, 4) void seat_dialog_text_append(
SeatDialogText *sdt, SeatDialogTextType type, const char *fmt, ...);
/* Parameter to seat_get_display */
typedef enum SeatDisplayType {
SDISP_X11, SDISP_ANY
} SeatDisplayType;
/*
* Data type 'Seat', which is an API intended to contain essentially
* everything that a back end might need to talk to its client for:
@ -1299,10 +1304,13 @@ struct SeatVtable {
void (*echoedit_update)(Seat *seat, bool echoing, bool editing);
/*
* Return the local X display string relevant to a seat, or NULL
* if there isn't one or if the concept is meaningless.
* Return a string describing the GUI display (e.g. X11 or
* Wayland) relevant to a seat, or NULL if there isn't one or if
* the concept is meaningless. If dtype is not SDISP_ANY then only
* a display string of the requested type will be returned, or
* NULL if the available display is of a different type.
*/
const char *(*get_x_display)(Seat *seat);
const char *(*get_display)(Seat *seat, SeatDisplayType dtype);
/*
* Return the X11 id of the X terminal window relevant to a seat,
@ -1426,8 +1434,8 @@ static inline bool seat_is_utf8(Seat *seat)
{ return seat->vt->is_utf8(seat); }
static inline void seat_echoedit_update(Seat *seat, bool ec, bool ed)
{ seat->vt->echoedit_update(seat, ec, ed); }
static inline const char *seat_get_x_display(Seat *seat)
{ return seat->vt->get_x_display(seat); }
static inline const char *seat_get_display(Seat *seat, SeatDisplayType dtype)
{ return seat->vt->get_display(seat, dtype); }
static inline bool seat_get_windowid(Seat *seat, long *id_out)
{ return seat->vt->get_windowid(seat, id_out); }
static inline bool seat_get_window_pixel_size(Seat *seat, int *w, int *h)
@ -1515,7 +1523,7 @@ const SeatDialogPromptDescriptions *nullseat_prompt_descriptions(Seat *seat);
bool nullseat_is_never_utf8(Seat *seat);
bool nullseat_is_always_utf8(Seat *seat);
void nullseat_echoedit_update(Seat *seat, bool echoing, bool editing);
const char *nullseat_get_x_display(Seat *seat);
const char *nullseat_get_display(Seat *seat, SeatDisplayType dtype);
bool nullseat_get_windowid(Seat *seat, long *id_out);
bool nullseat_get_window_pixel_size(Seat *seat, int *width, int *height);
StripCtrlChars *nullseat_stripctrl_new(

View File

@ -126,7 +126,7 @@ static const SeatVtable server_seat_vt = {
.prompt_descriptions = nullseat_prompt_descriptions,
.is_utf8 = nullseat_is_never_utf8,
.echoedit_update = nullseat_echoedit_update,
.get_x_display = nullseat_get_x_display,
.get_display = nullseat_get_display,
.get_windowid = nullseat_get_windowid,
.get_window_pixel_size = nullseat_get_window_pixel_size,
.stripctrl_new = nullseat_stripctrl_new,

View File

@ -203,7 +203,7 @@ static const SeatVtable sesschan_seat_vt = {
.prompt_descriptions = nullseat_prompt_descriptions,
.is_utf8 = nullseat_is_never_utf8,
.echoedit_update = nullseat_echoedit_update,
.get_x_display = nullseat_get_x_display,
.get_display = nullseat_get_display,
.get_windowid = nullseat_get_windowid,
.get_window_pixel_size = sesschan_get_window_pixel_size,
.stripctrl_new = nullseat_stripctrl_new,
@ -310,7 +310,7 @@ static void sesschan_start_backend(sesschan *sess, const char *cmd)
* confusingly set in the absence of that.
*
* (DISPLAY must also be cleared, but pty.c will do that anyway
* when our get_x_display method returns NULL.)
* when our get_display method returns NULL.)
*/
static const char *const env_to_unset[] = {
"XAUTHORITY", "SSH_AUTH_SOCK", "SSH_AGENT_PID",

View File

@ -37,7 +37,8 @@ SeatPromptResult nullseat_confirm_weak_cached_hostkey(
bool nullseat_is_never_utf8(Seat *seat) { return false; }
bool nullseat_is_always_utf8(Seat *seat) { return true; }
void nullseat_echoedit_update(Seat *seat, bool echoing, bool editing) {}
const char *nullseat_get_x_display(Seat *seat) { return NULL; }
const char *nullseat_get_display(Seat *seat, SeatDisplayType dtype)
{ return NULL; }
bool nullseat_get_windowid(Seat *seat, long *id_out) { return false; }
bool nullseat_get_window_pixel_size(
Seat *seat, int *width, int *height) { return false; }

View File

@ -419,7 +419,7 @@ static const SeatVtable plink_seat_vt = {
.prompt_descriptions = console_prompt_descriptions,
.is_utf8 = nullseat_is_never_utf8,
.echoedit_update = plink_echoedit_update,
.get_x_display = nullseat_get_x_display,
.get_display = nullseat_get_display,
.get_windowid = nullseat_get_windowid,
.get_window_pixel_size = nullseat_get_window_pixel_size,
.stripctrl_new = console_stripctrl_new,

View File

@ -958,7 +958,10 @@ Backend *pty_backend_create(
close(pty_utmp_helper_pipe);
pty_utmp_helper_pipe = -1;
} else {
const char *location = seat_get_x_display(pty->seat);
const char *location = seat_get_display(pty->seat, SDISP_ANY);
if (!location)
location = "";
int len = strlen(location)+1, pos = 0; /* +1 to include NUL */
while (pos < len) {
int ret = write(pty_utmp_helper_pipe,
@ -1133,7 +1136,7 @@ Backend *pty_backend_create(
* terminal to match the display the terminal itself is
* on.
*/
const char *x_display = seat_get_x_display(pty->seat);
const char *x_display = seat_get_display(pty->seat, SDISP_X11);
if (x_display) {
char *x_display_env_var = dupprintf("DISPLAY=%s", x_display);
putenv(x_display_env_var);

View File

@ -402,7 +402,7 @@ static void gtk_seat_notify_remote_exit(Seat *seat);
static void gtk_seat_update_specials_menu(Seat *seat);
static void gtk_seat_set_busy_status(Seat *seat, BusyStatus status);
#ifndef NOT_X_WINDOWS
static const char *gtk_seat_get_x_display(Seat *seat);
static const char *gtk_seat_get_display(Seat *seat, SeatDisplayType dtype);
static bool gtk_seat_get_windowid(Seat *seat, long *id);
#endif
static void gtk_seat_set_trust_status(Seat *seat, bool trusted);
@ -430,10 +430,10 @@ static const SeatVtable gtk_seat_vt = {
.is_utf8 = gtk_seat_is_utf8,
.echoedit_update = nullseat_echoedit_update,
#ifdef NOT_X_WINDOWS
.get_x_display = nullseat_get_x_display,
.get_display = nullseat_get_display,
.get_windowid = nullseat_get_windowid,
#else
.get_x_display = gtk_seat_get_x_display,
.get_display = gtk_seat_get_display,
.get_windowid = gtk_seat_get_windowid,
#endif
.get_window_pixel_size = gtk_seat_get_window_pixel_size,
@ -4331,11 +4331,11 @@ void modalfatalbox(const char *p, ...)
}
#ifndef NOT_X_WINDOWS
static const char *gtk_seat_get_x_display(Seat *seat)
static const char *gtk_seat_get_display(Seat *seat, SeatDisplayType dtype)
{
if (GDK_IS_X11_DISPLAY(gdk_display_get_default()))
return gdk_get_display();
if (dtype == SDISP_X11 && !GDK_IS_X11_DISPLAY(gdk_display_get_default()))
return NULL;
return gdk_get_display();
}
static bool gtk_seat_get_windowid(Seat *seat, long *id)

View File

@ -149,10 +149,10 @@ static bool tempseat_is_utf8(Seat *seat)
return seat_is_utf8(ts->realseat);
}
static const char *tempseat_get_x_display(Seat *seat)
static const char *tempseat_get_display(Seat *seat, SeatDisplayType dtype)
{
TempSeat *ts = container_of(seat, TempSeat, seat);
return seat_get_x_display(ts->realseat);
return seat_get_display(ts->realseat, dtype);
}
static bool tempseat_get_windowid(Seat *seat, long *id_out)
@ -348,7 +348,7 @@ static const struct SeatVtable tempseat_vt = {
.prompt_descriptions = tempseat_prompt_descriptions,
.is_utf8 = tempseat_is_utf8,
.echoedit_update = tempseat_echoedit_update,
.get_x_display = tempseat_get_x_display,
.get_display = tempseat_get_display,
.get_windowid = tempseat_get_windowid,
.get_window_pixel_size = tempseat_get_window_pixel_size,
.stripctrl_new = tempseat_stripctrl_new,

View File

@ -107,7 +107,7 @@ static const SeatVtable plink_seat_vt = {
.prompt_descriptions = console_prompt_descriptions,
.is_utf8 = nullseat_is_never_utf8,
.echoedit_update = plink_echoedit_update,
.get_x_display = nullseat_get_x_display,
.get_display = nullseat_get_display,
.get_windowid = nullseat_get_windowid,
.get_window_pixel_size = nullseat_get_window_pixel_size,
.stripctrl_new = console_stripctrl_new,

View File

@ -267,7 +267,7 @@ static const SeatVtable win_seat_vt = {
.prompt_descriptions = win_seat_prompt_descriptions,
.is_utf8 = win_seat_is_utf8,
.echoedit_update = nullseat_echoedit_update,
.get_x_display = nullseat_get_x_display,
.get_display = nullseat_get_display,
.get_windowid = nullseat_get_windowid,
.get_window_pixel_size = win_seat_get_window_pixel_size,
.stripctrl_new = win_seat_stripctrl_new,