From 78efe08c0706c2719cb12c7fcd1c8f47386d7b15 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Wed, 7 Dec 2022 19:19:34 +0800 Subject: [PATCH] Fix some more problems with running Emacs as untrusted * etc/PROBLEMS (X security problems): Describe new variable. * src/xfns.c (append_wm_protocols): Don't support ping when it does not work. * src/xterm.c (x_wm_supports_1): Don't support anything when untrusted. (x_term_init): Implement Vx_detect_server_trust. (syms_of_xterm): New variable `x-detect-server-trust'. * src/xterm.h (struct x_display_info): New field `untrusted'. --- etc/PROBLEMS | 14 ++++++++++++++ src/xfns.c | 14 ++++++++++---- src/xterm.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/xterm.h | 4 ++++ 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/etc/PROBLEMS b/etc/PROBLEMS index 2169ed0f80b..68f7cdb0560 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -1227,6 +1227,20 @@ you should use an Emacs input method instead. * X runtime problems +** X security problems + +*** Emacs faces trouble when running as an untrusted client. + +When Emacs is running as an untrusted client under X servers with the +Security extension, it is unable to use some window manager features +but reports them to the window manager anyway. This can lead to +constant prompting by the window manager about Emacs being +unresponsive. To resolve the problem, place: + + (setq x-detect-server-trust t) + +in your early-init.el. + ** X keyboard problems *** `x-focus-frame' fails to activate the frame. diff --git a/src/xfns.c b/src/xfns.c index 9951ced6611..2bf282fd243 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -2642,12 +2642,18 @@ append_wm_protocols (struct x_display_info *dpyinfo, if (existing) XFree (existing); - if (!found_wm_ping) - protos[num_protos++] = dpyinfo->Xatom_net_wm_ping; + if (!dpyinfo->untrusted) + { + /* Untrusted clients cannot use these protocols which require + communicating with the window manager. */ + + if (!found_wm_ping) + protos[num_protos++] = dpyinfo->Xatom_net_wm_ping; #if !defined HAVE_GTK3 && defined HAVE_XSYNC - if (!found_wm_sync_request && dpyinfo->xsync_supported_p) - protos[num_protos++] = dpyinfo->Xatom_net_wm_sync_request; + if (!found_wm_sync_request && dpyinfo->xsync_supported_p) + protos[num_protos++] = dpyinfo->Xatom_net_wm_sync_request; #endif + } if (num_protos) XChangeProperty (dpyinfo->display, diff --git a/src/xterm.c b/src/xterm.c index f446d093ef4..f2dbff1c446 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -26775,6 +26775,12 @@ x_wm_supports_1 (struct x_display_info *dpyinfo, Atom want_atom) if (!NILP (Vx_no_window_manager)) return false; + /* If the window system says Emacs is untrusted, there will be no + way to send any information to the window manager, making any + hints useless. */ + if (dpyinfo->untrusted) + return false; + block_input (); x_catch_errors (dpy); @@ -29507,6 +29513,7 @@ struct x_display_info * x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) { Display *dpy; + XKeyboardState keyboard_state; struct terminal *terminal; struct x_display_info *dpyinfo; XrmDatabase xrdb; @@ -29726,6 +29733,32 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) dpyinfo = xzalloc (sizeof *dpyinfo); terminal = x_create_terminal (dpyinfo); + if (!NILP (Vx_detect_server_trust)) + { + /* Detect whether or not the X server trusts this client, which + is done by making a SetKeyboardControl request and checking + for an Access error. */ + XGrabServer (dpy); + XGetKeyboardControl (dpy, &keyboard_state); + + x_catch_errors (dpy); + + /* At this point, the display is not on x_display_list, so + x_uncatch_errors won't sync. However, that's okay because + x_had_errors_p will. */ + + if (keyboard_state.global_auto_repeat + == AutoRepeatModeOn) + XAutoRepeatOn (dpy); + else + XAutoRepeatOff (dpy); + + if (x_had_errors_p (dpy)) + dpyinfo->untrusted = true; + x_uncatch_errors_after_check (); + XUngrabServer (dpy); + } + dpyinfo->next_failable_request = dpyinfo->failable_requests; { @@ -31802,4 +31835,14 @@ select text over slow X connections. If that is still too slow, setting this variable to the symbol `really-fast' will make Emacs return only cached values. */); Vx_use_fast_mouse_position = Qnil; + + DEFVAR_LISP ("x-detect-server-trust", Vx_detect_server_trust, + doc: /* Whether or not Emacs should detect whether or not it is trusted by X. + +If non-nil, Emacs will make an X request at connection startup that is +prohibited to untrusted clients under the X Security Extension and +check whether or not a resulting Access error is generated by the X +server. If the X server reports the error, then Emacs will disable +certain features that do not work for untrusted clients. */); + Vx_detect_server_trust = Qnil; } diff --git a/src/xterm.h b/src/xterm.h index fae40930e9b..c3bd647b6f3 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -376,6 +376,10 @@ struct x_display_info /* Number of frames that are on this display. */ int reference_count; + /* True if this client cannot communicate with the window manager + because it is untrusted. */ + bool untrusted; + /* The Screen this connection is connected to. */ Screen *screen; -- 2.39.2