diff options
author | Topi Miettinen <toiwoton@gmail.com> | 2021-11-26 15:34:48 +0100 |
---|---|---|
committer | Luca Boccassi <luca.boccassi@gmail.com> | 2021-11-28 19:24:39 +0100 |
commit | ddf127cda450833e5f46fe7a977adf5af10163c8 (patch) | |
tree | e03388893521694ba9c63734ef495de2c16e0691 /src/login | |
parent | Merge pull request #21549 from yuwata/network-netdev-mac-address-none (diff) | |
download | systemd-ddf127cda450833e5f46fe7a977adf5af10163c8.tar.xz systemd-ddf127cda450833e5f46fe7a977adf5af10163c8.zip |
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.
Diffstat (limited to 'src/login')
-rw-r--r-- | src/login/pam_systemd.c | 60 |
1 files changed, 37 insertions, 23 deletions
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c index 1b643d52ca..5bd7efc3e8 100644 --- a/src/login/pam_systemd.c +++ b/src/login/pam_systemd.c @@ -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; + + fd = RET_NERRNO(socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0)); + if (fd < 0) + return fd; - return 0; + 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) |