summaryrefslogtreecommitdiffstats
path: root/src/login
diff options
context:
space:
mode:
authorTopi Miettinen <toiwoton@gmail.com>2021-11-26 15:34:48 +0100
committerLuca Boccassi <luca.boccassi@gmail.com>2021-11-28 19:24:39 +0100
commitddf127cda450833e5f46fe7a977adf5af10163c8 (patch)
treee03388893521694ba9c63734ef495de2c16e0691 /src/login
parentMerge pull request #21549 from yuwata/network-netdev-mac-address-none (diff)
downloadsystemd-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.c60
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)