Commit d4ed9c0c authored by Dimitri John Ledkov 🌈's avatar Dimitri John Ledkov 🌈 Committed by Simon McVittie
Browse files

Import Debian changes 237-3ubuntu10.2

systemd (237-3ubuntu10.2) bionic; urgency=medium

  * logind: backport v238/v239 fixes for handling DRM devices.
    These changes introduce all the fixes that correct handling of open fd's
    related to the DRM devices, as used by for example NVIDIA GPUs. This backport
    includes some refactoring, corrections, and comment updates. This to insure
    that correct history is preserved, code comments match reality, and to ease
    backporting logind fixes in the future SRUs. (LP: #1777099)
  * Disable dh_installinit generation of tmpfiles for the systemd package.
    Replace with a manual safe call to systemd-tmpfiles which will process any
    updates to the tmpfiles shipped by systemd package, taking into account any
    overrides shipped by other packages, sysadmin, or specified in the runtime
    directories. (LP: #1748147)
parent 1be312df
systemd (237-3ubuntu10.2) bionic; urgency=medium
* logind: backport v238/v239 fixes for handling DRM devices.
These changes introduce all the fixes that correct handling of open fd's
related to the DRM devices, as used by for example NVIDIA GPUs. This backport
includes some refactoring, corrections, and comment updates. This to insure
that correct history is preserved, code comments match reality, and to ease
backporting logind fixes in the future SRUs. (LP: #1777099)
* Disable dh_installinit generation of tmpfiles for the systemd package.
Replace with a manual safe call to systemd-tmpfiles which will process any
updates to the tmpfiles shipped by systemd package, taking into account any
overrides shipped by other packages, sysadmin, or specified in the runtime
directories. (LP: #1748147)
-- Dimitri John Ledkov 🌈 <xnox@ubuntu.com> Fri, 22 Jun 2018 13:55:09 +0100
systemd (237-3ubuntu10.1) bionic; urgency=medium
[ Dimitri John Ledkov ]
......
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 26 Feb 2018 18:31:06 +0100
Subject: [PATCH 01/19] logind: trivial improvements
Just some addition whitespace, some additional assert()s, and removal of
redundant variables.
(cherry picked from commit 864fe630a7a1f11b735d818b8c79d2d1068e2f3f)
---
src/login/logind-session-device.c | 51 ++++++++++++++++++++-------------------
src/login/logind.c | 2 +-
2 files changed, 27 insertions(+), 26 deletions(-)
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index 067e67a..b1bac04 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -74,20 +74,25 @@ static int session_device_notify(SessionDevice *sd, enum SessionDeviceNotificati
return r;
switch (type) {
+
case SESSION_DEVICE_RESUME:
r = sd_bus_message_append(m, "uuh", major, minor, sd->fd);
if (r < 0)
return r;
break;
+
case SESSION_DEVICE_TRY_PAUSE:
t = "pause";
break;
+
case SESSION_DEVICE_PAUSE:
t = "force";
break;
+
case SESSION_DEVICE_RELEASE:
t = "gone";
break;
+
default:
return -EINVAL;
}
@@ -120,24 +125,18 @@ static int sd_eviocrevoke(int fd) {
}
static int sd_drmsetmaster(int fd) {
- int r;
-
assert(fd >= 0);
- r = ioctl(fd, DRM_IOCTL_SET_MASTER, 0);
- if (r < 0)
+ if (ioctl(fd, DRM_IOCTL_SET_MASTER, 0) < 0)
return -errno;
return 0;
}
static int sd_drmdropmaster(int fd) {
- int r;
-
assert(fd >= 0);
- r = ioctl(fd, DRM_IOCTL_DROP_MASTER, 0);
- if (r < 0)
+ if (ioctl(fd, DRM_IOCTL_DROP_MASTER, 0) < 0)
return -errno;
return 0;
@@ -146,7 +145,9 @@ static int sd_drmdropmaster(int fd) {
static int session_device_open(SessionDevice *sd, bool active) {
int fd, r;
+ assert(sd);
assert(sd->type != DEVICE_TYPE_UNKNOWN);
+ assert(sd->node);
/* open device and try to get an udev_device from it */
fd = open(sd->node, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
@@ -154,28 +155,27 @@ static int session_device_open(SessionDevice *sd, bool active) {
return -errno;
switch (sd->type) {
+
case DEVICE_TYPE_DRM:
if (active) {
- /* Weird legacy DRM semantics might return an error
- * even though we're master. No way to detect that so
- * fail at all times and let caller retry in inactive
- * state. */
+ /* Weird legacy DRM semantics might return an error even though we're master. No way to detect
+ * that so fail at all times and let caller retry in inactive state. */
r = sd_drmsetmaster(fd);
if (r < 0) {
close_nointr(fd);
return r;
}
- } else {
- /* DRM-Master is granted to the first user who opens a
- * device automatically (ughh, racy!). Hence, we just
- * drop DRM-Master in case we were the first. */
+ } else
+ /* DRM-Master is granted to the first user who opens a device automatically (ughh,
+ * racy!). Hence, we just drop DRM-Master in case we were the first. */
sd_drmdropmaster(fd);
- }
break;
+
case DEVICE_TYPE_EVDEV:
if (!active)
sd_eviocrevoke(fd);
break;
+
case DEVICE_TYPE_UNKNOWN:
default:
/* fallback for devices wihout synchronizations */
@@ -195,26 +195,27 @@ static int session_device_start(SessionDevice *sd) {
return 0;
switch (sd->type) {
+
case DEVICE_TYPE_DRM:
- /* Device is kept open. Simply call drmSetMaster() and hope
- * there is no-one else. In case it fails, we keep the device
- * paused. Maybe at some point we have a drmStealMaster(). */
+ /* Device is kept open. Simply call drmSetMaster() and hope there is no-one else. In case it fails, we
+ * keep the device paused. Maybe at some point we have a drmStealMaster(). */
r = sd_drmsetmaster(sd->fd);
if (r < 0)
return r;
break;
+
case DEVICE_TYPE_EVDEV:
- /* Evdev devices are revoked while inactive. Reopen it and we
- * are fine. */
+ /* Evdev devices are revoked while inactive. Reopen it and we are fine. */
r = session_device_open(sd, true);
if (r < 0)
return r;
- /* For evdev devices, the file descriptor might be left
- * uninitialized. This might happen while resuming into a
- * session and logind has been restarted right before. */
+
+ /* For evdev devices, the file descriptor might be left uninitialized. This might happen while resuming
+ * into a session and logind has been restarted right before. */
safe_close(sd->fd);
sd->fd = r;
break;
+
case DEVICE_TYPE_UNKNOWN:
default:
/* fallback for devices wihout synchronizations */
diff --git a/src/login/logind.c b/src/login/logind.c
index d15d4ce..4fa14b7 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -455,7 +455,7 @@ static int manager_attach_fds(Manager *m) {
sd = hashmap_get(s->devices, &st.st_rdev);
if (!sd) {
- /* Weird we got an fd for a session device which wasn't
+ /* Weird, we got an fd for a session device which wasn't
* recorded in the session state file... */
log_warning("Got fd for missing session device [%u:%u] in session %s",
major(st.st_rdev), minor(st.st_rdev), s->id);
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 26 Feb 2018 18:32:07 +0100
Subject: [PATCH 02/19] logind: rework sd_eviocrevoke()
Let's initialize static variables properly and get rid of redundant
variables.
(cherry picked from commit 5d5330a8e4c6f5926d74f1e0f4bfad2e6355235a)
---
src/login/logind-session-device.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index b1bac04..0992f26 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -107,17 +107,15 @@ static int session_device_notify(SessionDevice *sd, enum SessionDeviceNotificati
}
static int sd_eviocrevoke(int fd) {
- static bool warned;
- int r;
+ static bool warned = false;
assert(fd >= 0);
- r = ioctl(fd, EVIOCREVOKE, NULL);
- if (r < 0) {
- r = -errno;
- if (r == -EINVAL && !warned) {
+ if (ioctl(fd, EVIOCREVOKE, NULL) < 0) {
+
+ if (errno == EINVAL && !warned) {
+ log_warning_errno(errno, "Kernel does not support evdev-revocation: %m");
warned = true;
- log_warning("kernel does not support evdev-revocation");
}
}
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 26 Feb 2018 18:33:05 +0100
Subject: [PATCH 03/19] logind: propagate the right error,
don't make up ENOMEM
(cherry picked from commit e38aa66426ad657b6a9adcbd041fab27e216594b)
---
src/login/logind-session-device.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index 0992f26..30e29e1 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -370,10 +370,8 @@ int session_device_new(Session *s, dev_t dev, bool open_device, SessionDevice **
goto error;
r = hashmap_put(s->devices, &sd->dev, sd);
- if (r < 0) {
- r = -ENOMEM;
+ if (r < 0)
goto error;
- }
if (open_device) {
/* Open the device for the first time. We need a valid fd to pass back
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 26 Feb 2018 18:33:20 +0100
Subject: [PATCH 04/19] logind: let's reduce one level of indentation
(cherry picked from commit d7ba71f4b44a10507c53f64834124545663eee17)
---
src/login/logind-session-device.c | 35 +++++++++++++++++++----------------
1 file changed, 19 insertions(+), 16 deletions(-)
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index 30e29e1..64162f6 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -455,13 +455,14 @@ void session_device_resume_all(Session *s) {
assert(s);
HASHMAP_FOREACH(sd, s->devices, i) {
- if (!sd->active) {
- if (session_device_start(sd) < 0)
- continue;
- if (session_device_save(sd) < 0)
- continue;
- session_device_notify(sd, SESSION_DEVICE_RESUME);
- }
+ if (sd->active)
+ continue;
+
+ if (session_device_start(sd) < 0)
+ continue;
+ if (session_device_save(sd) < 0)
+ continue;
+ session_device_notify(sd, SESSION_DEVICE_RESUME);
}
}
@@ -472,25 +473,27 @@ void session_device_pause_all(Session *s) {
assert(s);
HASHMAP_FOREACH(sd, s->devices, i) {
- if (sd->active) {
- session_device_stop(sd);
- session_device_notify(sd, SESSION_DEVICE_PAUSE);
- }
+ if (!sd->active)
+ continue;
+
+ session_device_stop(sd);
+ session_device_notify(sd, SESSION_DEVICE_PAUSE);
}
}
unsigned int session_device_try_pause_all(Session *s) {
+ unsigned num_pending = 0;
SessionDevice *sd;
Iterator i;
- unsigned int num_pending = 0;
assert(s);
HASHMAP_FOREACH(sd, s->devices, i) {
- if (sd->active) {
- session_device_notify(sd, SESSION_DEVICE_TRY_PAUSE);
- ++num_pending;
- }
+ if (!sd->active)
+ continue;
+
+ session_device_notify(sd, SESSION_DEVICE_TRY_PAUSE);
+ num_pending++;
}
return num_pending;
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 26 Feb 2018 18:33:51 +0100
Subject: [PATCH 05/19] logind: fd 0 is a valid fd
(cherry picked from commit 4c9cb12c0536503979f44d04491ea7bbe118a4cc)
---
src/login/logind-session-device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index 64162f6..f160af1 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -527,7 +527,7 @@ int session_device_save(SessionDevice *sd) {
}
void session_device_attach_fd(SessionDevice *sd, int fd, bool active) {
- assert(fd > 0);
+ assert(fd >= 0);
assert(sd);
assert(sd->fd < 0);
assert(!sd->active);
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 26 Feb 2018 18:34:13 +0100
Subject: [PATCH 06/19] logind: let's pack a few struct fields we can pack
(cherry picked from commit 0410444446c84a759a8f2d0917710849fc91384c)
---
src/login/logind-session-device.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/login/logind-session-device.h b/src/login/logind-session-device.h
index a1cf17a..a9ead7b 100644
--- a/src/login/logind-session-device.h
+++ b/src/login/logind-session-device.h
@@ -39,9 +39,9 @@ struct SessionDevice {
dev_t dev;
char *node;
int fd;
- bool active;
- DeviceType type;
- bool pushed_fd;
+ DeviceType type:3;
+ bool active:1;
+ bool pushed_fd:1;
LIST_FIELDS(struct SessionDevice, sd_by_device);
};
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 26 Feb 2018 18:34:43 +0100
Subject: [PATCH 07/19] logind: check file is device node before using
.st_rdev
(cherry picked from commit 51ead3e3774aa9306d637723d92bbddf2258d2cb)
---
src/login/logind.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/login/logind.c b/src/login/logind.c
index 4fa14b7..bf4e55d 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -453,6 +453,12 @@ static int manager_attach_fds(Manager *m) {
continue;
}
+ if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
+ log_debug("Device fd doesn't actually point to device node: %m");
+ close_nointr(fd);
+ continue;
+ }
+
sd = hashmap_get(s->devices, &st.st_rdev);
if (!sd) {
/* Weird, we got an fd for a session device which wasn't
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 26 Feb 2018 18:34:49 +0100
Subject: [PATCH 08/19] logind: make sure we don't trip up on half-initialized
session devices
Fixes: #8035
(cherry picked from commit 4d219f5343b1924e7c519c2c178aeb5d1a5ab924)
---
src/login/logind-session-device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index f160af1..65b4bb8 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -420,7 +420,7 @@ void session_device_free(SessionDevice *sd) {
session_device_stop(sd);
session_device_notify(sd, SESSION_DEVICE_RELEASE);
- close_nointr(sd->fd);
+ safe_close(sd->fd);
LIST_REMOVE(sd_by_device, sd->device->session_devices, sd);
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 2 Mar 2018 11:55:16 +0100
Subject: [PATCH 09/19] logind: voidify a function we never check the return
value of
(cherry picked from commit a3ddf73c0e4abf8e3c1b8fd91eac469220a5b44b)
---
src/login/logind-session-device.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index 65b4bb8..706245d 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -106,7 +106,7 @@ static int session_device_notify(SessionDevice *sd, enum SessionDeviceNotificati
return sd_bus_send(sd->session->manager->bus, m, NULL);
}
-static int sd_eviocrevoke(int fd) {
+static void sd_eviocrevoke(int fd) {
static bool warned = false;
assert(fd >= 0);
@@ -118,8 +118,6 @@ static int sd_eviocrevoke(int fd) {
warned = true;
}
}
-
- return 0;
}
static int sd_drmsetmaster(int fd) {
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 2 Mar 2018 11:55:33 +0100
Subject: [PATCH 10/19] logind: cast away return value we don't care about
(cherry picked from commit 4804600b6a38994ce4157163fe8af68a0c83e3f0)
---
src/login/logind-session-device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index 706245d..db148d1 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -164,7 +164,7 @@ static int session_device_open(SessionDevice *sd, bool active) {
} else
/* DRM-Master is granted to the first user who opens a device automatically (ughh,
* racy!). Hence, we just drop DRM-Master in case we were the first. */
- sd_drmdropmaster(fd);
+ (void) sd_drmdropmaster(fd);
break;
case DEVICE_TYPE_EVDEV:
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 2 Mar 2018 11:55:51 +0100
Subject: [PATCH 11/19] logind: open device if needed
Fixes: #8291
(cherry picked from commit 4d3900f1b7ccce03366f9a57d259d0735c1cfbcf)
---
src/login/logind-session-device.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index db148d1..b7476e7 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -193,11 +193,19 @@ static int session_device_start(SessionDevice *sd) {
switch (sd->type) {
case DEVICE_TYPE_DRM:
- /* Device is kept open. Simply call drmSetMaster() and hope there is no-one else. In case it fails, we
- * keep the device paused. Maybe at some point we have a drmStealMaster(). */
- r = sd_drmsetmaster(sd->fd);
- if (r < 0)
- return r;
+
+ if (sd->fd < 0) {
+ /* Open device if it isn't open yet */
+ sd->fd = session_device_open(sd, true);
+ if (sd->fd < 0)
+ return sd->fd;
+ } else {
+ /* Device is kept open. Simply call drmSetMaster() and hope there is no-one else. In case it fails, we
+ * keep the device paused. Maybe at some point we have a drmStealMaster(). */
+ r = sd_drmsetmaster(sd->fd);
+ if (r < 0)
+ return r;
+ }
break;
case DEVICE_TYPE_EVDEV:
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 2 Mar 2018 11:56:15 +0100
Subject: [PATCH 12/19] logind: fix typo in comment
(cherry picked from commit 340aff15f89351b118a717967418c218b3dd0279)
---
src/login/logind-session-device.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index b7476e7..c64fb43 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -222,7 +222,7 @@ static int session_device_start(SessionDevice *sd) {
case DEVICE_TYPE_UNKNOWN:
default:
- /* fallback for devices wihout synchronizations */
+ /* fallback for devices without synchronizations */
break;
}
@@ -237,6 +237,7 @@ static void session_device_stop(SessionDevice *sd) {
return;
switch (sd->type) {
+
case DEVICE_TYPE_DRM:
/* On DRM devices we simply drop DRM-Master but keep it open.
* This allows the user to keep resources allocated. The
@@ -244,6 +245,7 @@ static void session_device_stop(SessionDevice *sd) {
* circumventing this. */
sd_drmdropmaster(sd->fd);
break;
+
case DEVICE_TYPE_EVDEV:
/* Revoke access on evdev file-descriptors during deactivation.
* This will basically prevent any operations on the fd and
@@ -251,6 +253,7 @@ static void session_device_stop(SessionDevice *sd) {
* protection this way. */
sd_eviocrevoke(sd->fd);
break;
+
case DEVICE_TYPE_UNKNOWN:
default:
/* fallback for devices without synchronization */
@@ -468,6 +471,7 @@ void session_device_resume_all(Session *s) {
continue;
if (session_device_save(sd) < 0)
continue;
+
session_device_notify(sd, SESSION_DEVICE_RESUME);
}
}
From: Alan Jenkins <alan.christopher.jenkins@gmail.com>
Date: Sat, 3 Mar 2018 18:37:50 +0000
Subject: [PATCH 13/19] login: fix FDNAME in call to sd_pid_notify_with_fds()
$ git grep FDNAME
logind-session-device.c: ... "FDNAME=session-", sd->session->id);
logind-session-device.c: ... "FDNAME=session", sd->session->id);
Oops.
Fixes #8343. Or at least a more minimal reproducer. Xorg still
dies when logind is restarted, but the Xorg message says this
is entirely deliberate.
(This could also be the reason I hit #8035, instead of the race
condition I originally suggested).
(cherry picked from commit b5cdfa40ca6aae5e98a69da7a8b350215f807649)
---
src/login/logind-session-device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c