xwayland: query window PIDs via XResQueryClientIds

`_NET_WM_PID` is unreliable: it is optional and even if set it may
contain PIDs from sandbox namespaces or remote systems.
Prefer XRes v1.2 QueryClientIds method which returns PIDs as seen by the
Xwayland server.
This commit is contained in:
Aleksei Bavshin 2021-04-16 19:27:12 -07:00 committed by Simon Ser
parent c314920a3d
commit e0f239fa28
3 changed files with 65 additions and 0 deletions

View File

@ -113,6 +113,7 @@ struct wlr_xwm {
struct wlr_xwayland_surface *drag_focus;
const xcb_query_extension_reply_t *xfixes;
const xcb_query_extension_reply_t *xres;
#if HAS_XCB_ERRORS
xcb_errors_context_t *errors_context;
#endif

View File

@ -4,6 +4,7 @@ xwayland_required = [
'xcb-composite',
'xcb-icccm',
'xcb-render',
'xcb-res',
'xcb-xfixes',
]
xwayland_optional = {

View File

@ -14,6 +14,7 @@
#include <wlr/xwayland.h>
#include <xcb/composite.h>
#include <xcb/render.h>
#include <xcb/res.h>
#include <xcb/xcb_icccm.h>
#include <xcb/xfixes.h>
#include "util/signal.h"
@ -510,6 +511,41 @@ static void read_surface_parent(struct wlr_xwm *xwm,
wlr_signal_emit_safe(&xsurface->events.set_parent, xsurface);
}
static void read_surface_client_id(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface) {
xcb_res_client_id_spec_t spec = {
.client = xsurface->window_id,
.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID
};
xcb_res_query_client_ids_cookie_t cookie = xcb_res_query_client_ids(
xwm->xcb_conn, 1, &spec);
xcb_res_query_client_ids_reply_t *reply = xcb_res_query_client_ids_reply(
xwm->xcb_conn, cookie, NULL);
if (reply == NULL) {
return;
}
uint32_t *pid = NULL;
xcb_res_client_id_value_iterator_t iter =
xcb_res_query_client_ids_ids_iterator(reply);
while (iter.rem > 0) {
if (iter.data->spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID &&
xcb_res_client_id_value_value_length(iter.data) > 0) {
pid = xcb_res_client_id_value_value(iter.data);
break;
}
xcb_res_client_id_value_next(&iter);
}
if (pid == NULL) {
free(reply);
return;
}
xsurface->pid = *pid;
wlr_signal_emit_safe(&xsurface->events.set_pid, xsurface);
free(reply);
}
static void read_surface_pid(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface,
xcb_get_property_reply_t *reply) {
@ -818,6 +854,9 @@ static void xwm_map_shell_surface(struct wlr_xwm *xwm,
for (size_t i = 0; i < sizeof(props)/sizeof(xcb_atom_t); i++) {
read_surface_property(xwm, xsurface, props[i]);
}
if (xwm->xres) {
read_surface_client_id(xwm, xsurface);
}
xsurface->surface_destroy.notify = handle_surface_destroy;
wl_signal_add(&surface->events.destroy, &xsurface->surface_destroy);
@ -1621,6 +1660,7 @@ void xwm_destroy(struct wlr_xwm *xwm) {
static void xwm_get_resources(struct wlr_xwm *xwm) {
xcb_prefetch_extension_data(xwm->xcb_conn, &xcb_xfixes_id);
xcb_prefetch_extension_data(xwm->xcb_conn, &xcb_composite_id);
xcb_prefetch_extension_data(xwm->xcb_conn, &xcb_res_id);
size_t i;
xcb_intern_atom_cookie_t cookies[ATOM_LAST];
@ -1664,6 +1704,29 @@ static void xwm_get_resources(struct wlr_xwm *xwm) {
xfixes_reply->major_version, xfixes_reply->minor_version);
free(xfixes_reply);
const xcb_query_extension_reply_t *xres =
xcb_get_extension_data(xwm->xcb_conn, &xcb_res_id);
if (!xres || !xres->present) {
return;
}
xcb_res_query_version_cookie_t xres_cookie =
xcb_res_query_version(xwm->xcb_conn, XCB_RES_MAJOR_VERSION,
XCB_RES_MINOR_VERSION);
xcb_res_query_version_reply_t *xres_reply =
xcb_res_query_version_reply(xwm->xcb_conn, xres_cookie, NULL);
if (xres_reply == NULL) {
return;
}
wlr_log(WLR_DEBUG, "xres version: %" PRIu32 ".%" PRIu32,
xres_reply->server_major, xres_reply->server_minor);
if (xres_reply->server_major > 1 ||
(xres_reply->server_major == 1 && xres_reply->server_minor >= 2)) {
xwm->xres = xres;
}
free(xres_reply);
}
static void xwm_create_wm_window(struct wlr_xwm *xwm) {