1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-27 18:55:40 +03:00

pam_systemd: Check also abstract socket for X11

It seems that `pam_systemd` was the only thing left that wanted to use sockets
in file system path `/tmp/.X11-unix/X*`. X11 apps actually prefer using the
abstract socket version.

This allows running Xserver with `-nolisten tcp -nolisten unix`, which makes
the server only listen to an abstract socket.

Also in my setup, Xserver is running as a separate system service instead of
starting from display manager service, and now `PrivateTmp=yes` can be used for
both. The file system of the display manager service is inherited by user apps
and now their `/tmp` will be separate from `/tmp` of PID1 namespace as well as
`/tmp` of Xserver.
This commit is contained in:
Topi Miettinen 2021-11-26 16:34:48 +02:00 committed by Luca Boccassi
parent 64a05587ce
commit ddf127cda4

View File

@ -199,35 +199,60 @@ static bool display_is_local(const char *display) {
display[1] <= '9';
}
static int socket_from_display(const char *display, char **path) {
static int socket_from_display(const char *display) {
_cleanup_free_ char *f = NULL;
size_t k;
char *f, *c;
char *c;
union sockaddr_union sa;
socklen_t sa_len;
_cleanup_close_ int fd = -1;
int r;
assert(display);
assert(path);
if (!display_is_local(display))
return -EINVAL;
k = strspn(display+1, "0123456789");
f = new(char, STRLEN("/tmp/.X11-unix/X") + k + 1);
/* Try abstract socket first. */
f = new(char, STRLEN("@/tmp/.X11-unix/X") + k + 1);
if (!f)
return -ENOMEM;
c = stpcpy(f, "/tmp/.X11-unix/X");
c = stpcpy(f, "@/tmp/.X11-unix/X");
memcpy(c, display+1, k);
c[k] = 0;
*path = f;
r = sockaddr_un_set_path(&sa.un, f);
if (r < 0)
return r;
sa_len = r;
return 0;
fd = RET_NERRNO(socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0));
if (fd < 0)
return fd;
r = RET_NERRNO(connect(fd, &sa.sa, sa_len));
if (r >= 0)
return TAKE_FD(fd);
if (r != -ECONNREFUSED)
return r;
/* Try also non-abstract socket. */
r = sockaddr_un_set_path(&sa.un, f + 1);
if (r < 0)
return r;
sa_len = r;
r = RET_NERRNO(connect(fd, &sa.sa, sa_len));
if (r >= 0)
return TAKE_FD(fd);
return r;
}
static int get_seat_from_display(const char *display, const char **seat, uint32_t *vtnr) {
union sockaddr_union sa;
socklen_t sa_len;
_cleanup_free_ char *p = NULL, *sys_path = NULL, *tty = NULL;
_cleanup_free_ char *sys_path = NULL, *tty = NULL;
_cleanup_close_ int fd = -1;
struct ucred ucred;
int v, r;
@ -242,20 +267,9 @@ static int get_seat_from_display(const char *display, const char **seat, uint32_
* the seat and the virtual terminal. Sounds ugly, is only
* semi-ugly. */
r = socket_from_display(display, &p);
if (r < 0)
return r;
r = sockaddr_un_set_path(&sa.un, p);
if (r < 0)
return r;
sa_len = r;
fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
fd = socket_from_display(display);
if (fd < 0)
return -errno;
if (connect(fd, &sa.sa, sa_len) < 0)
return -errno;
return fd;
r = getpeercred(fd, &ucred);
if (r < 0)