Skip to content

Commit

Permalink
Fall back to finding DISPLAY from display server process (#1471)
Browse files Browse the repository at this point in the history
  • Loading branch information
RebeccaMahany authored Nov 22, 2023
1 parent c882f3a commit e21f39f
Showing 1 changed file with 65 additions and 5 deletions.
70 changes: 65 additions & 5 deletions ee/desktop/runner/runner_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func (r *DesktopUsersProcessesRunner) userEnvVars(ctx context.Context, uid strin

sessionType := strings.Trim(string(typeOutput), "\n")
if sessionType == "x11" {
envVars["DISPLAY"] = r.displayFromX11(ctx, session)
envVars["DISPLAY"] = r.displayFromX11(ctx, session, int32(uidInt))
break
} else if sessionType == "wayland" {
envVars["DISPLAY"] = r.displayFromXwayland(ctx, int32(uidInt))
Expand All @@ -164,33 +164,93 @@ func (r *DesktopUsersProcessesRunner) userEnvVars(ctx context.Context, uid strin
return envVars
}

func (r *DesktopUsersProcessesRunner) displayFromX11(ctx context.Context, session string) string {
func (r *DesktopUsersProcessesRunner) displayFromX11(ctx context.Context, session string, uid int32) string {
// We can read $DISPLAY from the session properties
cmd, err := allowedcmd.Loginctl(ctx, "show-session", session, "--value", "--property=Display")
if err != nil {
level.Debug(r.logger).Log(
"msg", "could not create command to get Display from user session",
"err", err,
)
return defaultDisplay
return r.displayFromXDisplayServerProcess(ctx, uid)
}
xDisplayOutput, err := cmd.Output()
if err != nil {
level.Debug(r.logger).Log(
"msg", "could not get Display from user session",
"err", err,
)
return defaultDisplay
return r.displayFromXDisplayServerProcess(ctx, uid)
}

display := strings.Trim(string(xDisplayOutput), "\n")
if display == "" {
return defaultDisplay
return r.displayFromXDisplayServerProcess(ctx, uid)
}

return display
}

func (r *DesktopUsersProcessesRunner) displayFromXDisplayServerProcess(ctx context.Context, uid int32) string {
processes, err := process.ProcessesWithContext(ctx)
if err != nil {
level.Debug(r.logger).Log(
"msg", "could not query processes to find display server process",
"err", err,
)
return defaultDisplay
}

for _, p := range processes {
cmdline, err := p.CmdlineWithContext(ctx)
if err != nil {
level.Debug(r.logger).Log(
"msg", "could not get cmdline slice for process",
"err", err,
)
continue
}

if !strings.Contains(cmdline, "Xorg") && !strings.Contains(cmdline, "Xvfb") {
continue
}

// We have an Xorg or Xvfb process -- check to make sure it's for our running user
uids, err := p.UidsWithContext(ctx)
if err != nil {
level.Debug(r.logger).Log(
"msg", "could not get uids for process",
"err", err,
)
continue
}
uidMatch := false
for _, procUid := range uids {
if procUid == uid {
uidMatch = true
break
}
}

if uidMatch {
// We have a match! Grab the display value.
// The Xorg process looks like:
// /usr/lib/xorg/Xorg :20 -auth /home/<user>/.Xauthority -nolisten tcp -noreset -logfile /dev/null -verbose 3 -config /tmp/chrome_remote_desktop_j5rldjlk.conf
// The Xvfb process looks like:
// Xvfb :20 -auth /home/<user>/.Xauthority -nolisten tcp -noreset -screen 0 3840x2560x24
cmdlineArgs := strings.Split(cmdline, " ")
if len(cmdlineArgs) < 2 {
// Process is somehow malformed or not what we're looking for -- continue so we can evaluate the following process
continue
}

return cmdlineArgs[1]
}
}

return defaultDisplay
}

func (r *DesktopUsersProcessesRunner) displayFromXwayland(ctx context.Context, uid int32) string {
//For wayland, DISPLAY is not included in loginctl show-session output -- in GNOME,
// Mutter spawns Xwayland and sets $DISPLAY at the same time. Find $DISPLAY by finding
Expand Down

0 comments on commit e21f39f

Please sign in to comment.